将 Amazon ECR 容器镜像复制到各处 AWS 账户 AWS 区域 - AWS 规范指引

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

将 Amazon ECR 容器镜像复制到各处 AWS 账户 AWS 区域

Faisal Shahdad,Amazon Web Services

Summary

此模式向您展示了如何使用无服务器方法将带标签的图像从现有的 Amazon Elastic Container Registry (Amazon ECR) 存储库复制到其他和。 AWS 账户 AWS 区域该解决方案 AWS Step Functions 用于管理复制工作流程和复制大型容器映像的 AWS Lambda 功能。

Amazon ECR 使用原生跨区域跨账户复制功能,可以跨区域和账户复制容器映像。但是这些功能只能从开启复制的那一刻起复制映像。目前没有机制能够将现有映像复制到不同区域和账户。

这种模式可以帮助人工智能 (AI) 团队向其他账户和区域分发容器化机器学习 (ML) 模型、框架(例如 PyTorch TensorFlow、和 Hugging Face)以及依赖关系。这可以帮助您克服服务限制并优化 GPU 计算资源。您也可以选择性地从特定来源账户和地区复制 Amazon ECR 存储库。有关更多信息,请参阅 Amazon ECR 中的跨区域复制已实现

先决条件和限制

先决条件

  • 两个或更多活跃账户 AWS 账户 (至少有一个源账户和一个目标账户)

  • 所有账户都有相应的 AWS Identity and Access Management (IAM) 权限

  • 用于构建 Lambda 容器映像的 Docker

  • AWS Command Line Interface (AWS CLI) 已为所有账户配置

限制

  • 未标记的映像排除- 该解决方案仅复制具有显式标签的容器映像。它会跳过摘要中存在的未加标签的 SHA256 映像。

  • Lambda 执行超时限制 — AWS Lambda 限制为最长 15 分钟的执行超时,这可能不足以复制大型容器映像或存储库。

  • 手动管理容器映像 — crane-app.py Python 代码需要重新构建和重新部署 Lambda 容器映像。

  • 并行处理容量有限 — MaxConcurrency 状态设置限制了您可以同时复制的存储库数量。但是,您可以在来源账户的 AWS CloudFormation 模板中修改此设置。请注意,较高的并发值可能会导致您超过服务速率限制和账户级 Lambda 执行配额。

架构

目标堆栈

该模式有四个主要组成部分:

  • 源账户基础架构 — 创建编排组件的 CloudFormation 模板

  • 目标账户基础设施- 创建跨账户访问角色的 CloudFormation 模板

  • Lambda 函数 — 基于 Python 的函数,使用 Crane 进行高效的映像复制

  • 容器映像 – 将 Lambda 函数与所需工具打包在一起的 Docker 容器

目标架构

Step Function 工作流

Step Functions 状态机会编排以下内容,如下图所示:

  • PopulateRepositoryList 扫描 Amazon ECR 存储库并填充 Amazon DynamoDB

  • GetRepositoryList 从 DynamoDB 检索唯一的存储库列表

  • DeduplicateRepositories 确保没有重复处理

  • CopyRepositories 处理存储库的并行复制

  • NotifySuccess/NotifyFailure 基于执行结果的 Amazon Simple Notification Service(Amazon SNS)通知

工具

Amazon 工具

  • Amazon CloudWatch 可帮助您实时监控您的 AWS 资源和运行的应用程序 AWS 的指标。

  • Amazon DynamoDB 是一项完全托管式 NoSQL 数据库服务,可提供快速、可预测、可扩展的性能。

  • Amazon Simple Notification Service(Amazon SNS)可帮助您协调和管理发布者与客户端(包括 Web 服务器和电子邮件地址)之间的消息交换。

  • AWS Identity and Access Management (IAM) 通过控制谁经过身份验证并有权使用 AWS 资源,从而帮助您安全地管理对资源的访问权限。

  • AWS Lambda 是一项计算服务,可帮助您运行代码,无需预调配或管理服务器。它只在需要时运行您的代码,并自动进行扩展,因此您只需为使用的计算时间付费。

  • AWS Step Functions是一项无服务器编排服务,可帮助您组合 Lambda 函数和其他函数 AWS 服务 来构建业务关键型应用程序。

其他工具

  • Crane 是一款 Docker 编排工具。它与 Docker Compose 类似,但还有其他功能。

  • Docker 是一组平台即服务(PaaS)产品,它们使用操作系统级别的虚拟化技术在容器中交付软件。

代码存储库

  • 此模式的代码可在 GitHub sample-ecr-copy 存储库中找到。您可以使用存储库中的 CloudFormation 模板来创建底层资源。

最佳实践

