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 layersecr.api.ecr.<region>.amazonaws.com— auth tokens3.<region>.amazonaws.com— ECR lưu image layer trên S3logs.<region>.amazonaws.com— CloudWatch Logsssm.<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
ResourceInitializationErrorche 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:GetSecretValuetrê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.

