CodePipeline:ECR 源 + ECS 部署配置

Posted

技术标签:

【中文标题】CodePipeline:ECR 源 + ECS 部署配置【英文标题】:CodePipeline: ECR source + ECS deploy configuration 【发布时间】:2019-08-15 19:35:55 【问题描述】:

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

目前,AWS CodePipline 中没有将 bitbucket 指定为源的选项。但是,我设法使用 webhook 配置 CodeBuild,以便它构建 docker 文件并在每次推送到发布分支时将其推送到 ECR。

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

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

很遗憾,如果在部署步骤中出现以下错误,则会导致基本配置和工件链接:

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

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

我知道,可以使用 bitbucket + API Gateway/Lambda + CodePipeline 配置 CI/CD,我还考虑使用 CodeCommit 而不是 bitbucket 作为源存储库 - 不过,希望有一个可能的优雅解决方案直接将 bitbucket 与 CodePipeline 一起使用。

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

【问题讨论】:

嗨,谢尔盖,您有没有机会找出发生这种情况的原因,我们无法将 ECR 设置为源并将 docker 映像部署到 ECS? imageDetail.json 也遇到过同样的问题? @statut 嗨!原来的问题仍然是开放的。我决定改用另一个管道。这个想法在lgallardo.com/2018/09/07/codepipeline-bitbucket 中有描述。根据我的观察,ECR 的 imageDetail.json 输出不能用于部署,所以我可能会尝试使用“Invoke”lambda 阶段将 imageDetail.json 转换为以下格式的 imagedefinitions.json:["name":""," imageUri":""] 谢谢!提供的格式帮助了我 @statut 如果您提供有关最终解决方案的一些详细信息,我们将不胜感激,以便我们将其标记为已接受的答案。会对社区有所帮助。 整个最初的问题是 CodePipeline 不支持 bitbucket 作为源提供程序。 AWS 现在已添加此功能:aws.amazon.com/blogs/devops/… - 然而,它有其局限性,因此该线程中讨论的解决方案对于某些商业开发场景仍然有用。 【参考方案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 文件,这只是一个没有自定义的标准阶段。

【讨论】:

我认为是这样,将对其进行测试并尽快接受答案! 回到这个问题需要时间,但我终于设法使用您的脚本创建了一个工作管道。谢谢! 我遇到了类似的问题,你能分享示例管道导出输出吗 太棒了。您能否分享 imagedefinitions.json 文件以供我们参考? - @carlos-barros @Pushparaj imagedefinitions.json 文件由上面的 buildspec.yml 脚本生成,仅包含以下内容:["name":"container","imageUri":"123456.dkr.ecr.us-east-1.amazonaws.com/some/image:tag"] imageUri 是根据从 imageDetail 读取的存储库 uri 和图像标签动态生成的.json【参考方案2】:

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

    用例: Tools Account 具有 CodePipeline,它执行 CodeBuild 和 docker 推送到 QA Accounts ECR。该图像将有 2 个标签 - “提交哈希”和“最新”。 QA 帐户有一个管道,当新映像可用时执行,此管道将新映像部署到 QA 帐户的 Fargate 集群中。 部署平台: Amazon ECS 标准部署操作。 来源: ECR。 问题原因: ECR Source 的输出工件正确仅包含有关图像的信息,不包含 ECS 期望的容器名称标准部署。 对 AWS 的建议: 鉴于使用 ECR 作为 ECS 源的流行场景,我们可以提出一个参数,即有能力(可选)在输出工件中添加容器名称 - 这将允许生成输出工件可以作为 ECS 标准部署的输入。

根据这个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"
    ]

我采取的解决方法是:

    在 Source 阶段:除了 ECR 源之外,我还添加了一个来自 s3 的源,其中包含 zip 中的 imagedefinitions.json。

    在 ECS 部署阶段操作中,我指的是来自 s3 源的输出工件,其中包含 ECS 标准部署可以理解的格式的 imagedefinitions.json。

注意: imagedefinitions.json 在 s3 存储桶中是静态的,并且总是引用该图像上的最新标签。因此,在 QA 图像定义存储桶中,我最终会得到一个图像定义 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"

【讨论】:

您是否也在支持或 ECR/CodePipeline git 上将此建议发布到 AWS?看起来实现起来并没有那么大的功能。 @SergeyNikitin - 我已经在 ECR 论坛上发布了这个。 Link here如果你想关注。 谢谢,我遇到了这个问题。静态 S3 zip 成功了! 刚刚使用静态 S3,谢谢!在您导出的管道中,我将 "FileName": "imageDetail.json" 更改为 "FileName": "imagedefinitions.json" 并且我的静态 S3 文件包含一个 imagedefinitions.json 文件 - 因为这更清楚它正在作用于 imagedef 文件。

以上是关于CodePipeline:ECR 源 + ECS 部署配置的主要内容,如果未能解决你的问题,请参考以下文章

CodePipeline:如何将 ECR 与 Elastic Beanstalk 集成?

AWS ECS Blue/Green CodePipeline:尝试读取图像工件时出现异常

AWS CodePipeline:如何使 CodeBuild 构建的 ECR 映像作为剩余阶段的工件?

将新映像推送到 ECR 存储库时如何自动部署到 ECS Fargate

如何在 ECR 源管道中向 CodeDeploy 提供 AppSpec 和任务定义

ECR 映像移动到 ECS(Docker、Gitlab)