Sửa lỗi AWS ECS ResourceInitializationError: unable to retrieve ecr registry auth

intermediate☁️ AWS2026-04-16| AWS ECS (Fargate hoặc EC2 launch type), Amazon ECR, AWS IAM, VPC với private subnets

Error Message

ResourceInitializationError: unable to pull secrets or registry auth: execution resource retrieval failed: unable to retrieve ecr registry auth: service call has been retried 3 time(s): RequestError: send request failed
#ecs#ecr#docker#iam#task-execution-role

Tình huống

Triển khai một task definition ECS mới trỏ đến image ECR. Task thất bại ngay trong quá trình khởi tạo — container chưa kịp chạy. Kiểm tra ECS console:

ResourceInitializationError: unable to pull secrets or registry auth: execution resource retrieval failed: unable to retrieve ecr registry auth: service call has been retried 3 time(s): RequestError: send request failed

Không có container log. Không có gì trong CloudWatch. Task cứ lặp lại trạng thái STOPPED với exit code None.

Có hai nguyên nhân gây ra lỗi này: thiếu quyền IAM trên task execution role, hoặc sự cố mạng ngăn ECS agent kết nối đến ECR. Cả hai đều sinh ra cùng một thông báo lỗi — đó chính xác là điều khiến việc debug trở nên khó chịu.

Quá trình debug

Bước 1: Kiểm tra task execution role

Task execution role khác với task role. Đây là role mà ECS agent dùng để pull image và lấy secrets — không phải role mà code ứng dụng của bạn dùng lúc chạy.

Tìm Task execution role trong task definition, rồi kiểm tra:

aws iam list-attached-role-policies --role-name ecsTaskExecutionRole

Bạn cần thấy AmazonECSTaskExecutionRolePolicy trong kết quả. Nếu thiếu, đó là vấn đề của bạn. Managed policy này bao gồm mức tối thiểu cần thiết: pull ECR và ghi CloudWatch Logs.

Tiếp theo, kiểm tra xem trust relationship có thực sự cho phép ECS assume role này không:

aws iam get-role --role-name ecsTaskExecutionRole --query 'Role.AssumeRolePolicyDocument'

Kết quả mong đợi:

{
  "Effect": "Allow",
  "Principal": {
    "Service": "ecs-tasks.amazonaws.com"
  },
  "Action": "sts:AssumeRole"
}

Trust policy sai hoặc bị thiếu đồng nghĩa ECS không thể assume role — và bạn không thể vượt qua bước khởi tạo.

Bước 2: Kiểm tra kết nối mạng (Fargate trong private subnet)

Đây là phần dễ bỏ sót. Nếu execution role trông ổn, thủ phạm gần như chắc chắn là kết nối mạng. Fargate task trong private subnet cần đến được nhiều AWS endpoint chỉ để khởi động:

  • ecr.dkr.ecr.<region>.amazonaws.com — image layers
  • ecr.api.ecr.<region>.amazonaws.com — auth token
  • s3.<region>.amazonaws.com — ECR lưu image layer trên S3
  • logs.<region>.amazonaws.com — CloudWatch Logs
  • ssm.<region>.amazonaws.com — nếu dùng Secrets Manager hoặc SSM Parameter Store

Private subnet không có NAT Gateway và không có VPC endpoint sẽ không thể định tuyến đến bất kỳ endpoint nào trong số này. ECS agent âm thầm timeout — và bạn nhận được chính xác lỗi này.

Kiểm tra các VPC endpoint đang tồn tại:

aws ec2 describe-vpc-endpoints \
  --filters "Name=vpc-id,Values=vpc-xxxxxxxx" \
  --query 'VpcEndpoints[*].{Service:ServiceName,State:State}'

Bước 3: Xác minh ECR image URI

Ít gặp hơn, nhưng đáng kiểm tra nhanh. Account ID hoặc region sai trong URI cũng gây ra lỗi xác thực. Điều này hay xảy ra khi sao chép task definition giữa các region — chẳng hạn từ us-east-1 sang ap-northeast-1 — mà quên cập nhật URI.

aws ecs describe-task-definition --task-definition my-task \
  --query 'taskDefinition.containerDefinitions[*].image'

Định dạng đúng: 123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/my-repo:tag

Cách khắc phục

Fix 1: Gắn managed policy đúng vào execution role

aws iam attach-role-policy \
  --role-name ecsTaskExecutionRole \
  --policy-arn arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy

Dùng Secrets Manager hoặc SSM để inject biến môi trường? Execution role cần thêm các quyền sau:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "secretsmanager:GetSecretValue",
        "ssm:GetParameters",
        "kms:Decrypt"
      ],
      "Resource": "*"
    }
  ]
}

