为ECS任务/容器创建AWS CloudWatch日志组的Terraform配置

17

我正在尝试使用Terraform创建一个AWS ECS任务,该任务将日志放置在CloudWatch上的特定日志组中。问题是容器定义位于JSON文件中,而且我无法从.tf文件将CloudWatch组名称映射到该.json文件中。

container_definition.json:

[
  {
    "name": "supreme-task",
    "image": "xxxx50690yyyy.dkr.ecr.eu-central-1.amazonaws.com/supreme-task",
    "essential": true,
    "portMappings": [
      {
        "containerPort": 5000,
        "hostPort": 5000
      }
    ],
    "logConfiguration": {
      "logDriver": "awslogs",
      "options": {
        "awslogs-group": "supreme-task-group",  <- This needs to be taken from variable.tf file.
        "awslogs-region": "eu-central-1",
        "awslogs-stream-prefix": "streaming"
      }
    }
  }
]

变量.tf:


variable "ecs_task_definition_name" {
  description = "Task definition name."
  type = string
  default = "supreme-task-def"
}

variable "task_role" {
  description = "Name of the task role."
  type = string
  default = "supreme-task-role"
}

variable "task_execution_role" {
  description = "Name of the task execution role."
  type = string
  default = "supreme-task-exec-role"
}

variable "cloudwatch_group" {
  description = "CloudWatch group name."
  type = string
  default = "supreme-task-group"
}

任务定义:

resource "aws_ecs_task_definition" "task_definition" {
  family = var.ecs_task_definition_name
  requires_compatibilities = ["FARGATE"]
  network_mode = "awsvpc"
  cpu = 1024
  memory = 4096
  container_definitions = file("modules/ecs-supreme-task/task-definition.json")
  execution_role_arn = aws_iam_role.task_execution_role.name
  task_role_arn = aws_iam_role.task_role.name
}

有没有一种方法可以做到这一点?或者也许应该用不同的方法来完成这个任务?


2
你尝试过使用插值(通过在HEREDOC中内联JSON)或使用Terraform的模板特性吗? - ydaetskcoR
使用内联JSON进行插值,非常感谢! :) - dextertron_
你想要自己回答吗? - ydaetskcoR
不需要,你可以做到。 - dextertron_
3个回答

30

按照 @ydaetskcorR 的评论解决。

将容器定义作为内联参数。

container_definitions = <<DEFINITION
    [
      {
        "name": "${var.repository_name}",
        "image": "${var.repository_uri}",
        "essential": true,
        "portMappings": [
          {
            "containerPort": 5000,
            "hostPort": 5000
          }
        ],
        "logConfiguration": {
          "logDriver": "awslogs",
          "options": {
            "awslogs-group": "${var.cloudwatch_group}",
            "awslogs-region": "eu-central-1",
            "awslogs-stream-prefix": "ecs"
          }
        }
      }
    ]
    DEFINITION

我尝试了这个,但对我不起作用。ECS任务定义中的container_definitions无效:解码JSON时出错:在对象键值对之后存在无效字符“"”。 - Kalyan Raparthi
这是两年前的事情了,terraform的API可能已经发生了变化。 - dextertron_
TF需要获取JSON编码的字符串,我相信第一行应该是container_definitions = jsonencode([ ,没有使用heredoc(<<DEFINITION)。 - nnsense
它在 Terraform v1.6.2 中完美运行。我不知道为什么,但是使用 jsonencode 的相同配置对我来说不起作用。 - undefined

4
如果想要将容器定义加载为模板,以避免在tf文件中使用内容内联,则可以按照以下步骤进行:
1. 创建一个带有变量的容器定义模板文件,注意扩展名应为.tpl
container_definition.tpl
[
  {
    "name": "supreme-task",
    "image": "xxxx50690yyyy.dkr.ecr.eu-central-1.amazonaws.com/supreme-task",
    "essential": true,
    "portMappings": [
      {
        "containerPort": 5000,
        "hostPort": 5000
      }
    ],
    "logConfiguration": {
      "logDriver": "awslogs",
      "options": {
        "awslogs-group": "${cloudwatch_group}",
        "awslogs-region": "eu-central-1",
        "awslogs-stream-prefix": "streaming"
      }
    }
  }
]

2- 然后将文件作为模板加载并注入变量:

task_definition.tf

data template_file task_definition {
  template = file("${path.module}/container_definition.tpl")

  vars = {
    cloudwatch_group = var.cloudwatch_group
  }
}

resource "aws_ecs_task_definition" "task_definition" {
  family = var.ecs_task_definition_name
  requires_compatibilities = ["FARGATE"]
  network_mode = "awsvpc"
  cpu = 1024
  memory = 4096
  container_definitions = data.template_file.task_definition.rendered
  execution_role_arn = aws_iam_role.task_execution_role.name
  task_role_arn = aws_iam_role.task_role.name
}

0
你可以在terraform中这样做 -
# Container definition
    container_definitions = jsonencode([
        {
            name                    = "app-container-test"
            image                   = "acc_id.dkr.ecr.region.amazonaws.com/repository-test:4"
            cpu                     = 256
            memory                  = 512
            port_mappings = [
                {
                    container_port  = 80
                    host_port       = 80
                    protocol        = "tcp"
                }
            ]
            logConfiguration = {
            logDriver = "awslogs"
            options   = {
                "awslogs-group"         = "fargate-logs-test"
                "awslogs-region"        = var.aws_region
                "awslogs-stream-prefix" = "ecs"
            }
        }
        }

不要忘记添加日志权限(角色、策略)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接