You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

EC2实例在私有子网时AWS ECS任务无法找到容器实例的解决方法

解决ECS在私有子网EC2实例上部署失败的问题

核心原因

私有子网内的EC2实例默认没有公网出口,无法连接AWS ECS控制平面端点(如ecs.<region>.amazonaws.com),也没法拉取容器镜像,导致实例无法注册到ECS集群,最终服务找不到可用实例触发报错。

具体配置方案

1. 给私有子网配置NAT网关(实现公网访问能力)

私有子网内的ECS实例需要通过NAT网关访问公网,才能完成ECS代理注册、镜像拉取等操作。Terraform配置示例:

# 为NAT网关分配弹性公网IP
resource "aws_eip" "nat_eip" {
  vpc = true
}

# 创建NAT网关(必须部署在公有子网)
resource "aws_nat_gateway" "nat" {
  allocation_id = aws_eip.nat_eip.id
  subnet_id     = aws_subnet.public_subnet.id
}

# 私有子网路由表:将所有公网流量指向NAT网关
resource "aws_route_table" "private" {
  vpc_id = aws_vpc.main.id

  route {
    cidr_block     = "0.0.0.0/0"
    nat_gateway_id = aws_nat_gateway.nat.id
  }
}

# 关联私有子网与路由表
resource "aws_route_table_association" "private_subnet" {
  subnet_id      = aws_subnet.private_subnet.id
  route_table_id = aws_route_table.private.id
}

2. 配置EC2实例的IAM角色权限

EC2实例需要权限向ECS集群注册自身,以及访问ECR拉取镜像。直接使用AWS托管策略即可满足需求:

# 创建ECS实例角色
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"
      }
    }]
  })
}

# 附加ECS实例托管策略
resource "aws_iam_role_policy_attachment" "ecs_instance_policy" {
  role       = aws_iam_role.ecs_instance_role.name
  policy_arn = "arn:aws:iam::aws:policy/service-role/AmazonEC2ContainerServiceforEC2Role"
}

# 创建实例配置文件,关联到EC2实例
resource "aws_iam_instance_profile" "ecs_instance_profile" {
  name = "ecs-instance-profile"
  role = aws_iam_role.ecs_instance_role.name
}

3. 配置EC2实例的用户数据(指定ECS集群)

使用AWS官方的ECS优化AMI(预装ECS代理),通过用户数据指定实例要加入的ECS集群:

resource "aws_instance" "ecs_instance" {
  ami           = "ami-xxxxxx" # 替换为对应区域的ECS优化AMI,可在AWS控制台查询
  instance_type = "t2.micro"
  subnet_id     = aws_subnet.private_subnet.id
  iam_instance_profile = aws_iam_instance_profile.ecs_instance_profile.name
  vpc_security_group_ids = [aws_security_group.ecs_instance_sg.id]

  user_data = <<-EOF
              #!/bin/bash
              echo "ECS_CLUSTER=your-cluster-name" >> /etc/ecs/ecs.config
              # 可选:如果需要调试,开启ECS代理日志
              echo "ECS_LOGLEVEL=debug" >> /etc/ecs/ecs.config
              EOF

  tags = {
    Name = "ECS-Private-Instance"
  }
}

4. 安全组配置

EC2实例的安全组只需开放出站规则,满足与ECS控制平面、镜像仓库的通信需求:

resource "aws_security_group" "ecs_instance_sg" {
  name        = "ecs-instance-sg"
  description = "Allow outbound traffic for ECS instance"
  vpc_id      = aws_vpc.main.id

  # 允许所有出站流量(或限制到AWS服务网段,更安全)
  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }

  tags = {
    Name = "ECS-Instance-SG"
  }
}

5. ECS服务与任务定义配置

确保ECS服务指定私有子网,且不分配公网IP(内部访问场景):

resource "aws_ecs_service" "ecs_service" {
  name            = "ecs-service-name"
  cluster         = aws_ecs_cluster.main.id
  task_definition = aws_ecs_task_definition.main.arn
  desired_count   = 1

  network_configuration {
    subnets          = [aws_subnet.private_subnet.id]
    security_groups  = [aws_security_group.ecs_task_sg.id]
    assign_public_ip = false # 私有子网内无需公网IP
  }
}

验证步骤

  1. 登录ECS控制台,查看集群的「容器实例」数量,确认私有子网的EC2已成功注册
  2. 查看EC2实例的系统日志(CloudWatch Logs),检查ECS代理启动日志是否有连接错误
  3. 检查私有子网路由表,确认0.0.0.0/0路由指向NAT网关
  4. 确认IAM角色的托管策略已正确附加

内容的提问来源于stack exchange,提问作者Guillaume

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 12:53:11