CodePipeline:ECR源+ ECS部署配置

时间:2019-03-25 14:16:33

标签: amazon-ecs aws-codepipeline aws-codebuild aws-ecr

基本上,我需要使用ECS容器的Bitbucket源代码配置CI / CD。我想使用CodePipline将新的ECR映像部署到ECS。

当前,AWS CodePipline中没有选项将bitbucket指定为源。但是,我设法通过Webhooks配置CodeBuild,因此它会构建docker文件,并在每次发布发布分支时将其推送到ECR。

我想将ECR配置为CodePipline中的“源”阶段,并将其部署到现有的ECS集群/服务中,因此部署将实现自动化。

  • 我在源阶段将“ Amazon ECR”指定为具有“ image_details”输出工件的操作提供程序。
  • 我将“ Amazon ECS”(不是“ Amazon ECS(蓝色/绿色)”)指定为部署阶段的操作提供程序,并以“ image_details”作为输入工件

codepipeline_settings

不幸的是,如果在部署步骤中出现以下错误,则会得到基本配置和工件链接:

Invalid action configuration
The image definition file imageDetail.json contains invalid JSON format

尽管“ Amazon ECR”阶段将imageDetail.json作为输出工件提供,但“ Amazon ECS”部署提供程序似乎并不期望这样做。有什么合理的方法解决这个问题吗?

我知道,可以使用bitbucket + API网关/ Lambda + CodePipeline配置CI / CD,我也考虑使用CodeCommit代替bitbucket作为源存储库-仍然,希望有一种可能的优雅解决方案直接将Bitbucket与CodePipeline结合使用。

UPD: 我最终获得了不错的配置,如this博客中所述:总体思路是允许CodeBuild将源代码从bitbucket上传到S3,然后将CodePipeline与S3一起用作将新docker映像部署到ECR的源并在ECS集群中发布新的任务定义修订。 S3仍在开销中,我正在为该任务寻找更优雅的解决方案。

2 个答案:

答案 0 :(得分:5)

我有一个类似的用例,遇到了同样的问题。解决我的用例的解决方案有点长答案...

  1. 用例:工具帐户具有CodePipeline,由CodePipeline和Docker推送至QA帐户ECR。该图像将具有2个标签-“提交哈希”和“最新”。质量检查帐户有一个管道,该管道在提供新映像时执行,该管道将新映像部署到质量检查帐户中的Fargate群集中。
  2. 部署平台: Amazon ECS标准部署操作。
  3. 来源: ECR。
  4. 问题原因: ECR源的输出工件 正确 仅包含有关图像的信息,但不包含容器名称,即ECS Standard Deploy期望。
  5. 对AWS的建议:考虑到使用ECR作为ECS来源的流行方案,我们可以提出一个有能力(可选)在输出工件中添加容器名称的论点-这将允许生成可接受作为ECS Standard Deploy输入的输出工件。

根据此official doco from AWS,ECS标准部署需要一个- imagedefinitions.json文件,该文件提供容器名称和图像URI。它应类似于:

[
  {
    "name": "sample-app",
    "imageUri": "11111EXAMPLE.dkr.ecr.us-west-2.amazonaws.com/ecs-repo:latest"
  }
]

但是,ECR源会在下面生成一个名为imageDetail.json的输出工件。这与ECS Standard Deploy aka imagedefinitions.json的预期输入格式不匹配-包括容器名称(名称),并且部署失败,并显示类似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"
    ]
}

我用来解决此问题的方法是:

  1. 在Source阶段:除了ECR源,我还从s3中添加了一个源,该源在zip中包含imagedefinitions.json。

  2. 在ECS Deploy阶段操作中,我指的是s3源中的Output工件,其中包含imagedefinitions.json,其格式为ECS Standard Deploy可以理解。

注意:imagedefinitions.json在s3存储桶中是静态的,并且始终引用所述图像上的最新标记。因此,在“质量检查图像定义”存储区中,我将获得一个图像定义zip,即每个Fargate服务实例一个。

我已在此处导出管道以供一般参考:

{
"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"
}

答案 1 :(得分:1)

最近,我不得不解决一个类似的问题,我想使用ECR作为管道的源并将其部署到ECS。我发现的解决方案是创建3个阶段:

  • 来源:ECR
  • 构建:用于将ECR工件转换为Deploy阶段可以理解的工件的自定义代码
  • 部署:至ECS

这是我正在用作构建阶段的buildspec.yml文件:

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

基本上,这是读取imageDetail.json文件并提取ECR存储库URL和TAG并输出为ECS Deploy阶段格式化的json文件,这是没有自定义的标准阶段。