Terraform创建ECS架构问题:Capacity Provider未关联集群及脚本修正
ECS实例无法连接集群的Terraform脚本修正
你遇到的ECS实例无法连接集群的核心原因是Capacity Provider未与ECS集群绑定,同时脚本缺失ECS实例必需的安全组出站规则(实例需要出站流量与ECS控制平面通信、拉取镜像)。以下是具体修正方案:
核心修正点
1. 关联Capacity Provider与ECS集群
修改aws_ecs_cluster资源,添加capacity_providers和default_capacity_provider_strategy配置,将创建的Capacity Provider绑定到集群:
resource "aws_ecs_cluster" "my_cluster" { name = "ecs-demo" # 关联Capacity Provider capacity_providers = [aws_ecs_capacity_provider.my_capacity_provider.name] default_capacity_provider_strategy { capacity_provider = aws_ecs_capacity_provider.my_capacity_provider.name weight = 1 base = 1 } }
2. 补全安全组出站规则
给aws_security_group添加全量出站规则,确保ECS实例能正常与AWS服务通信:
resource "aws_security_group" "my_security_group" { name = "ecs-demo-security-group" description = "Allow SSH, HTTP traffic and ECS required outbound" vpc_id = "vpc-xxxx" # 替换为你的VPC ID ingress { from_port = 22 to_port = 22 protocol = "tcp" cidr_blocks = ["0.0.0.0/0"] } ingress { from_port = 3000 to_port = 3000 protocol = "tcp" cidr_blocks = ["0.0.0.0/0"] } # 添加ECS实例必需的出站规则 egress { from_port = 0 to_port = 0 protocol = "-1" cidr_blocks = ["0.0.0.0/0"] } }
3. 修正资源创建顺序
由于ECS集群依赖Capacity Provider,需要添加depends_on确保Terraform创建顺序正确:
resource "aws_ecs_cluster" "my_cluster" { name = "ecs-demo" capacity_providers = [aws_ecs_capacity_provider.my_capacity_provider.name] default_capacity_provider_strategy { capacity_provider = aws_ecs_capacity_provider.my_capacity_provider.name weight = 1 base = 1 } # 确保集群在Capacity Provider创建后再创建 depends_on = [aws_ecs_capacity_provider.my_capacity_provider] }
完整修正后的Terraform脚本
provider "aws" { region = "ap-south-1" } resource "aws_key_pair" "my_key_pair" { key_name = "any" public_key = file("~/.ssh/any.pub") } resource "aws_security_group" "my_security_group" { name = "ecs-demo-security-group" description = "Allow SSH, HTTP traffic and ECS required outbound" vpc_id = "vpc-xxxx" # 替换为你的VPC ID ingress { from_port = 22 to_port = 22 protocol = "tcp" cidr_blocks = ["0.0.0.0/0"] } ingress { from_port = 3000 to_port = 3000 protocol = "tcp" cidr_blocks = ["0.0.0.0/0"] } # 添加ECS实例必需的出站规则 egress { from_port = 0 to_port = 0 protocol = "-1" cidr_blocks = ["0.0.0.0/0"] } } resource "aws_ecs_cluster" "my_cluster" { name = "ecs-demo" # 关联Capacity Provider capacity_providers = [aws_ecs_capacity_provider.my_capacity_provider.name] default_capacity_provider_strategy { capacity_provider = aws_ecs_capacity_provider.my_capacity_provider.name weight = 1 base = 1 } # 确保集群在Capacity Provider创建后再创建 depends_on = [aws_ecs_capacity_provider.my_capacity_provider] } resource "aws_iam_role" "my_execution_role" { name = "ecs-demo-execution-role" assume_role_policy = jsonencode({ Version = "2012-10-17", Statement = [ { Action = "sts:AssumeRole", Effect = "Allow", Principal = { Service = "ecs-tasks.amazonaws.com" } } ] }) } resource "aws_iam_role_policy_attachment" "ecs_execution_role_attachment" { policy_arn = "arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy" role = aws_iam_role.my_execution_role.name } resource "aws_iam_role" "ecs_instance_role" { name = "ecs-instance-role" assume_role_policy = jsonencode({ Version = "2012-10-17", Statement = [ { Action = "sts:AssumeRole", Effect = "Allow", Principal = { Service = "ec2.amazonaws.com" } } ] }) } resource "aws_iam_role_policy_attachment" "ecs_instance_role_attachment" { policy_arn = "arn:aws:iam::aws:policy/service-role/AmazonEC2ContainerServiceforEC2Role" role = aws_iam_role.ecs_instance_role.name } resource "aws_iam_instance_profile" "ecs_instance_profile" { name = "ecs-instance-profile" role = aws_iam_role.ecs_instance_role.name } resource "aws_ecs_capacity_provider" "my_capacity_provider" { name = "my-ecs-demo-capacity-provider" auto_scaling_group_provider { auto_scaling_group_arn = aws_autoscaling_group.my_autoscaling_group.arn managed_scaling { status = "ENABLED" target_capacity = 100 } managed_termination_protection = "DISABLED" # 可选,根据需要调整 } tags = { Name = "ecs-demo" } } resource "aws_launch_template" "my_launch_template" { name = "ecs-demo-launch-template" image_id = "ami-076bbae7511f2cc74" # 确认该AMI是对应区域的ECS优化AMI block_device_mappings { device_name = "/dev/xvda" ebs { volume_size = 30 volume_type = "gp2" } } key_name = aws_key_pair.my_key_pair.key_name instance_type = "t2.micro" iam_instance_profile { name = aws_iam_instance_profile.ecs_instance_profile.name } network_interfaces { security_groups=[aws_security_group.my_security_group.id] } user_data = base64encode(<<-EOF #!/bin/bash echo ECS_CLUSTER=${aws_ecs_cluster.my_cluster.name} >> /etc/ecs/ecs.config echo ECS_BACKEND_HOST= >> /etc/ecs/ecs.config EOF ) tag_specifications { resource_type = "instance" tags = { Name = "ecs-demo" } } lifecycle { create_before_destroy = true } } resource "aws_autoscaling_group" "my_autoscaling_group" { desired_capacity = 1 max_size = 2 min_size = 1 mixed_instances_policy { launch_template { launch_template_specification { launch_template_id = aws_launch_template.my_launch_template.id version = "$Latest" } } instances_distribution { spot_allocation_strategy = "lowest-price" on_demand_allocation_strategy = "prioritized" on_demand_base_capacity = 0 on_demand_percentage_above_base_capacity = 0 } } vpc_zone_identifier = ["subnet-xxxx"] # 替换为你的子网IDs tag { key = "AmazonECSManaged" value = true propagate_at_launch = true } } resource "aws_ecs_task_definition" "my_task" { family = "ecs-demo-task" network_mode = "awsvpc" requires_compatibilities = ["EC2"] cpu = "256" memory = "512" execution_role_arn = aws_iam_role.my_execution_role.arn container_definitions = <<DEFINITION [ { "name": "ecs-demo", "image": "ecr_image_arn", # 替换为你的ECR镜像ARN "cpu": 256, "memory": 512, "essential": true, "portMappings": [ { "containerPort": 80, "hostPort": 80 } ] } ] DEFINITION } resource "aws_ecs_service" "my_ecs_service" { name = "ecs-demo-service" cluster = aws_ecs_cluster.my_cluster.id task_definition = aws_ecs_task_definition.my_task.arn desired_count = 1 launch_type = "EC2" network_configuration { subnets = ["subnet-xxxx"] # 替换为你的子网IDs security_groups = [aws_security_group.my_security_group.id] } }
额外注意事项
- 确认使用的AMI是ap-south-1区域的ECS优化AMI,避免因系统缺少ECS Agent导致连接失败
- 替换脚本中所有
vpc-xxxx、subnet-xxxx、ecr_image_arn为你的实际资源信息 - 检查ECS实例角色权限,
AmazonEC2ContainerServiceforEC2Role策略已包含实例与集群通信的必要权限
内容的提问来源于stack exchange,提问作者Butani Hardik
相关产品推荐
相关产品推荐