遵循最低权限原则,并授予执行任务所需的最低权限。有关详情,请参阅 IAM 文档中的授予最低权限安全最佳实践

操作说明

Task说明所需技能

配置 AWS CLI 配置文件。

  1. 配置源账户配置文件:

    aws configure --profile source-account # Enter: Access Key ID, Secret Access Key, Default region, Output format (json)
  2. 配置目标账户配置文件:

    aws configure --profile destination-account # Enter: Access Key ID, Secret Access Key, Default region, Output format (json)
  3. 验证配置:

    aws sts get-caller-identity --profile source-account aws sts get-caller-identity --profile destination-account
DevOps 工程师、数据工程师、机器学习工程师

收集所需信息。

  1. 获取源账户 ID:

    export SOURCE_ACCOUNT_ID=$(aws sts get-caller-identity --profile source-account --query Account --output text) echo "Source Account ID: $SOURCE_ACCOUNT_ID"
  2. 获取目标账户 ID:

    export DEST_ACCOUNT_ID=$(aws sts get-caller-identity --profile destination-account --query Account --output text) echo "Destination Account ID: $DEST_ACCOUNT_ID"
  3. 设置 AWS 区域. 修改您所在地区的以下命令:

    export SOURCE_REGION="us-east-1" export DEST_REGION="us-east-2"
  4. 列出源账户中现有的 Amazon ECR 存储库:

    aws ecr describe-repositories --profile source-account --region $SOURCE_REGION --query 'repositories[].repositoryName' --output table
DevOps 工程师、数据工程师、机器学习工程师

克隆存储库。

将项目的 存储库克隆到本地工作站。

git clone https://github.com/aws-samples/sample-ecr-copy
DevOps 工程师、数据工程师、机器学习工程师
Task说明所需技能

验证模版。

验证 CloudFormation 模板:

aws cloudformation validate-template \ --template-body file://"Destination Account cf_template.yml" \ --profile destination-account
DevOps 工程师、机器学习工程师、数据工程师

部署目标基础设施。

  1. 部署目标账户堆栈:

    aws cloudformation deploy \ --template-file "Destination Account cf_template.yml" \ --stack-name ecr-copy-destination \ --parameter-overrides \ SourceAccountId=$SOURCE_ACCOUNT_ID \ SourceRoleName=ECRContainerLambdaRole \ --capabilities CAPABILITY_NAMED_IAM \ --profile destination-account \ --region $DEST_REGION
  2. 等待堆栈删除完成。

    aws cloudformation wait stack-create-complete \ --stack-name ecr-copy-destination \ --profile destination-account \ --region $DEST_REGION
数据工程师、机器学习工程师、 DevOps 工程师

验证部署。

  1. 获取堆栈输出:

    aws cloudformation describe-stacks \ --stack-name ecr-copy-destination \ --profile destination-account \ --region $DEST_REGION \ --query 'Stacks[0].Outputs' \ --output table
  2. 存储跨账户 IAM 角色:

    export CROSS_ACCOUNT_ROLE_ARN=$(aws cloudformation describe-stacks \ --stack-name ecr-copy-destination \ --profile destination-account \ --region $DEST_REGION \ --query 'Stacks[0].Outputs[?OutputKey==`CrossAccountRoleArn`].OutputValue' \ --output text) echo "Cross-Account Role ARN: $CROSS_ACCOUNT_ROLE_ARN"
DevOps 工程师、机器学习工程师、数据工程师
Task说明所需技能

准备容器构建。

  1. 验证 Docker 是否正在运行:

    docker --version docker info
  2. 确保 crane-app.pyDockerfile 位于当前目录中:

    ls -la crane-app.py Dockerfile
数据工程师、机器学习工程师、 DevOps 工程师

构建容器映像。

  1. 构建 Lambda 容器映像:

    docker build -t ecr-copy-lambda . --no-cache
  2. 验证映像是否已创建:

    docker images ecr-copy-lambda
  3. (可选)在本地测试容器:

    docker run --rm --entrypoint python ecr-copy-lambda -c "import boto3; print('Container working')"
数据工程师、机器学习工程师、 DevOps 工程师

