I’m searching AWS documentation but I’m still unclear on what ECR resource policy is necessary to retrieve an image from ECR?
The error I’m receiving is
CannotPullContainerError: The task cannot pull <image>.
There is a connection issue between the task and the registry.
Check your task network configuration. :
failed to copy: httpReadSeeker:
failed open:
failed to do request:
Get <image>: i/o timeout
Below is my IAM policy, which the role has assumed
{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"logs:CreateLogStream",
"logs:PutLogEvents"
],
"Resource": "arn:aws:<myArn>",
"Effect": "Allow"
},
{
"Action": [
"batch:DescribeJobs",
"batch:ListJobs",
"batch:TerminateJob",
"ec2:AttachNetworkInterface",
"ec2:CreateNetworkInterface",
"ec2:DeleteNetworkInterface",
"ec2:DescribeNetworkInterfaces",
"ecr:BatchCheckLayerAvailability",
"ecr:DescribeRepositories",
"ecr:GetAuthorizationToken",
"ecr:GetDownloadUrlForLayer",
"ecr:GetRepositoryPolicy",
"ecr:ListImages",
"ecr:PutImageTagMutability",
"ecr:TagResource",
"ecs:DescribeTasks",
"ecs:RunTask",
"ecs:StopTask",
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:DescribeLogGroups",
"logs:PutLogEvents",
"s3:GetObject",
"s3:ListBucket",
"s3:PutObject"
],
"Resource": "*",
"Effect": "Allow"
}
]
}
Edit VPC construct below
import { DeploymentStackProps } from '@amzn/pipelines';
import { Construct } from 'constructs';
import * as ec2 from 'aws-cdk-lib/aws-ec2';
export interface VpcConstructProps extends DeploymentStackProps {
stageName: string;
modelContext: string;
lambdaSourcePackage: string;
lambdaImagePackage: string;
fargateSourcePackage: string;
fargateImagePackage: string;
scheduleExpression: string;
}
export class VpcConstruct extends Construct {
public readonly lambdaImageLocation: any;
public readonly securityGroup: ec2.SecurityGroup;
public readonly vpc: ec2.Vpc;
public readonly ecrApiEndpoint: ec2.InterfaceVpcEndpoint;
public readonly ecrDkrEndpoint: ec2.InterfaceVpcEndpoint;
public readonly cloudwatchLogsEndpoint: ec2.InterfaceVpcEndpoint;
constructor(scope: Construct, id: string, props: VpcConstructProps) {
super(scope, id);
// Create VPC
this.vpc = new ec2.Vpc(this, `VPC-${props.modelContext}-${props.stageName}`, {
maxAzs: 3, // Maximum number of Availability Zones to use
natGateways: 1, // Number of NAT Gateways to use
subnetConfiguration: [
{
subnetType: ec2.SubnetType.PUBLIC,
name: `PublicSubnet-${props.modelContext}-${props.stageName}`,
},
{
subnetType: ec2.SubnetType.PRIVATE_ISOLATED,
name: `PrivateSubnet-${props.modelContext}-${props.stageName}`,
},
],
});
// Add VPC endpoint for ECR API
this.ecrApiEndpoint = new ec2.InterfaceVpcEndpoint(
this,
`EcrApiEndpoint-${props.modelContext}-${props.stageName}`,
{
vpc: this.vpc,
service: ec2.InterfaceVpcEndpointAwsService.ECR,
},
);
// Add VPC endpoint for ECR Docker
this.ecrDkrEndpoint = new ec2.InterfaceVpcEndpoint(
this,
`EcrDkrEndpoint-${props.modelContext}-${props.stageName}`,
{
vpc: this.vpc,
service: ec2.InterfaceVpcEndpointAwsService.ECR_DOCKER,
},
);
// Optionally, you can add VPC endpoint for CloudWatch Logs if you're logging in a private subnet
this.cloudwatchLogsEndpoint = new ec2.InterfaceVpcEndpoint(
this,
`CloudwatchLogsEndpoint-${props.modelContext}-${props.stageName}`,
{
vpc: this.vpc,
service: ec2.InterfaceVpcEndpointAwsService.CLOUDWATCH_LOGS,
},
);
this.securityGroup = new ec2.SecurityGroup(this, `SecurityGroup-${props.modelContext}-${props.stageName}`, {
vpc: this.vpc,
allowAllOutbound: true,
});
}
}
3