Fondamentalement, je dois configurer CI/CD avec le code source de bitbucket en conteneurs ECS. Je souhaite utiliser CodePipline pour déployer une nouvelle image ECR sur ECS.
Actuellement, il n'y a pas d'option dans AWS CodePipline pour spécifier bitbucket comme source. Cependant, j'ai réussi à configurer CodeBuild avec des webhooks pour qu'il crée un fichier docker et le pousse vers ECR sur chaque branche Push to release.
Je souhaite configurer ECR comme étape "source" dans CodePipline et le déployer sur le cluster/service ECS existant afin que le déploiement soit automatisé.
Malheureusement, la configuration de base et le chaînage d'artefacts résultent si l'erreur suivante dans l'étape de déploiement:
Invalid action configuration
The image definition file imageDetail.json contains invalid JSON format
Bien que l'étape "Amazon ECR" fournisse imageDetail.json comme un artefact de sortie, il ne semble pas être attendu pour le fournisseur de déploiement "Amazon ECS". Existe-t-il un moyen rationnel de contourner ce problème?
Je suis conscient qu'il est possible de configurer CI/CD avec bitbucket + API Gateway/Lambda + CodePipeline, je considère également l'utilisation de CodeCommit au lieu de bitbucket comme dépôt source - j'espère néanmoins qu'il existe une solution élégante possible pour utiliser bitbucket avec CodePipeline directement.
UPD: Je me suis retrouvé avec une configuration plutôt sympa, décrite dans this blogpost: l'idée générale est de permettre à CodeBuild de téléchargez le code source de bitbucket vers S3, puis utilisez CodePipeline avec S3 comme source pour déployer une nouvelle image docker sur ECR et publier une nouvelle révision de définition de tâche dans le cluster ECS. S3 est toujours au-dessus et je cherche une solution plus élégante pour la tâche.
J'ai récemment dû résoudre un problème similaire où je voulais utiliser ECR comme source de mon pipeline et lui faire déployer l'image sur ECS. La solution que j'ai trouvée a été de créer 3 étapes:
Voici le fichier buildspec.yml que j'utilise comme étape de génération:
version: 0.2
phases:
install:
runtime-versions:
python: 3.7
build:
commands:
- PHP_REPOSITORY_URI=$(cat imageDetail.json | python -c "import sys, json; print(json.load(sys.stdin)['ImageURI'].split('@')[0])")
- IMAGE_TAG=$(cat imageDetail.json | python -c "import sys, json; print(json.load(sys.stdin)['ImageTags'][0])")
- echo $PHP_REPOSITORY_URI:$IMAGE_TAG
post_build:
commands:
- echo Writing image definitions file...
- printf '[{"name":"container","imageUri":"%s"}]' $PHP_REPOSITORY_URI:$IMAGE_TAG > imagedefinitions.json
artifacts:
files: imagedefinitions.json
Fondamentalement, cela permet de lire le fichier imageDetail.json et d'extraire l'URL et le TAG du référentiel ECR et de générer un fichier json formaté pour l'étape ECS Deploy, qui n'est qu'une étape standard sans personnalisation.
J'ai eu un cas d'utilisation similaire et j'ai rencontré le même problème. Une réponse longue avec une solution qui répond à mon cas d'utilisation ...
Selon cela doco officiel d'AWS ECS Standard Deployment attend un fichier - imagedefinitions.json qui fournit le nom du conteneur et l'URI de l'image. Il devrait ressembler à:
[
{
"name": "sample-app",
"imageUri": "11111EXAMPLE.dkr.ecr.us-west-2.amazonaws.com/ecs-repo:latest"
}
]
Mais la source ECR produit un artefact de sortie appelé exemple imageDetail.json ci-dessous. Cela ne correspond pas au format d'entrée attendu pour ECS Standard Deploy aka imagedefinitions.json - qui inclut le nom du conteneur (nom) et le déploiement échoue avec un message comme Deploy Failure :
{
"ImageSizeInBytes": "44728918",
"ImageDigest": "sha256:EXAMPLE11223344556677889900bfea42ea2d3b8a1ee8329ba7e68694950afd3",
"Version": "1.0",
"ImagePushedAt": "Mon Jan 21 20:04:00 UTC 2019",
"RegistryId": "EXAMPLE12233",
"RepositoryName": "dk-image-repo",
"ImageURI": "ACCOUNTID.dkr.ecr.us-west-2.amazonaws.com/dk-image-repo@sha256:example3",
"ImageTags": [
"latest"
]
}
L'approche que j'ai adoptée pour résoudre ce problème est la suivante:
Dans l'étape Source: En plus de la source ECR, j'ai ajouté une source de s3 qui contient imagedefinitions.json dans un Zip.
Dans l'action de l'étape ECS Deploy, je me réfère à l'artefact de sortie de la source s3 qui contient imagedefinitions.json au format que ECS Standard Deploy comprend.
Remarque: Le fichier imagedefinitions.json est statique dans le compartiment s3 et fait toujours référence à la dernière balise sur ladite image. Donc, dans le compartiment de définitions d'images QA, je me retrouverai avec un fichier Zip de définitions d'images, c'est-à-dire un par instance du service Fargate.
J'ai exporté mon pipeline ici pour référence générale:
{
"pipeline": {
"roleArn": "arn:aws:iam::ACCOUNTID:role/service-role/AWSCodePipelineServiceRole-REGION-PIPELINENAME",
"stages": [
{
"name": "Source",
"actions": [
{
"inputArtifacts": [],
"name": "Source",
"region": "REGION",
"actionTypeId": {
"category": "Source",
"owner": "AWS",
"version": "1",
"provider": "ECR"
},
"outputArtifacts": [
{
"name": "SourceArtifact"
}
],
"configuration": {
"ImageTag": "latest",
"RepositoryName": "PIPELINENAME"
},
"runOrder": 1
},
{
"inputArtifacts": [],
"name": "sourceimagedeffile",
"region": "REGION",
"actionTypeId": {
"category": "Source",
"owner": "AWS",
"version": "1",
"provider": "S3"
},
"outputArtifacts": [
{
"name": "PIPELINENAME-imagedefjson"
}
],
"configuration": {
"S3Bucket": "BUCKETNAME",
"PollForSourceChanges": "true",
"S3ObjectKey": "PIPELINENAME.Zip"
},
"runOrder": 1
}
]
},
{
"name": "Deploy",
"actions": [
{
"inputArtifacts": [
{
"name": "PIPELINENAME-imagedefjson"
}
],
"name": "Deploy",
"region": "REGION",
"actionTypeId": {
"category": "Deploy",
"owner": "AWS",
"version": "1",
"provider": "ECS"
},
"outputArtifacts": [],
"configuration": {
"ClusterName": "FARGATECLUSTERNAME",
"ServiceName": "PIPELINENAME",
"FileName": "imageDetail.json"
},
"runOrder": 1
}
]
}
],
"artifactStore": {
"type": "S3",
"location": "codepipeline-REGION-555869339681"
},
"name": "PIPELINENAME"
}