创建存储库并上传映像。

  1. 在源账户中创建 Amazon ECR 存储库:

    aws ecr create-repository \ --repository-name ecr-copy-lambda \ --profile source-account \ --region $SOURCE_REGION
  2. 获取 Amazon ECR 登录令牌并对 Docker 进行身份验证:

    aws ecr get-login-password \ --profile source-account \ --region $SOURCE_REGION | \ docker login --username AWS --password-stdin \ $SOURCE_ACCOUNT_ID.dkr.ecr.$SOURCE_REGION.amazonaws.com
  3. 为 Amazon ECR 的图片添加标签:

    docker tag ecr-copy-lambda:latest \ $SOURCE_ACCOUNT_ID.dkr.ecr.$SOURCE_REGION.amazonaws.com/ecr-copy-lambda:latest
  4. 将映像上传到 Amazon S3

    docker push $SOURCE_ACCOUNT_ID.dkr.ecr.$SOURCE_REGION.amazonaws.com/ecr-copy-lambda:latest
  5. 存储映像 URI 以备后用:

    export LAMBDA_IMAGE_URI="$SOURCE_ACCOUNT_ID.dkr.ecr.$SOURCE_REGION.amazonaws.com/ecr-copy-lambda:latest" echo "Lambda Image URI: $LAMBDA_IMAGE_URI"
数据工程师、机器学习工程师、 DevOps 工程师

Verify the image.

  1. 列出存储库中的映像:

    aws ecr list-images \ --repository-name ecr-copy-lambda \ --profile source-account \ --region $SOURCE_REGION
  2. 获取映像详情:

    aws ecr describe-images \ --repository-name ecr-copy-lambda \ --profile source-account \ --region $SOURCE_REGION
数据工程师、机器学习工程师、 DevOps 工程师
Task说明所需技能

准备部署参数。

  1. 设置通知电子邮件:

    export NOTIFICATION_EMAIL="your-email@company.com"
  2. 定义要复制的存储库(以逗号分隔):

    export REPOSITORY_LIST="app-frontend,app-backend,database-migrations"
  3. 设置环境:

    export ENVIRONMENT="dev" echo "Deployment Parameters:" echo "Source Account: $SOURCE_ACCOUNT_ID" echo "Destination Account: $DEST_ACCOUNT_ID" echo "Source Region: $SOURCE_REGION" echo "Destination Region: $DEST_REGION" echo "Lambda Image: $LAMBDA_IMAGE_URI" echo "Notification Email: $NOTIFICATION_EMAIL" echo "Repositories: $REPOSITORY_LIST"
数据工程师、 DevOps 工程师、机器学习工程师

验证源模版。

验证源 CloudFormation 模板:

aws cloudformation validate-template \ --template-body file://"Source Account Cf template.yml" \ --profile source-account
数据工程师、机器学习工程师、 DevOps 工程师

部署源基础设施。

  1. 部署源账户堆栈:

    aws cloudformation deploy \ --template-file "Source Account Cf template.yml" \ --stack-name ecr-copy-source \ --parameter-overrides \ SourceAccountId=$SOURCE_ACCOUNT_ID \ DestinationAccountId=$DEST_ACCOUNT_ID \ DestinationRegion=$DEST_REGION \ SourceRegion=$SOURCE_REGION \ NotificationEmail=$NOTIFICATION_EMAIL \ RepositoryList="$REPOSITORY_LIST" \ LambdaImageUri=$LAMBDA_IMAGE_URI \ Environment=$ENVIRONMENT \ --capabilities CAPABILITY_NAMED_IAM \ --profile source-account \ --region $SOURCE_REGION
  2. 等待堆栈完成(这可能需要 10 分钟):

    aws cloudformation wait stack-create-complete \ --stack-name ecr-copy-source \ --profile source-account \ --region $SOURCE_REGION
数据工程师、机器学习工程师、 DevOps 工程师

验证部署并收集输出。

  1. 获取堆栈输出:

    aws cloudformation describe-stacks \ --stack-name ecr-copy-source \ --profile source-account \ --region $SOURCE_REGION \ --query 'Stacks[0].Outputs' \ --output table
  2. 存储状态机和 SNS 主题的 Amazon 资源名称 (ARNs):

    export STATE_MACHINE_ARN=$(aws cloudformation describe-stacks \ --stack-name ecr-copy-source \ --profile source-account \ --region $SOURCE_REGION \ --query 'Stacks[0].Outputs[?OutputKey==`StateMachineArn`].OutputValue' \ --output text) export SNS_TOPIC_ARN=$(aws cloudformation describe-stacks \ --stack-name ecr-copy-source \ --profile source-account \ --region $SOURCE_REGION \ --query 'Stacks[0].Outputs[?OutputKey==`SNSTopicArn`].OutputValue' \ --output text) echo "State Machine ARN: $STATE_MACHINE_ARN" echo "SNS Topic ARN: $SNS_TOPIC_ARN"
DevOps 工程师、机器学习工程师、数据工程师

确认电子邮件订阅。

  1. 查看您的电子邮件以确认您的 SNS 订阅。

  2. 在电子邮件中选择确认链接。

  3. 验证订阅状态。

    aws sns list-subscriptions-by-topic \ --topic-arn $SNS_TOPIC_ARN \ --profile source-account \ --region $SOURCE_REGION
