web-dev-qa-db-fra.com

CodePipeline: configuration ECR source + ECS deploy

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é.

  • J'ai spécifié "Amazon ECR" comme fournisseur d'action avec l'artefact de sortie "image_details" à l'étape source.
  • J'ai spécifié "Amazon ECS" (pas "Amazon ECS (bleu/vert)") comme fournisseur d'action pour l'étape de déploiement avec "image_details" comme artefact d'entrée

codepipeline_settings

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.

11
Sergey Nikitin

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:

  • Source: ECR
  • Build: Code personnalisé pour convertir l'artefact ECR en un artefact que la phase Deploy comprendrait
  • Déployer: Vers ECS

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.

8
Carlos Barros

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 ...

  1. Cas d'utilisation: Le compte Tools a le CodePipeline qui fait l'ECR CodeBuild et Docker Push to QA Accounts. L'image aura 2 balises - Un "hachage de validation" et "dernier". Le compte QA possède un pipeline qui s'exécute lorsqu'une nouvelle image est mise à disposition et ce pipeline déploie la nouvelle image dans le cluster Fargate du compte QA.
  2. Plateforme de déploiement: Actions de déploiement standard Amazon ECS.
  3. Source: ECR.
  4. Cause du problème: Artefact de sortie de la source ECR à juste titre contient uniquement les informations sur l'image et n'inclut pas le nom du conteneur attendu par ECS Standard Deploy.
  5. Suggestion à AWS: Étant donné le scénario populaire d'utilisation d'ECR comme source pour ECS, nous pouvons faire valoir la possibilité (facultative) d'ajouter le nom du conteneur dans l'artefact de sortie - Cela permettrait la génération d'artefacts de sortie qui sont acceptables comme entrée pour ECS Standard Deploy.

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:

  1. Dans l'étape Source: En plus de la source ECR, j'ai ajouté une source de s3 qui contient imagedefinitions.json dans un Zip.

  2. 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"
}
6
kiran01bm