我们通过定义一个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_definition
和aws_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}")}"
...
}