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