跨账户或区域复制已筛选的 Amazon ECR 容器映像 - AWS Prescriptive Guidance

本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。

跨账户或区域复制已筛选的 Amazon ECR 容器映像

由 Abdal Garuba (AWS) 编写

环境:生产

技术:容器和微服务; DevOps

AWS 服务:亚马逊 EC2 容器注册表;亚马逊;AWS CloudWatch CodeBuild;AWS Identity and Access Management;AWS CLI

Summary

Amazon Elastic Container Registry (Amazon ECR) 可以使用跨区域跨账户复制功能,跨 Amazon Web Services (AWS) 区域和 Amazon Web Services account 本地复制映像存储库中的所有容器映像。(有关更多信息,请参阅 AWS Blog 文章 Amazon ECR 中的跨区域复制已实现。) 但是,无法根据任何标准筛选在 AWS 区域或账户之间复制的映像。 

此示例介绍了如何根据映像标签模式在 Amazon Web Services account 和区域之间复制存储在 Amazon ECR 中的容器映像。该模式使用 Amazon CloudWatch Events 来监听具有预定义自定义标签的图像的推送事件。推送事件启动一个 AWS CodeBuild 项目并将图像详细信息传递给该项目。该 CodeBuild 项目根据提供的详细信息将图像从源 Amazon ECR 注册表复制到目标注册表。

此模式跨账户复制具有特定标签的映像。例如您可使用此模式仅将可用于生产的安全映像复制到生产 Amazon Web Services account。在开发账户中,在对映像进行全面测试后,您可向安全映像添加预定义的标签,并使用此模式中的步骤将标记的映像复制到生产账户。

先决条件和限制

先决条件

  • 用于源和目标 Amazon ECR 注册表的有效 Amazon Web Services account

  • 此模式所用工具的管理权限

  • Docker 已安装在本地计算机上以进行测试

  • AWS 命令行界面(AWS CLI),用于对 Amazon ECR 进行身份验证

限制

  • 此模式仅在一个 AWS 区域中监视源注册表的推送事件。您可将此模式部署到其他区域,以监视这些区域中的注册表。

  • 在这种模式中,一个 Amazon CloudWatch Events 规则监听单个图像标签模式。如果要检查多个模式,则可以添加事件来监听其他映像标签模式。

架构

目标架构

用于跨账户和地区复制经过筛选的 Amazon ECR 容器镜像的架构。

自动化和扩缩

这种模式可以通过基础设施即代码(IaC)脚本实现自动化,并可以大规模部署。要使用 AWS CloudFormation 模板部署此模式,请下载附件并按照 “其他信息” 部分的说明进行操作。

您可以将多个 Amazon Events CloudWatch 事件(具有不同的自定义事件模式)指向同一 AWS CodeBuild 项目以复制多个图像标签模式,但您需要按如下方式更新buildspec.yaml文件(包含在附件和 “工具” 部分中)中的辅助验证以支持多种模式。

... if [[ ${IMAGE_TAG} != release-* ]]; then ...

工具

Amazon 服务

  • IAM – AWS Identity and Access Management (IAM)让您安全地控制对 Amazon Web Services 和资源的访问。在这种模式中,您需要创建跨账户 IAM 角色,AWS 在 CodeBuild 将容器映像推送到目标注册表时将担任该角色。

  • Amazon ECR – Amazon Elastic Container Registry (Amazon ECR) 是一个完全托管式容器注册表,可以轻松地在任何地方存储、管理、共享和部署容器映像和构件。将图像推送到源注册表的操作会将系统事件详细信息发送到 Amazon Events 获取 CloudWatch 的事件总线。

  • AWS CodeBuild — AWS CodeBuild 是一项完全托管的持续集成服务,它为执行编译源代码、运行测试和生成准备部署的工件等任务提供计算能力。此模式使用 AWS CodeBuild 执行从源 Amazon ECR 注册表到目标注册表的复制操作。

  • CloudWatch 事件 — Amazon CloudWatch Events 提供一系列描述了 AWS 资源变化的系统事件。此模式使用规则将 Amazon ECR 推送操作与特定映像标签模式进行匹配。

