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

Terraform启用ECS Exec遇错误:需配置有效taskRoleArn

ECS Exec启用失败的Terraform配置修复方案

启用ECS Exec时触发以下错误:

InvalidParameterException: The service couldn't be updated because a valid taskRoleArn is not being used

问题根源在于ECS Exec要求两个关键条件:

  • 任务定义必须指定task_role_arn(原配置仅设置了execution_role_arn)
  • 任务角色(Task Role)和执行角色(Execution Role)都需要具备ECS Exec相关权限

以下是修复后的完整Terraform配置,关键修改已标注:

provider "aws" {
  region  = "us-east-1"
}

resource "aws_ecr_repository" "my_first_ecr_repo" {
  name = "my-first-ecr-repo" 
}

resource "aws_ecs_cluster" "my_cluster" {
  name = "my-first-cluster" 
}

# 新增:ECS任务角色(Task Role),用于容器内执行操作
resource "aws_iam_role" "ecsTaskRole" {
  name               = "ecsTaskRole"
  assume_role_policy = data.aws_iam_policy_document.ecs_task_assume_role.json
}

data "aws_iam_policy_document" "ecs_task_assume_role" {
  statement {
    actions = ["sts:AssumeRole"]
    principals {
      type        = "Service"
      identifiers = ["ecs-tasks.amazonaws.com"]
    }
  }
}

# 新增:给任务角色附加ECS Exec所需权限
resource "aws_iam_role_policy_attachment" "ecs_task_exec_access" {
  role       = aws_iam_role.ecsTaskRole.name
  policy_arn = "arn:aws:iam::aws:policy/AmazonECSContainerExecutionRolePolicy"
}

resource "aws_iam_role" "ecsTaskExecutionRole" {
  name               = "ecsTaskExecutionRole"
  assume_role_policy = data.aws_iam_policy_document.assume_role_policy.json
}

data "aws_iam_policy_document" "assume_role_policy" {
  statement {
    actions = ["sts:AssumeRole"]
    principals {
      type        = "Service"
      identifiers = ["ecs-tasks.amazonaws.com"]
    }
  }
}

resource "aws_iam_role_policy_attachment" "ecsTaskExecutionRole_policy" {
  role       = aws_iam_role.ecsTaskExecutionRole.name
  policy_arn = "arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy"
}

# 新增:给执行角色补充ECS Exec所需的SSM权限
resource "aws_iam_role_policy" "ecs_execution_ssm_policy" {
  name   = "ecs-execution-ssm-policy"
  role   = aws_iam_role.ecsTaskExecutionRole.id
  policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Effect   = "Allow"
        Action   = [
          "ssmmessages:CreateControlChannel",
          "ssmmessages:CreateDataChannel",
          "ssmmessages:OpenControlChannel",
          "ssmmessages:OpenDataChannel"
        ]
        Resource = "*"
      }
    ]
  })
}

resource "aws_default_vpc" "default_vpc" {
}

resource "aws_default_subnet" "default_subnet_a" {
  availability_zone = "us-east-1a"
}

resource "aws_default_subnet" "default_subnet_e" {
  availability_zone = "us-east-1b"
}

resource "aws_default_subnet" "default_subnet_f" {
  availability_zone = "us-east-1c"
}

resource "aws_ecs_task_definition" "my_first_task" {
  family                   = "my-first-task" 
  container_definitions    = <<DEFINITION
  [
    {
      "name": "my-first-task",
      "image": "${aws_ecr_repository.my_first_ecr_repo.repository_url}",
      "essential": true,
      "portMappings": [
        {
          "containerPort": 3000,
          "hostPort": 3000
        }
      ],
      "memory": 512,
      "cpu": 256
    }
  ]
  DEFINITION
  requires_compatibilities = ["FARGATE"] 
  network_mode             = "awsvpc"
  memory                   = 512         
  cpu                      = 256         
  execution_role_arn       = aws_iam_role.ecsTaskExecutionRole.arn
  # 修改:新增任务角色ARN指定
  task_role_arn            = aws_iam_role.ecsTaskRole.arn
}

resource "aws_ecs_service" "my_first_service" {
  name            = "my-first-service"                             
  enable_execute_command = true
  cluster         = aws_ecs_cluster.my_cluster.id             
  task_definition = aws_ecs_task_definition.my_first_task.arn
  launch_type     = "FARGATE"
  desired_count   = 3 

  load_balancer {
    target_group_arn = aws_lb_target_group.target_group.arn 
    container_name   = aws_ecs_task_definition.my_first_task.family
    container_port   = 3000 
  }

  network_configuration {
    subnets          = [aws_default_subnet.default_subnet_a.id, aws_default_subnet.default_subnet_e.id, aws_default_subnet.default_subnet_f.id]
    assign_public_ip = true 
    security_groups  = [aws_security_group.service_security_group.id] 
  }
}

resource "aws_alb" "application_load_balancer" {
  name               = "test-lb-tf" 
  load_balancer_type = "application"
  subnets = [ 
    aws_default_subnet.default_subnet_a.id,
    aws_default_subnet.default_subnet_e.id,
    aws_default_subnet.default_subnet_f.id
  ]
  
  security_groups = [aws_security_group.load_balancer_security_group.id]
}

resource "aws_security_group" "service_security_group" {
  ingress {
    from_port = 0
    to_port   = 0
    protocol  = "-1"
    
    security_groups = [aws_security_group.load_balancer_security_group.id]
  }

  egress {
    from_port   = 0 
    to_port     = 0 
    protocol    = "-1" 
    cidr_blocks = ["0.0.0.0/0"] 
  }

  # 可选但建议:添加ECS Exec所需的SSM端口出站规则
  egress {
    from_port   = 443
    to_port     = 443
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }
}

resource "aws_security_group" "load_balancer_security_group" {
  ingress {
    from_port   = 80 
    to_port     = 80
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"] 
  }

  egress {
    from_port   = 0 
    to_port     = 0 
    protocol    = "-1" 
    cidr_blocks = ["0.0.0.0/0"] 
  }
}

resource "aws_lb_target_group" "target_group" {
  name        = "target-group"
  port        = 80
  protocol    = "HTTP"
  target_type = "ip"
  vpc_id      = aws_default_vpc.default_vpc.id 
  health_check {
    matcher = "200,301,302"
    path = "/"
  }
}

resource "aws_lb_listener" "listener" {
  load_balancer_arn = aws_alb.application_load_balancer.arn 
  port              = "80"
  protocol          = "HTTP"
  default_action {
    type             = "forward"
    target_group_arn = aws_lb_target_group.target_group.arn 
  }
}

关键修改说明

  1. 新增任务角色(ecsTaskRole):ECS Exec需要任务角色授予容器内操作权限,附加AmazonECSContainerExecutionRolePolicy托管策略
  2. 补充执行角色权限:给ecsTaskExecutionRole添加自定义SSM权限,允许与SSM消息通道交互
  3. 任务定义指定task_role_arn:在aws_ecs_task_definition中新增task_role_arn字段,关联创建的任务角色
  4. 安全组优化:可选添加443端口出站规则,确保容器能连接到SSM服务

部署完成后,可通过以下命令测试ECS Exec:

aws ecs execute-command --cluster my-first-cluster --task <TASK_ID> --container my-first-task --command "/bin/sh" --interactive

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 04:42:03