本文為英文版的機器翻譯版本,如內容有任何歧義或不一致之處,概以英文版為準。
跨 AWS 帳戶 和 複製 Amazon ECR 容器映像 AWS 區域
Faisal Shahdad,Amazon Web Services
總結
此模式說明如何使用無伺服器方法,將現有 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 執行配額。
Architecture
目標堆疊
模式有四個主要元件:
來源帳戶基礎設施 – 建立協同運作元件的 CloudFormation 範本
目的地帳戶基礎設施 – 建立跨帳戶存取角色的 CloudFormation 範本
Lambda 函數 – 使用 Crane 進行高效率映像複製的 Python 函數
容器映像 – 使用必要工具封裝 Lambda 函數的 Docker 容器
目標架構
Step Functions 工作流程
Step Functions 狀態機器會協調下列項目,如下圖所示:
PopulateRepositoryList – 掃描 Amazon ECR 儲存庫並填入 Amazon DynamoDB
GetRepositoryList – 從 DynamoDB 擷取唯一儲存庫清單
DeduplicateRepositories – 確保沒有重複的處理
CopyRepositories – 處理儲存庫的平行複製
NotifySuccess/NotifyFailure – 根據執行結果的 Amazon Simple Notification Service (Amazon SNS) 通知
Amazon 工具
其他工具
程式碼儲存庫
最佳實務
遵循最低權限原則,並授予執行任務所需的最低許可。如需詳細資訊,請參閱 IAM 文件中的授予最低權限和安全最佳實務。
史詩
| 任務 | Description | 所需的技能 |
|---|
設定 AWS CLI 設定檔。 | 設定來源帳戶設定檔: aws configure --profile source-account
# Enter: Access Key ID, Secret Access Key, Default region, Output format (json)
設定目的地帳戶設定檔: aws configure --profile destination-account
# Enter: Access Key ID, Secret Access Key, Default region, Output format (json)
驗證組態: aws sts get-caller-identity --profile source-account
aws sts get-caller-identity --profile destination-account
| DevOps 工程師、資料工程師、ML 工程師 |
收集必要資訊。 | 取得來源帳戶 ID: export SOURCE_ACCOUNT_ID=$(aws sts get-caller-identity --profile source-account --query Account --output text)
echo "Source Account ID: $SOURCE_ACCOUNT_ID"
取得目的地帳戶 ID: export DEST_ACCOUNT_ID=$(aws sts get-caller-identity --profile destination-account --query Account --output text)
echo "Destination Account ID: $DEST_ACCOUNT_ID"
設定 AWS 區域。為您的區域修改此命令: export SOURCE_REGION="us-east-1"
export DEST_REGION="us-east-2"
列出來源帳戶中現有的 Amazon ECR 儲存庫: aws ecr describe-repositories --profile source-account --region $SOURCE_REGION --query 'repositories[].repositoryName' --output table
| DevOps 工程師、資料工程師、ML 工程師 |
複製儲存庫。 | 將模式的儲存庫複製到本機工作站: git clone https://github.com/aws-samples/sample-ecr-copy
| DevOps 工程師、資料工程師、ML 工程師 |
| 任務 | Description | 所需的技能 |
|---|
驗證範本。 | 驗證 CloudFormation 範本: aws cloudformation validate-template \
--template-body file://"Destination Account cf_template.yml" \
--profile destination-account
| DevOps 工程師、ML 工程師、資料工程師 |
部署目的地基礎設施。 | 部署目的地帳戶堆疊: 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
等待堆疊完成: aws cloudformation wait stack-create-complete \
--stack-name ecr-copy-destination \
--profile destination-account \
--region $DEST_REGION
| 資料工程師、ML 工程師、DevOps 工程師 |
驗證部署。 | 取得堆疊輸出: aws cloudformation describe-stacks \
--stack-name ecr-copy-destination \
--profile destination-account \
--region $DEST_REGION \
--query 'Stacks[0].Outputs' \
--output table
存放跨帳戶 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 工程師、ML 工程師、資料工程師 |
| 任務 | Description | 所需的技能 |
|---|
準備容器建置。 | 確認 Docker 正在執行: docker --version
docker info
確定 crane-app.py和 Dockerfile 位於目前的目錄中: ls -la crane-app.py Dockerfile
| 資料工程師、ML 工程師、DevOps 工程師 |
建置容器映像。 | 建置 Lambda 容器映像: docker build -t ecr-copy-lambda . --no-cache
確認已建立映像: docker images ecr-copy-lambda
(選用) 在本機測試容器: docker run --rm --entrypoint python ecr-copy-lambda -c "import boto3; print('Container working')"
| 資料工程師、ML 工程師、DevOps 工程師 |
建立儲存庫並上傳映像。 | 在來源帳戶中建立 Amazon ECR 儲存庫: aws ecr create-repository \
--repository-name ecr-copy-lambda \
--profile source-account \
--region $SOURCE_REGION
取得 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
標記 Amazon ECR 的映像: docker tag ecr-copy-lambda:latest \
$SOURCE_ACCOUNT_ID.dkr.ecr.$SOURCE_REGION.amazonaws.com/ecr-copy-lambda:latest
將映像上傳至 Amazon ECR: docker push $SOURCE_ACCOUNT_ID.dkr.ecr.$SOURCE_REGION.amazonaws.com/ecr-copy-lambda:latest
存放映像 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"
| 資料工程師、ML 工程師、DevOps 工程師 |
驗證映像。 | 列出儲存庫中的映像: aws ecr list-images \
--repository-name ecr-copy-lambda \
--profile source-account \
--region $SOURCE_REGION
取得映像詳細資訊: aws ecr describe-images \
--repository-name ecr-copy-lambda \
--profile source-account \
--region $SOURCE_REGION
| 資料工程師、ML 工程師、DevOps 工程師 |
| 任務 | Description | 所需的技能 |
|---|
準備部署參數。 | 設定通知電子郵件: export NOTIFICATION_EMAIL="your-email@company.com"
定義要複製的儲存庫 (逗號分隔): export REPOSITORY_LIST="app-frontend,app-backend,database-migrations"
設定環境: 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 工程師、ML 工程師 |
驗證來源範本。 | 驗證來源 CloudFormation 範本: aws cloudformation validate-template \
--template-body file://"Source Account Cf template.yml" \
--profile source-account
| 資料工程師、ML 工程師、DevOps 工程師 |
部署來源基礎設施。 | 部署來源帳戶堆疊: 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
等待堆疊完成 (最多可能需要 10 分鐘): aws cloudformation wait stack-create-complete \
--stack-name ecr-copy-source \
--profile source-account \
--region $SOURCE_REGION
| 資料工程師、ML 工程師、DevOps 工程師 |
驗證部署並收集輸出。 | 取得堆疊輸出: aws cloudformation describe-stacks \
--stack-name ecr-copy-source \
--profile source-account \
--region $SOURCE_REGION \
--query 'Stacks[0].Outputs' \
--output table
存放狀態機器和 SNS 主題的 Amazon Resource Name (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 工程師、ML 工程師、資料工程師 |
確認您的電子郵件訂閱。 | 請檢查您的電子郵件以確認您的 SNS 訂閱。 選擇電子郵件中的確認連結。 驗證訂閱狀態。 aws sns list-subscriptions-by-topic \
--topic-arn $SNS_TOPIC_ARN \
--profile source-account \
--region $SOURCE_REGION
| 資料工程師、ML 工程師、DevOps 工程師 |
| 任務 | Description | 所需的技能 |
|---|
執行並監控複製程序。 | 登入 AWS 管理主控台,然後開啟 Step Functions 主控台。 找到狀態機器。 選擇 Start execution (開始執行)。 完成後,結果會顯示在執行輸入和輸出索引標籤上。 (選用) 如果您想要使用 繼續執行 Step Functions AWS CLI,請遵循此史詩中的其餘步驟。
| DevOps 工程師、ML 工程師、資料工程師 |
執行步驟函數。 | 產生唯一名稱: export EXECUTION_NAME="ecr-copy-$(date +%Y%m%d-%H%M%S)"
執行步驟函數。 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 工程師、ML 工程師、資料工程師 |
監控進度。 | 檢查狀態:
aws stepfunctions describe-execution \
--execution-arn $EXECUTION_ARN \
--profile source-account \
--region $SOURCE_REGION \
--query '{Status:status,StartDate:startDate,StopDate:stopDate}' \
--output table
取得歷史記錄:
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 工程師、ML 工程師、資料工程師 |
檢查結果。 | 等待程序完成 (每 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 工程師、ML 工程師、資料工程師 |
驗證映像。 | 列出目的地帳戶中的儲存庫: aws ecr describe-repositories \
--profile destination-account \
--region $DEST_REGION \
--query 'repositories[].repositoryName' \
--output table
檢查儲存庫映像: 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 工程師、資料工程師、ML 工程師 |
疑難排解
| 問題 | 解決方案 |
|---|
步驟函數無法執行。 | 若要從歷史記錄擷取詳細的失敗事件,請執行下列 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
若要擷取失敗 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 容器映像 URI | ${ACCOUNT}.dkr.ecr.${REGION}.amazonaws.com/ecr-copy-lambda:latest
|