数据工程师、机器学习工程师、 DevOps 工程师
Task说明所需技能

运行并监控复制过程

  1. 登录并打开 Step AWS 管理控制台 Functions 控制台

  2. 创建状态机。

  3. 选择启动执行

    完成后,结果将显示在执行输入和输出选项卡上。

  4. (可选)如果您想使用继续运行 Step Functions AWS CLI,请按照本长篇故事中的其余步骤进行操作。

DevOps 工程师、机器学习工程师、数据工程师

运行 Step Function。

  1. 生成唯一的名称:

    export EXECUTION_NAME="ecr-copy-$(date +%Y%m%d-%H%M%S)"
  2. 运行 Step Function。

    export EXECUTION_ARN=$(aws stepfunctions start-execution \ --state-machine-arn $STATE_MACHINE_ARN \ --name $EXECUTION_NAME \ --profile source-account \ --region $SOURCE_REGION \ --query 'executionArn' \ --output text) echo "Execution started: $EXECUTION_ARN" echo "Execution Name: $EXECUTION_NAME"
DevOps 工程师、机器学习工程师、数据工程师

监控进度。

  1. 检查状态:

    aws stepfunctions describe-execution \ --execution-arn $EXECUTION_ARN \ --profile source-account \ --region $SOURCE_REGION \ --query '{Status:status,StartDate:startDate,StopDate:stopDate}' \ --output table
  2. 获取历史记录:

    aws stepfunctions get-execution-history \ --execution-arn $EXECUTION_ARN \ --profile source-account \ --region $SOURCE_REGION \ --query 'events[?type==`TaskStateEntered` || type==`TaskSucceeded` || type==`TaskFailed`].{Type:type,Timestamp:timestamp,Details:stateEnteredEventDetails.name}' \ --output table
DevOps 工程师、机器学习工程师、数据工程师

检查结果。

等待该过程完成(每 30 秒更新一次):

while true; do STATUS=$(aws stepfunctions describe-execution \ --execution-arn $EXECUTION_ARN \ --profile source-account \ --region $SOURCE_REGION \ --query 'status' \ --output text) echo "Current status: $STATUS" if [[ "$STATUS" == "SUCCEEDED" || "$STATUS" == "FAILED" || "$STATUS" == "TIMED_OUT" || "$STATUS" == "ABORTED" ]]; then break fi sleep 30 done echo "Final execution status: $STATUS"
DevOps 工程师、机器学习工程师、数据工程师

验证映像。

  1. 列出目标账户中的存储库:

    aws ecr describe-repositories \ --profile destination-account \ --region $DEST_REGION \ --query 'repositories[].repositoryName' \ --output table
  2. 检查存储库映像:

    for repo in $(echo $REPOSITORY_LIST | tr ',' ' '); do echo "\nImages in repository: $repo" aws ecr list-images \ --repository-name $repo \ --profile destination-account \ --region $DEST_REGION \ --query 'imageIds[].imageTag' \ --output table 2>/dev/null || echo "Repository $repo not found or no images" done
DevOps 工程师、数据工程师、机器学习工程师

问题排查

问题解决方案

Step Function 无法运行。

  1. 要从历史记录中检索详细的故障事件,请运行以下 AWS CLI 命令:

    if [[ "$STATUS" == "FAILED" ]]; then echo "Getting failure details..." aws stepfunctions get-execution-history \ --execution-arn $EXECUTION_ARN \ --profile source-account \ --region $SOURCE_REGION \ --query 'events[?type==`TaskFailed`]' \ --output json fi
  2. 要检索失败的 Lambda 函数的日志,请运行以下 AWS CLI 命令:

    # Check Lambda function logs echo "\nLambda function logs:" aws logs describe-log-groups \ --log-group-name-prefix "/aws/lambda/ecr-copy-source" \ --profile source-account \ --region $SOURCE_REGION \ --query 'logGroups[].logGroupName' \ --output table

相关资源

附加信息

配置参数

参数

说明

示例

SourceAccountId

来源 AWS 账户 ID

11111111111

DestinationAccountId

目的地 AWS 账户 ID

22222222222

DestinationRegion

目标 AWS 区域

us-east-2

SourceRegion

来源 AWS 区域

us-east-1

NotificationEmail

电子邮件通知

abc@xyz.com

RepositoryList

要复制的存储库

repo1,repo2,repo3

LambdaImageUri

Lambda 容器映像

${ACCOUNT}.dkr.ecr.${REGION}.amazonaws.com/ecr-copy-lambda:latest