工具

  • Docker CLI – Docker 是一款可以更轻松地创建和管理容器的工具。容器将应用程序及其所有依赖项打包到一个单元或者包,可以轻松部署在支持容器运行时系统的任何平台上。

代码

您可通过两种方式实现此模式:

  • 自动设置:部署附件中提供的两个 AWS CloudFormation 模板。有关说明,请参阅其他信息部分。

  • 手动设置:按照操作说明部分的步骤执行操作。 

示例 buildspec.yaml

如果您使用的是随此模式提供的 CloudFormation 模板,则该buildspec.yaml文件将包含在 CodeBuild 资源中。

version: 0.2 env: shell: bash phases: install: commands: - export CURRENT_ACCOUNT=$(echo ${CODEBUILD_BUILD_ARN} | cut -d':' -f5) - export CURRENT_ECR_REGISTRY=${CURRENT_ACCOUNT}.dkr.ecr.${AWS_REGION}.amazonaws.com - export DESTINATION_ECR_REGISTRY=${DESTINATION_ACCOUNT}.dkr.ecr.${DESTINATION_REGION}.amazonaws.com pre_build: on-failure: ABORT commands: - echo "Validating Image Tag ${IMAGE_TAG}" - | if [[ ${IMAGE_TAG} != release-* ]]; then aws codebuild stop-build --id ${CODEBUILD_BUILD_ID} sleep 60 exit 1 fi - aws ecr get-login-password --region ${AWS_REGION} | docker login -u AWS --password-stdin ${CURRENT_ECR_REGISTRY} - docker pull ${CURRENT_ECR_REGISTRY}/${REPO_NAME}:${IMAGE_TAG} build: commands: - echo "Assume cross-account role" - CREDENTIALS=$(aws sts assume-role --role-arn ${CROSS_ACCOUNT_ROLE_ARN} --role-session-name Rolesession) - export AWS_DEFAULT_REGION=${DESTINATON_REGION} - export AWS_ACCESS_KEY_ID=$(echo ${CREDENTIALS} | jq -r '.Credentials.AccessKeyId') - export AWS_SECRET_ACCESS_KEY=$(echo ${CREDENTIALS} | jq -r '.Credentials.SecretAccessKey') - export AWS_SESSION_TOKEN=$(echo ${CREDENTIALS} | jq -r '.Credentials.SessionToken') - echo "Logging into cross-account registry" - aws ecr get-login-password --region ${DESTINATION_REGION} | docker login -u AWS --password-stdin ${DESTINATION_ECR_REGISTRY} - echo "Check if Destination Repository exists, else create" - | aws ecr describe-repositories --repository-names ${REPO_NAME} --region ${DESTINATION_REGION} \ || aws ecr create-repository --repository-name ${REPO_NAME} --region ${DESTINATION_REGION} - echo "retag image and push to destination" - docker tag ${CURRENT_ECR_REGISTRY}/${REPO_NAME}:${IMAGE_TAG} ${DESTINATION_ECR_REGISTRY}/${REPO_NAME}:${IMAGE_TAG} - docker push ${DESTINATION_ECR_REGISTRY}/${REPO_NAME}:${IMAGE_TAG}

操作说明

任务描述所需技能

创建 “ CloudWatch 活动” 角色。

在源 AWS 账户中,创建一个 IAM 角色供亚马逊 CloudWatch 活动代替。该角色应具有启动 AWS CodeBuild 项目的权限。

要使用 AWS CLI 创建角色,请按照 IAM 文档中的说明进行操作。

示例信任策略(trustpolicy.json): 

{ "Version": "2012-10-17", "Statement": { "Effect": "Allow", "Principal": {"Service": "events.amazonaws.com"}, "Action": "sts:AssumeRole" } }

