Как избежать дублирования в terraform при наличии нескольких сервисов в ECS, которые отличаются только командой? - PullRequest
0 голосов
/ 01 марта 2019

Мы создаем службы ECS в Terraform, определяя файл template_file, который заполняет шаблон JSON определения задачи всеми необходимыми переменными.Затем создается aws_ecs_task_definition с визуализированным шаблоном template_file.С этим определением задачи создается 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 вместовеб-приложение).

Есть ли другой способ сделать это, кроме дублирования всего (шаблон JSON, template_file со всеми определенными переменными, aws_ecs_task_definition и aws_ecs_service)?

Ответы [ 2 ]

0 голосов
/ 03 марта 2019

Расширение принятого ответа, чтобы показать, как также устранить дублирование, вызванное определенными переменными в блоке 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}")}"
  ...
}
0 голосов
/ 01 марта 2019

Модули являются основным способом решения этой проблемы в Terraform.

Если вы переместите существующий код в одну папку, вы можете определить переменные, которые позволят вам настроить этот модуль, например:команда для передачи в службу ECS.

Так что в вашем случае у вас может быть что-то вроде этого:

modules / 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}")}"
  # ...
}

modules / foo-service / variables.tf

variable "command" {}

staging / 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"
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...