我正在尝试使用 AWS CDK 将 Docker 映像启动为 Fargate 任务。图像已上传到私人存储库,但我在提取图像时遇到问题。
按照这篇 AWS 文章中的说明,我尝试了多种方法来确保任务可以访问私有存储库,但我无法解决问题。这包括使用 VPC 终端节点并打开必要的端口。
我正在使用具有三个私有子网的现有 VPC。否则,AWS 账户配置为“空白”。 ECS存储库与VPC位于同一区域,并且CDK应用程序配置为与VPC和存储库相同的区域和帐户。
下面是我的代码:
import { Stack, StackProps } from "aws-cdk-lib";
import {
aws_ecs as ecs,
aws_iam as iam,
aws_ecs_patterns as ecsPatterns,
aws_ecr as ecr,
aws_ec2 as ec2,
} from "aws-cdk-lib";
import {
Vpc,
} from "aws-cdk-lib/aws-ec2";
import { Construct } from "constructs";
export class MattermostStack extends Stack {
constructor(scope: Construct, id: string, props?: StackProps) {
super(scope, id, props);
// Use existing VPC
const vpc = Vpc.fromLookup(this, 'MyVPC', {
tags: {
Name: 'my-VPC',
},
})
// Create VPC endpoint for ECR
const ecrVpcEndpoint = vpc.addInterfaceEndpoint('EcrEndpoint', {
service: ec2.InterfaceVpcEndpointAwsService.ECR,
privateDnsEnabled: true, // Set to false if you want public DNS names for the endpoint
subnets: { subnetType: ec2.SubnetType.PRIVATE_ISOLATED }, // Specify the subnets where you want the endpoint
});
// Create task execution role
const ecsTaskExecutionRole = new iam.Role(this, "ecsTaskExecutionRole", {
assumedBy: new iam.ServicePrincipal("ecs-tasks.amazonaws.com"),
});
ecsTaskExecutionRole.addManagedPolicy(
iam.ManagedPolicy.fromAwsManagedPolicyName(
"service-role/AmazonECSTaskExecutionRolePolicy"
)
);
// Define your cluster, Fargate ECS task and service
const ecsCluster = new ecs.Cluster(this, 'EcsCluster', { vpc: vpc });
const fargateService = new ecs.FargateService(this, 'FargateService', {
cluster: ecsCluster,
taskDefinition: new ecs.FargateTaskDefinition(this, 'MattermostTaskDefinition', {
taskRole: ecsTaskExecutionRole
}),
assignPublicIp: false, // Set to true if you want tasks to have public IP addresses
});
// Get image
const containerImage = ecs.ContainerImage.fromEcrRepository(ecr.Repository.fromRepositoryName(this, 'mattermost', 'mattermost-team-edition'));
// Add container to the task definition
const container = fargateService.taskDefinition.addContainer('MattermostContainer', {
image: containerImage,
memoryLimitMiB: 512, // Adjust as needed
cpu: 256, // Adjust as needed
environment: {
MM_SQLSETTINGS_DRIVERNAME: 'postgres',
// replace username/pass with secret (also see dbStack commented lines)
MM_SQLSETTINGS_DATASOURCE: 'postgres://xxxxxxxx:[email protected]:5500/mattermost?sslmode=disable&connect_timeout=10',
},
portMappings: [{ containerPort: 8065 }],
logging: new ecs.AwsLogDriver({ streamPrefix: 'MatterLogTest', mode: ecs.AwsLogDriverMode.NON_BLOCKING }),
});
// Connect your service to the VPC endpoint
fargateService.connections.allowTo(ecrVpcEndpoint, ec2.Port.allTraffic(), 'Allow access to ECR');
// Allow inbound HTTPS access
fargateService.connections.allowFromAnyIpv4(ec2.Port.tcp(443), 'Allow inbound HTTPS traffic');
// Allow HTTPS access through port 443 at the task definition level
container.addPortMappings({
containerPort: 443,
protocol: ecs.Protocol.TCP,
})
// Allow inbound HTTPS access through port 443 at the security group level
const securityGroup = fargateService.connections.securityGroups[0]; // Assuming there is at least one security group
securityGroup.addIngressRule(ec2.Peer.anyIpv4(), ec2.Port.tcp(443), 'Allow HTTPS inbound traffic');
}
}
不幸的是,在部署堆栈时,我在任务级别收到此错误:
CannotPullContainerError: pull image manifest has been retried 5 time(s): failed to resolve ref xxxxxxx.dkr.ecr.eu-central-1.amazonaws.com/mattermost-team-edition:latest: failed to do request: Head "https://xxxxxxx.dkr.ecr.eu-central-1.amazonaws.com/v2/mattermost-team-edition/manifests/latest": dial tcp 3.121.166.70:443: i/o timeout
谁能告诉我我的 CDK 堆栈配置有什么问题吗?
我能够通过在失败的集群/任务上运行此运行手册并仔细研究发现的所有问题来解决这个问题。
我改变了一些东西以使其正常工作:
最终的 CDK 堆栈现在如下所示:
// Use existing VPC
const vpc = Vpc.fromLookup(this, 'MyVPC', {
tags: {
Name: 'MyVPC',
},
})
// Create VPC endpoint for ECR
const ecrVpcEndpoint = vpc.addInterfaceEndpoint('EcrEndpoint', {
service: ec2.InterfaceVpcEndpointAwsService.ECR,
privateDnsEnabled: true, // Set to false if you want public DNS names for the endpoint
subnets: { subnetType: ec2.SubnetType.PRIVATE_ISOLATED }, // Specify the subnets where you want the endpoint
});
// Create VPC endpoint for ECR docker
const ecrDkrVpcEndpoint = vpc.addInterfaceEndpoint('EcrDkrEndpoint', {
service: ec2.InterfaceVpcEndpointAwsService.ECR_DOCKER,
privateDnsEnabled: true, // Set to false if you want public DNS names for the endpoint
subnets: { subnetType: ec2.SubnetType.PRIVATE_ISOLATED }, // Specify the subnets where you want the endpoint
});
// Create a Gateway endpoint for S3
const s3GatewayEndpoint = vpc.addGatewayEndpoint('S3GatewayEndpoint', {
service: ec2.GatewayVpcEndpointAwsService.S3,
});
// Get existing role
const ecsTaskExecutionRole = iam.Role.fromRoleArn(this, 'ecsTaskExecutionRole', 'arn:aws:iam::805442828467:role/ecsTaskExecutionRole');
// Define your cluster, Fargate ECS task and service
const ecsCluster = new ecs.Cluster(this, 'EcsCluster', { vpc: vpc });
const fargateService = new ecs.FargateService(this, 'FargateService', {
cluster: ecsCluster,
taskDefinition: new ecs.FargateTaskDefinition(this, 'MattermostTaskDefinition', {
taskRole: ecsTaskExecutionRole
}),
assignPublicIp: false, // Set to true if you want tasks to have public IP addresses
vpcSubnets: { subnetType: ec2.SubnetType.PRIVATE_ISOLATED }
});
// Add a container to the task definition
const containerImage = ecs.ContainerImage.fromEcrRepository(ecr.Repository.fromRepositoryName(this, 'mattermost', 'mattermost-team-edition'));
// Add container to the task definition
const container = fargateService.taskDefinition.addContainer('MattermostContainer', {
image: containerImage,
memoryLimitMiB: 512, // Adjust as needed
cpu: 256, // Adjust as needed
environment: {
MM_SQLSETTINGS_DRIVERNAME: 'postgres',
// replace username/pass with secret (also see dbStack commented lines) -> remember setting up IAM role: https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task_execution_IAM_role.html
MM_SQLSETTINGS_DATASOURCE: 'postgres://xxxxx:[email protected]:5500/mattermost?sslmode=disable&connect_timeout=10',
},
portMappings: [{ containerPort: 8065 }],
});
// Connect service to the VPC endpoints
fargateService.connections.allowTo(ecrVpcEndpoint, ec2.Port.allTraffic(), 'Allow access to ECR');
fargateService.connections.allowTo(ecrDkrVpcEndpoint, ec2.Port.allTraffic(), 'Allow access to ECR docker');
// Allow inbound HTTPS access
fargateService.connections.allowFromAnyIpv4(ec2.Port.tcp(443), 'Allow inbound HTTPS traffic');
// Allow HTTPS access through port 443 at the task definition level
container.addPortMappings({
containerPort: 443,
protocol: ecs.Protocol.TCP,
})
// Allow inbound HTTPS access through port 443 at the security group level
const securityGroup = fargateService.connections.securityGroups[0]; // Assuming there is at least one security group
securityGroup.addIngressRule(ec2.Peer.anyIpv4(), ec2.Port.tcp(443), 'Allow HTTPS inbound traffic');