terraform 不断强制使用默认参数替换容器定义的新资源/强制

aas*_*yas 5 amazon-web-services amazon-ecs terraform

我提出了aws_ecs_task_defintion以下 terraform 配置。

local.image_tag作为变量传递来通过 terraform 控制 ecr 图像的部署。

我能够在初始 terraform 计划/应用周期中调出 ecs_cluster 。

然而,在随后的 terraform plan/apply 周期中,terraform 强制使用新的容器定义,这就是为什么即使我们的 ecr 映像也要重新部署整个任务定义local.image_tag保持不变也要重新部署整个任务定义

这种行为会导致意外的任务定义回收,而无需对 ecr 图像进行任何更改,而只是使用默认值强制 terraform 值。

TF配置

resource "aws_ecs_task_definition" "this_task" {
  family                   = "this-service"
  execution_role_arn       = var.this_role
  task_role_arn            = var.this_role
  network_mode             = "awsvpc"
  requires_compatibilities = ["FARGATE"]
  cpu                      = 256
  memory                   = var.env != "prod" ? 512 : 1024
  tags                     = local.common_tags
  # Log the to datadog if it's running in the prod account.
  container_definitions = (
    <<TASK_DEFINITION
[
    {
        "essential": true,
        "image": "AWS_ACCOUNT_ID.dkr.ecr.us-west-2.amazonaws.com/thisisservice:${local.image_tag}",
        "environment" :[
            {"name":"ID", "value":"${jsondecode(data.aws_secretsmanager_secret_version.this_decrypt.secret_string)["id"]}"},
            {"name":"SECRET","value":"${jsondecode(data.aws_secretsmanager_secret_version.this_decrypt.secret_string)["secret"]}"},
            {"name":"THIS_SOCKET_URL","value":"${local.websocket_url}"},
            {"name":"THIS_PLATFORM_API","value":"${local.platform_api}"},
            {"name":"REDISURL","value":"${var.redis_url}"},
            {"name":"BASE_S3","value":"${aws_s3_bucket.ec2_vp.id}"}
        ],
        "name": "ec2-vp",
        "logConfiguration": {
            "logDriver": "awsfirelens",
            "options": {
                "Name": "datadog",
                "apikey": "${jsondecode(data.aws_secretsmanager_secret_version.datadog_api_key[0].secret_string)["api_key"]}",
                "Host": "http-intake.logs.datadoghq.com",
                "dd_service": "this",
                "dd_source": "this",
                "dd_message_key": "log",
                "dd_tags": "cluster:${var.cluster_id},Env:${var.env}",
                "TLS": "on",
                "provider": "ecs"
            }
        },
        "portMappings": [
            {
                "containerPort": 443,
                "hostPort": 443
            }
        ]
    },
    {
        "essential": true,
        "image": "amazon/aws-for-fluent-bit:latest",
        "name": "log_router",
        "firelensConfiguration": {
            "type": "fluentbit",
            "options": { "enable-ecs-log-metadata": "true" }
        }
    
    }
]
TASK_DEFINITION
)
}
Run Code Online (Sandbox Code Playgroud)



-/+ resource "aws_ecs_task_definition" "this_task" {
              ~ arn                      = "arn:aws:ecs:ca-central-1:AWS_ACCOUNT_ID:task-definition/this:4" -> (known after apply)
              ~ container_definitions    = jsonencode(
                  ~ [ # forces replacement
                      ~ {
                          - cpu              = 0 -> null
                            environment      = [
                                {
                                    name  = "BASE_S3"
                                    value = "thisisthevalue"
                                },
                                {
                                    name  = "THIS_PLATFORM_API"
                                    value = "thisisthevlaue"
                                },
                                {
                                    name  = "SECRET"
                                    value = "thisisthesecret"
                                },
                                {
                                    name  = "ID"
                                    value = "thisistheid"
                                },
                                {
                                    name  = "THIS_SOCKET_URL"
                                    value = "thisisthevalue"
                                },
                                {
                                    name  = "REDISURL"
                                    value = "thisisthevalue"
                                },
                            ]
                            essential        = true
                            image            = "AWS_ACCOUNT_ID.dkr.ecr.us-west-2.amazonaws.com/this:v1.0.0-develop.6"
                            logConfiguration = {
                                logDriver = "awsfirelens"
                                options   = {
                                    Host           = "http-intake.logs.datadoghq.com"
                                    Name           = "datadog"
                                    TLS            = "on"
                                    apikey         = "thisisthekey"
                                    dd_message_key = "log"
                                    dd_service     = "this"
                                    dd_source      = "this"
                                    dd_tags        = "thisisthetags"
                                    provider       = "ecs"
                                }
                            }
                          - mountPoints      = [] -> null
                            name             = "ec2-vp"
                          ~ portMappings     = [
                              ~ {
                                    containerPort = 443
                                    hostPort      = 443
                                  - protocol      = "tcp" -> null
                                },
                            ]
                          - volumesFrom      = [] -> null
                        } # forces replacement,
                      ~ {
                          - cpu                   = 0 -> null
                          - environment           = [] -> null
                            essential             = true
                            firelensConfiguration = {
                                options = {
                                    enable-ecs-log-metadata = "true"
                                }
                                type    = "fluentbit"
                            }
                            image                 = "amazon/aws-for-fluent-bit:latest"
                          - mountPoints           = [] -> null
                            name                  = "log_router"
                          - portMappings          = [] -> null
                          - user                  = "0" -> null
                          - volumesFrom           = [] -> null
                        } # forces replacement,
                    ]
                )
                cpu                      = "256"
                execution_role_arn       = "arn:aws:iam::AWS_ACCOUNTID:role/thisistherole"
                family                   = "this"
              ~ id                       = "this-service" -> (known after apply)
                memory                   = "512"
                network_mode             = "awsvpc"
                requires_compatibilities = [
                    "FARGATE",
                ]
              ~ revision                 = 4 -> (known after apply)
                tags                     = {
                    "Cluster"      = "this"
                    "Env"          = "this"
                    "Name"         = "this"
                    "Owner"        = "this"
                    "Proj"         = "this"
                    "SuperCluster" = "this"
                    "Terraform"    = "true"
                }
                task_role_arn            = "arn:aws:iam::AWS_ACCOUNT+ID:role/thisistherole"
            }
Run Code Online (Sandbox Code Playgroud)

上面是强制执行新任务定义/容器定义的 terraform 计划。

正如您所看到的,terraform 正在将所有默认值替换为 null 或空。我仔细检查了上次运行生成的 terraform.tfstate 文件,这些值与上面计划中显示的值完全相同。

我不确定为什么会发生这种意外行为,并希望获得一些有关如何解决此问题的线索。

我正在使用 terraform 0.12.25 和最新的 terraform aws 提供商。

aas*_*yas 5

此问题存在一个已知的terraform aws 提供程序错误。

为了使 terraform 不替换正在运行的任务/容器定义,我必须使用 null 或空配置集填写 terraform 计划上显示的所有默认值。

填写完所有参数后,我再次运行 terafform 计划/应用周期,以确保它不会像以前那样替换容器定义。