在EC中拥有多个服务仅在命令中有多个服务时,如何避免在Terraform中重复



我们通过定义一个template_file来创建terraform的ECS服务,该模板file填充了任务定义JSON模板,其中所有需要的变量。然后使用渲染模板_File创建aws_ecs_task_definition。使用此任务定义,创建了aws_ecs_service

data "template_file" "web" {
  template = "${file("${path.module}/tasks/web.json")}"
  vars {
    ...
  }
}
resource "aws_ecs_task_definition" "web" {
  container_definitions    = "${data.template_file.web.rendered}"
  requires_compatibilities = ["FARGATE"]
  ...
}
data "aws_ecs_task_definition" "web" {
  task_definition = "${aws_ecs_task_definition.web.family}"
}
resource "aws_ecs_service" "web" {
  name            = "web"
  task_definition = "${aws_ecs_task_definition.web.family}:${max("${aws_ecs_task_definition.web.revision}", "${data.aws_ecs_task_definition.web.revision}")}"
  ...
}

还有其他服务定义几乎与第一个相同的服务,只有一个小差异(例如启动sidekiq而不是Web应用程序)。

)。

除了复制所有内容(json模板,带有所有定义变量的 template_file),aws_ecs_task_definitionaws_ecs_service)是否有其他方法?

模块是在Terraform中解决此问题的主要方法。

如果将现有代码移至单个文件夹中,则可以定义变量,使您可以自定义该模块,例如将命令传递到您的ECS服务。

因此,在您的情况下,您可能会有类似的东西:

模块/foo-service/main.tf

data "template_file" "web" {
  template = "${file("${path.module}/tasks/web.json")}"
  vars {
    # ...
    command = "${var.command}"
  }
}
resource "aws_ecs_task_definition" "web" {
  container_definitions    = "${data.template_file.web.rendered}"
  requires_compatibilities = ["FARGATE"]
  # ...
}
data "aws_ecs_task_definition" "web" {
  task_definition = "${aws_ecs_task_definition.web.family}"
}
resource "aws_ecs_service" "web" {
  name            = "web"
  task_definition = "${aws_ecs_task_definition.web.family}:${max("${aws_ecs_task_definition.web.revision}", "${data.aws_ecs_task_definition.web.revision}")}"
  # ...
}

模块/foo-service/variables.tf

variable "command" {}

登台/main.tf

module "foo_service_web" {
  source  = "../modules/foo-service"
  command = "bundle exec server"
}
module "foo_service_sidekiq" {
  source  = "../modules/foo-service"
  command = "bundle exec sidekiq"
}

在接受的答案上扩展,以展示如何删除由template_file vars块中定义的变量引起的重复(它们不会更改,因此必须在之间重复模块)。它也不是仅在这些变量内串联或使用默认值的解决方案,因为它们仍然会在项目之间发生变化,而不在同一项目的服务中。我们可以使用局部变量来设置使用合并函数的默认值和覆盖默认值:

main.tf

locals {
  task_variables = {
    image = "..."
    # lots of other variables
    command = "["nginx", "-g", "daemon off; error_log /dev/stdout info;"]"
  }
}
# first invocation of the module, overriding the command
module "sidekiq" {
  source = "ecs_service"
  ...
  task_variables = "${merge(
    local.task_variables,
    map(
      "command", "["bash", "-c", "exec bundle exec sidekiq"]",
    )
  )}"
}
# second invocation of the module, no overrides
module "web" {
  source = "ecs_service"
  task_variables = "${local.task_variables}"
}

模块ECS_Service

variable "task_variables" {
  type = "map"
}
data "template_file" "web_task" {
  template = "${file("${path.module}/tasks/task_definition.json")}"
  vars = "${var.task_variables}"
}
resource "aws_ecs_task_definition" "web" {
  container_definitions    = "${data.template_file.web_task.rendered}"
  ...
}
data "aws_ecs_task_definition" "web" {
  task_definition = "${aws_ecs_task_definition.web.family}"
  ...
}
resource "aws_ecs_service" "web" {
  task_definition = "${aws_ecs_task_definition.web.family}:${max("${aws_ecs_task_definition.web.revision}", "${data.aws_ecs_task_definition.web.revision}")}"
  ...
}

最新更新