Fix 2: Thêm VPC endpoint cho private subnet (không có NAT Gateway)

Tạo interface endpoint cho ECR và gateway endpoint cho S3:

# ECR API endpoint
aws ec2 create-vpc-endpoint \
  --vpc-id vpc-xxxxxxxx \
  --vpc-endpoint-type Interface \
  --service-name com.amazonaws.ap-northeast-1.ecr.api \
  --subnet-ids subnet-xxxxxxxx \
  --security-group-ids sg-xxxxxxxx \
  --private-dns-enabled

# ECR DKR endpoint (image layers)
aws ec2 create-vpc-endpoint \
  --vpc-id vpc-xxxxxxxx \
  --vpc-endpoint-type Interface \
  --service-name com.amazonaws.ap-northeast-1.ecr.dkr \
  --subnet-ids subnet-xxxxxxxx \
  --security-group-ids sg-xxxxxxxx \
  --private-dns-enabled

# S3 gateway endpoint (ECR lưu layer ở đây)
aws ec2 create-vpc-endpoint \
  --vpc-id vpc-xxxxxxxx \
  --vpc-endpoint-type Gateway \
  --service-name com.amazonaws.ap-northeast-1.s3 \
  --route-table-ids rtb-xxxxxxxx

# CloudWatch Logs endpoint
aws ec2 create-vpc-endpoint \
  --vpc-id vpc-xxxxxxxx \
  --vpc-endpoint-type Interface \
  --service-name com.amazonaws.ap-northeast-1.logs \
  --subnet-ids subnet-xxxxxxxx \
  --security-group-ids sg-xxxxxxxx \
  --private-dns-enabled

Security group trên mỗi VPC endpoint phải cho phép HTTPS inbound (port 443) từ các task subnet. Nếu thiếu, endpoint có nhưng traffic vẫn không đi qua được.

Fix 3: Phương án thay thế — gán public IP (chỉ để test nhanh)

Muốn xác định xem vấn đề có phải do mạng trước khi thiết lập endpoint không? Bật auto-assign public IP cho một lần chạy thử:

aws ecs run-task \
  --cluster my-cluster \
  --task-definition my-task \
  --launch-type FARGATE \
  --network-configuration "awsvpcConfiguration={subnets=[subnet-xxxxxxxx],securityGroups=[sg-xxxxxxxx],assignPublicIp=ENABLED}"

Task khởi động được khi có public IP nhưng thất bại khi không có? Đã xác nhận là do mạng. Hãy thiết lập VPC endpoint — đừng dùng cấu hình này lên production.

Xác minh

Sau khi áp dụng fix, chạy lại task và theo dõi các sự kiện:

aws ecs describe-tasks \
  --cluster my-cluster \
  --tasks <task-arn> \
  --query 'tasks[0].{Status:lastStatus,StoppedReason:stoppedReason,Containers:containers[*].{Name:name,Reason:reason}}'

Pull thành công sẽ đưa task qua các trạng thái PENDING → ACTIVATING → RUNNING. Vẫn thất bại? Kiểm tra stoppedReason — thường chứa thông tin chi tiết hơn những gì ECS console hiển thị.

Khi task đã chạy, xem log trực tiếp:

aws logs tail /ecs/my-task --follow

Bài học rút ra

  • Luôn khởi tạo ECS task execution role từ AmazonECSTaskExecutionRolePolicy — đừng tự viết policy từ đầu. Bạn sẽ bỏ sót điều gì đó.
  • Khi dựng ECS trong VPC mới, hãy tạo sẵn VPC endpoint cho ECR/S3/Logs trước khi deploy bất kỳ task nào. Phải bổ sung sau khi deployment đã bị lỗi rất mất công.
  • Thông báo lỗi ghi "retried 3 times" — đó là network timeout, không phải bị từ chối xác thực. Lỗi 403 thật sự từ IAM trông khác hẳn. Wrapper ResourceInitializationError che khuất cả hai trường hợp, vì vậy hãy luôn kiểm tra IAM và mạng cùng lúc.
  • Task execution role và task role phục vụ hai mục đích khác nhau. Các developer thường cấu hình một cái và quên mất cái kia tồn tại.
  • Tham chiếu Secrets Manager trong task definition yêu cầu quyền secretsmanager:GetSecretValue trên execution role. Chạy trong private subnet? Bạn còn cần thêm Secrets Manager VPC endpoint — đây là endpoint riêng biệt, khác với ECR.

Related Error Notes