개발하자

Terraform은 컨테이너 정의에 대해 기본 매개 변수를 사용하여 새로운 리소스/강제 교체를 계속 강제합니다

Cuire 2023. 8. 25. 21:40
반응형

Terraform은 컨테이너 정의에 대해 기본 매개 변수를 사용하여 새로운 리소스/강제 교체를 계속 강제합니다

나는 다음과 같은 테라폼 구성을 생각해내고 있다.

나는 테라폼을 통해 ECR 이미지의 배치를 제어하기 위한 변수로 전달한다.

나는 초기 테라폼 계획/적용 주기에 따라 ecs_클러스터를 정상적으로 가동할 수 있다.

그러나 후속 테라폼 계획/적용 주기에서 테라폼은 새 컨테이너 정의를 강제로 적용하고 있으며, 이는 ECR 이미지가 그대로 유지됨에도 불구하고 전체 작업 정의를 재배치하는 이유입니다

이 동작으로 인해 ECR 이미지에 변경 사항 없이 의도하지 않은 작업 정의가 재활용되고 기본값이 설정된 강제 값만 지형적으로 적용됩니다.

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
)
}



-/+ 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"
            }

위는 새로운 작업 정의/컨테이너 정의를 강제하는 테라폼 계획입니다.

보시다시피 테라폼은 모든 기본값을 null 또는 빈 값으로 대체하고 있습니다. 나는 이전 실행에서 이미 생성된 terraform.tfstate 파일을 다시 확인했고 그 값은 위의 계획에 표시된 것과 정확히 같다.

나는 왜 이 의도하지 않은 행동이 일어나고 있는지 확신할 수 없고 이것을 고치는 방법에 대한 단서를 가지고 싶다.

나는 테라폼 0.12.25와 최신 테라폼 악스 제공자를 사용하고 있다.




이 문제로 알려진 것이 있습니다.

테라폼이 실행 중인 작업/컨테이너 정의를 대체하지 않도록 하려면 테라폼 계획에 표시되는 모든 기본값을 null 또는 빈 구성 집합으로 작성해야 합니다.

모든 매개 변수가 작성되면 이전처럼 컨테이너 정의를 대체하지 않도록 테라폼 계획/적용 주기를 다시 실행했습니다.




사이드카 용기로 가지고 있어도 같은 문제가 발생했습니다. 이 컨테이너 정의에 추가하는 것은 태스크 정의가 강제로 다시 생성되는 것을 방지할 수 있는 최소한의 방법입니다.

{
  "name": "log_router",
  "image": "public.ecr.aws/aws-observability/aws-for-fluent-bit:latest",
  "logConfiguration": null,
  "firelensConfiguration": {
    "type": "fluentbit",
    "options": {
      "enable-ecs-log-metadata": "true"
    }
  },
  "user": "0"
}



이전 답변과 논평에서 언급한 바와 같이, 오늘날 작업 정의는 종종 교체를 강제하고 신뢰할 수 없는 차이를 보여준다.

하지만 저는 AWS 공급업체에서 이와 같은 문제를 피할 수 있었습니다

  • 해당 구성에 별도의 설정을 만듭니다
  • 내부에서, 대신 를 사용하거나 와 유사한 항목을 사용합니다.

하지만, 혹은 당신이 코드에 설정한 무엇이든. 작동하려면 매개 변수 조작이 필요합니다.

자세한 내용:


반응형