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

ECS部署ECR镜像时为何使用首个而非最新Task Definition?

ECS服务持续使用旧Task Definition,CodeDeploy部署停滞问题排查

问题描述

我使用CircleCI结合aws/ecr、aws/ecs orb上传新Docker镜像,预期更新ECS服务,但遇到以下问题:

  • CircleCI部署日志显示已使用最新的Task Definition(可在部署版本及appspec中查看),但ECS服务始终使用最初创建的错误Task Definition(曾错误设置镜像为SHA ID导致无法拉取)。
  • 错误Task Definition导致任务持续启动失败,CodeDeploy部署陷入停滞,无法完成版本更新。

核心配置信息

Terraform基础设施配置(关键片段)

# ECS任务定义
resource "aws_ecs_task_definition" "task_def" {
  family = "${var.app_name}-task-def-${var.env}"
  network_mode = "awsvpc"
  task_role_arn = aws_iam_role.ecs_task_role.arn
  execution_role_arn = aws_iam_role.ecs_exec_role.arn
  requires_compatibilities = ["FARGATE"]
  cpu = "256"
  memory = "512"
  container_definitions = jsonencode([
    {
      name      = "${var.app_name}-container-${var.env}"
      image     = "${data.aws_ecr_repository.ecr_repository.repository_url}:latest"
      essential = true
      portMappings = [
        {
          containerPort = var.port
          hostPort      = var.port
        },
      ]
      # 其他配置省略
    },
  ])
}

# ECS服务
resource "aws_ecs_service" "service" {
  lifecycle {
    ignore_changes = [
      task_definition,
      load_balancer,
    ]
  }
  cluster = aws_ecs_cluster.cluster.arn
  name = "${var.app_name}-service-${var.env}"
  task_definition = aws_ecs_task_definition.task_def.arn
  deployment_controller {
    type = "CODE_DEPLOY"
  }
  # 其他配置省略
}

# CodeDeploy部署组
resource "aws_codedeploy_deployment_group" "deployment_group" {
  app_name = aws_codedeploy_app.codedeploy_app.name
  deployment_config_name = "CodeDeployDefault.ECSAllAtOnce"
  auto_rollback_configuration {
    enabled = true
    events = ["DEPLOYMENT_FAILURE"]
  }
  blue_green_deployment_config {
    terminate_blue_instances_on_deployment_success {
      action                           = "TERMINATE"
      termination_wait_time_in_minutes = 5
    }
  }
  # 其他配置省略
}

CircleCI部署配置

deploy:
  executor: aws-ecr/default
  working_directory: ~/code
  parameters:
    env:
      type: string
  steps:
    - attach_workspace:
        at: ~/
    - aws-ecr/build-and-push-image:
        repo: "test-<< parameters.env >>"
        tag: "latest,${CIRCLE_BUILD_NUM}"
    - aws-ecs/update-service:
        family: "test-task-def-<< parameters.env >>"
        service-name: "test-service-<< parameters.env >>"
        cluster: "test-cluster-<< parameters.env >>"
        container-image-name-updates: "container=test-container-<< parameters.env >>,tag=${CIRCLE_BUILD_NUM}"
        deployment-controller: "CODE_DEPLOY"
        codedeploy-application-name: "test-application-<< parameters.env >>"
        codedeploy-deployment-group-name: "test-deployment-group-<< parameters.env >>"
        codedeploy-load-balanced-container-name: "test-container-<< parameters.env >>"
        codedeploy-load-balanced-container-port: 3000

问题原因分析

  1. CodeDeploy蓝绿部署未完成切换:初始错误的Task Definition导致蓝环境任务启动失败,后续CircleCI触发的部署中,绿色环境的新任务可能因权限、镜像地址等问题仍无法启动,CodeDeploy无法完成流量切换,服务活跃任务定义停留在旧版本。
  2. 停滞部署阻塞更新流程:CodeDeploy存在未完成的失败部署时,新部署可能无法正常触发,或服务会持续尝试用旧任务定义恢复失败任务。
  3. ECS执行角色权限缺失:当前Terraform配置中,ECS执行角色未添加ECR镜像拉取权限(AmazonEC2ContainerRegistryReadOnly),可能导致新Task Definition无法拉取镜像,任务启动失败。
  4. Terraform生命周期规则:ECS Service配置的lifecycle.ignore_changes = [task_definition]会阻止Terraform更新服务的任务定义,但不影响AWS API调用(如CircleCI orb),不过初始部署的旧任务定义可能成为服务默认状态,若后续部署未正确覆盖则持续保留。

解决方案

1. 清理停滞的CodeDeploy部署

  • 登录AWS CodeDeploy控制台,找到对应应用和部署组下的失败/进行中部署,手动停止或回滚。
  • 确保部署组中无阻塞状态的部署。

2. 手动验证并激活正确Task Definition

  • 登录AWS ECS控制台,创建任务定义新版本,指定正确的ECR镜像地址(如xxx.dkr.ecr.region.amazonaws.com/repo:${CIRCLE_BUILD_NUM})。
  • 手动更新ECS服务,切换到新版本任务定义,验证任务是否能正常启动。

3. 修复ECS执行角色权限

在Terraform中为ECS执行角色添加ECR只读权限:

resource "aws_iam_role_policy_attachment" "attach_ecr_readonly_to_exec_role" {
  role       = aws_iam_role.ecs_exec_role.name
  policy_arn = "arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly"
}

执行terraform apply更新权限配置。

4. 重新触发CircleCI部署

  • 确认container-image-name-updates中的容器名称与Task Definition完全匹配,tag使用正确的构建号。
  • 重新运行部署流水线,观察CodeDeploy部署流程是否正常完成,绿色环境任务是否启动成功。

5. 排查任务启动失败细节

  • 查看ECS任务的CloudWatch日志,定位任务启动失败的具体原因(如镜像拉取错误、网络配置问题、环境变量缺失等)。
  • 验证ECR镜像是否存在,权限是否正确配置。

内容的提问来源于stack exchange,提问作者Gergő Horváth

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 04:01:43