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

如何用Terraform创建ECS任务定义新版本而非新任务定义

问题:Terraform每次运行重复创建ECS任务定义与集群的排查与解决

问题描述

我有一个运行多任务的AWS ECS集群,这些任务均为旧任务的修订版本,仅Docker命令中的路径存在差异。希望通过Terraform自动化流程:基于现有任务创建新版本,并在现有集群中运行采用最新任务修订版的新任务。但当前每次运行脚本都会创建新的任务定义,还误以为会创建新ECS集群,不清楚问题出在哪里。

提供的Terraform代码(main.tf)

# Provider configuration
provider "aws" {
  region = "ap-northeast-1"
}

# Read input.yaml file
data "local_file" "input" {
  filename = "input.yaml"
}

# Parse input.yaml file
locals {
  input_data = yamldecode(data.local_file.input.content)
}

# Retrieve existing ECS task definition
data "aws_ecs_task_definition" "existing_task" {
  task_definition = "modbus-simulator-fargate-task"
}

# Create new ECS task definition based on existing one with modifications
resource "aws_ecs_task_definition" "modbus_simulator" {
  family                   = data.aws_ecs_task_definition.existing_task.family
  task_role_arn            = data.aws_ecs_task_definition.existing_task.task_role_arn
  execution_role_arn       = data.aws_ecs_task_definition.existing_task.execution_role_arn
  network_mode             = data.aws_ecs_task_definition.existing_task.network_mode
  requires_compatibilities = ["FARGATE"]  # Add FARGATE here
  cpu                      = 1024      # Specify CPU here
  memory                   = 3072       # Specify memory here

  container_definitions = jsonencode([
    {
      "name": "client-server-simulator",
      "image": "337039605624.dkr.ecr.ap-northeast-1.amazonaws.com/client-server-simulator:26-june-2024",
      "cpu": 0,
      "portMappings": [
        {
          "name": "client-server-simulator-80-tcp",
          "containerPort": 80,
          "hostPort": 80,
          "protocol": "tcp",
          "appProtocol": "http"
        }
      ],
      "essential": true,
      "command": [
        "--s3-path",
        local.input_data[0].s3_path,
        "--modbus-ip",
        local.input_data[0].modbus_ip,
        "--modbus-port",
        local.input_data[0].modbus_port,
        "--interval",
        local.input_data[0].interval,
        "--edge-id",
        local.input_data[0].edge_id,
        "--location",
        local.input_data[0].location,
        "--company",
        local.input_data[0].company
      ],
      "environment": [],
      "mountPoints": [],
      "volumesFrom": [],
      "logConfiguration": {
        "logDriver": "awslogs",
        "options": {
          "awslogs-group": "/ecs/modbus-simulator-fargate-task",
          "awslogs-create-group": "true",
          "awslogs-region": "ap-northeast-1",
          "awslogs-stream-prefix": "ecs"
        }
      },
      "systemControls": []
    }
  ])
}

# Update ECS service to use the new task definition revision
resource "aws_ecs_service" "modbus_simulator_service" {
  name            = "modbus-simulator-service"
  cluster         = "modbus-simulator-cluster" # use the existing cluster
  task_definition = aws_ecs_task_definition.modbus_simulator.arn
  desired_count   = 1

  # Update only if there's a change in the task definition
  lifecycle {
    ignore_changes = [task_definition]
  }
}

编辑补充

.tfstate文件创建并存储在本地系统中,已查阅相关仓库提供的示例。


问题排查与解决步骤

1. 关于“重复创建ECS集群”的澄清

你的代码中没有定义aws_ecs_cluster资源,Terraform不会创建新集群。aws_ecs_service直接指定了现有集群名称modbus-simulator-cluster,所以集群不会被Terraform管控,更不会重复创建。你提到的“创建新集群”大概率是误解,或者之前的脚本包含集群创建逻辑。

2. 任务定义重复创建的原因与优化

(1)正常的修订版生成(符合ECS设计)

AWS ECS任务定义是不可修改的,任何变更(比如command中的参数变化)都会生成新的修订版,这是ECS的原生设计。如果是因为input.yaml中的参数每次运行都有变化,那么生成新修订版是预期行为。

(2)不必要重复创建的修复

如果是无意义的重复创建,检查以下两点:

  • 硬编码属性导致的差异:你当前硬编码了requires_compatibilities、cpu、memory,没有复用现有任务的属性,可能导致即使原任务这些属性不变,Terraform也会因为本地配置与远程不一致而创建新修订版。改为从数据源读取:
    requires_compatibilities = data.aws_ecs_task_definition.existing_task.requires_compatibilities
    cpu                      = data.aws_ecs_task_definition.existing_task.cpu
    memory                   = data.aws_ecs_task_definition.existing_task.memory
    
  • input.yaml意外变更:确保每次运行时input.yaml的内容没有被意外修改(比如换行符、空格差异),否则会触发container_definitions更新,导致新修订版生成。

3. ECS服务无法更新到最新任务定义的问题

你配置了lifecycle.ignore_changes = [task_definition],这会让Terraform忽略任务定义ARN的变化,阻止服务自动更新到新的修订版,和你“运行最新任务修订版”的需求完全相反。直接移除这段配置:

# 移除以下代码块
# lifecycle {
#   ignore_changes = [task_definition]
# }

移除后,当任务定义生成新修订版时,Terraform会自动更新ECS服务,滚动部署最新版本的任务。

4. 本地tfstate的注意事项

本地存储tfstate时,必须保证每次运行Terraform都使用同一个tfstate文件:

  • 不要删除、复制或移动tfstate文件,否则Terraform会认为是全新环境,重新创建所有管控的资源。
  • 如果是多人协作场景,建议改用远程状态存储(如AWS S3配合DynamoDB锁),避免状态冲突。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 15:32:04