示例权限策略(permissionpolicy.json):

{ "Version": "2012-10-17", "Statement": { "Effect": "Allow", "Action": "codebuild:StartBuild", "Resource": "<CodeBuild Project ARN>" } }
AWS 管理员、AWS DevOps、AWS 系统管理员、云管理员、云架构师、 DevOps 工程师

创建 CodeBuild 角色。

按照 IAM 文档中的说明创建一个 IAM 角色让 AWS CodeBuild 代替。角色还必须具有以下权限:

示例信任策略(trustpolicy.json):

{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Service": "codebuild.amazonaws.com" }, "Action": "sts:AssumeRole" } ] }

示例权限策略(permissionpolicy.json):

{ "Version": "2012-10-17", "Statement": [ { "Action": [ "codebuild:StartBuild", "codebuild:StopBuild", "codebuild:Get*", "codebuild:List*", "codebuild:BatchGet*" ], "Resource": "*", "Effect": "Allow" }, { "Action": [ "logs:CreateLogGroup", "logs:CreateLogStream", "logs:PutLogEvents" ], "Resource": "*", "Effect": "Allow" }, { "Action": "sts:AssumeRole", "Resource": "<ARN of destination role>", "Effect": "Allow", "Sid": "AssumeCrossAccountArn" } ] }

按如下方式将托管策略 AmazonEC2ContainerRegistryReadOnly 附加到 CLI 命令:

~$ aws iam attach-role-policy \ --policy-arn arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly \ --role-name <name of CodeBuild Role>
AWS 管理员、AWS DevOps、AWS 系统管理员、云管理员、云架构师、 DevOps 工程师

创建跨账户角色。

在目标 AWS 账户中,为源账户的 AWS CodeBuild 角色创建一个 IAM 角色。跨账户角色应允许容器映像创建新的存储库并将容器映像上传至 Amazon ECR。

要使用 AWS CLI 创建 IAM 角色,请按照 IAM 文档中的说明进行操作。 

要允许上一步 CodeBuild 中的 AWS 项目,请使用以下信任策略:

{ "Version": "2012-10-17", "Statement": { "Effect": "Allow", "Principal": { "AWS": "<ARN of source codebuild role>" }, "Action": "sts:AssumeRole" } }

要允许上一步中的 AWS CodeBuild 项目将图像保存在目标注册表中,请使用以下权限策略:

{ "Version": "2012-10-17", "Statement": [ { "Action": [ "ecr:GetDownloadUrlForLayer", "ecr:BatchCheckLayerAvailability", "ecr:PutImage", "ecr:InitiateLayerUpload", "ecr:UploadLayerPart", "ecr:CompleteLayerUpload", "ecr:GetRepositoryPolicy", "ecr:DescribeRepositories", "ecr:GetAuthorizationToken", "ecr:CreateRepository" ], "Resource": "*", "Effect": "Allow" } ] }
AWS 管理员、AWS DevOps、云管理员、云架构师、 DevOps 工程师、AWS 系统管理员
任务描述所需技能

创建 CodeBuild 项目。

按照 AWS CodeBuild 文档中的说明在源账户中创建 AWS CodeBuild 项目。该项目应与源注册表位于同一区域。 

项目配置如下:

  • 环境类型:LINUX CONTAINER

  • 服务角色:CodeBuild Role

  • 特权模式:true

  • 环境映像:aws/codebuild/standard:x.x(使用最新可用映像)

  • 环境变量:

    • CROSS_ACCOUNT_ROLE_ARN:跨账户角色的 Amazon 资源名称(ARN)

    • DESTINATION_REGION:跨账户区域的名称

    • DESTINATION_ACCOUNT:目标账户的号码

  • 构建规范:使用工具部分中列出的 buildspec.yaml 文件。

AWS 管理员、AWS DevOps、AWS 系统管理员、云管理员、云架构师、 DevOps 工程师
任务描述所需技能

创建事件规则。

由于该模式使用内容筛选功能,因此您需要使用 Amazon 创建事件 EventBridge。按照 EventBridge 文档中的说明创建事件和目标,并进行一些修改:

  • 对于 Define pattern(定义模式),选择 Event pattern(事件模式),然后选择 Custom pattern(自定义模式)

  • 将以下自定义事件模式示例代码复制到提供的文本框中:

    {   "source": ["aws.ecr"],   "detail-type": ["ECR Image Action"],   "detail": {     "action-type": ["PUSH"],     "result": ["SUCCESS"],     "image-tag": [{ "prefix": "release-"}]   } }
  • 对于选择目标,选择 AWS CodeBuild 项目,然后粘贴您在上一篇长篇故事中创建的 AWS CodeBuild 项目的 ARN。

  • 对于 Configure input(配置输入),选择 Input Transformer(输入转换器)

    • 输入路径文本框,粘贴:

      {"IMAGE_TAG":"$.detail.image-tag","REPO_NAME":"$.detail.repository-name"}
    • 输入模板文本框,粘贴:

      {"environmentVariablesOverride": [ {"name": "IMAGE_TAG", "value":<IMAGE_TAG>},{"name":"REPO_NAME","value":<REPO_NAME>}]}
  • 选择使用现有角色,然后选择您之前在创建 IAM 角色长篇故事中创建 CloudWatch 的事件角色的名称。

AWS 管理员、AWS DevOps、AWS 系统管理员、云管理员、云架构师、 DevOps 工程师
任务描述所需技能

向 Amazon ECR 进行身份验证。

按照 Amazon ECR 文档中的步骤,向来源和目标注册表进行身份验证。

AWS 管理员、AWS DevOps、AWS 系统管理员、云管理员、 DevOps 工程师、云架构师

测试映像复制。

在您的源账户中,将容器映像推送到新的或现有的 Amazon ECR 源存储库,其映像标签前缀为 release-。要推送映像,请按照 Amazon ECR 文档 中的步骤进行操作。 

您可以在CodeBuild 控制台中监控 CodeBuild 项目的进度。 

CodeBuild 项目成功完成后,登录目标 AWS 账户,打开 Amazon ECR 控制台,并确认目标的 Amazon ECR 注册表中存在该映像。

AWS 管理员、AWS DevOps、AWS 系统管理员、云管理员、云架构师、 DevOps 工程师

测试映像排除。

在您的源账户中,使用没有自定义前缀的映像标签将容器映像推送到新的或现有的 Amazon ECR 源存储库。 

确认 CodeBuild 项目尚未启动,并且目标注册表中未显示任何容器映像。

AWS 管理员、AWS DevOps、AWS 系统管理员、云管理员、云架构师、 DevOps 工程师

相关资源

其他信息

若要自动部署此模式的资源,请执行以下步骤:

  1. 下载附件并提取两个 CloudFormation 模板:part-1-copy-tagged-images.yamlpart-2-destination-account-role.yaml

  2. 登录 AWS CloudFormation 控制台part-1-copy-tagged-images.yaml在与源 Amazon ECR 注册表相同的 AWS 账户和区域中进行部署。根据需要更新参数。模板部署以下资源:

    • 亚马逊 CloudWatch 活动 IAM 角色

    • AWS CodeBuild 项目 IAM 角色

    • AWS CodeBuild 项目

    • AWS CloudWatch 活动规则

  3. 记下输出选项卡中的 SourceRoleName 值。在下一个步骤中,您需要用到此值。

  4. 在要将 Amazon ECR 容器映像复制到的 AWS 账户中部署第二个 CloudFormation 模板。part-2-destination-account-role.yaml根据需要更新参数。为 SourceRoleName 参数指定第 3 步的值 。此模板部署跨账户 IAM 角色。

  5. 验证映像复制和排除,如操作说明部分的最后一步所述。

附件

要访问与此文档相关联的其他内容,请解压以下文件:attachment.zip