我们通过定义template_file在Terraform中创建ECS服务,该文件使用所有需要的变量填充任务定义JSON模板。然后,使用渲染的template_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
)之外,还有其他方法吗?
答案 0 :(得分:0)
Modules是在Terraform中解决此问题的主要方法。
如果将现有代码移动到单个文件夹中,则可以定义允许您自定义该模块的变量,例如要传递给ECS服务的命令。
因此,在您的情况下,您可能会遇到类似这样的情况:
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}")}"
# ...
}
variable "command" {}
module "foo_service_web" {
source = "../modules/foo-service"
command = "bundle exec server"
}
module "foo_service_sidekiq" {
source = "../modules/foo-service"
command = "bundle exec sidekiq"
}
答案 1 :(得分:0)
扩展接受的答案,以显示如何还消除由template_file
vars块中的已定义变量引起的重复(该重复不会改变,因此在模块调用之间必须重复)。这也不是仅内联这些变量或使用默认值的解决方案,因为它们仍将在项目之间更改,只是不在同一项目的服务中更改。我们可以使用局部变量来设置默认值,并使用合并功能覆盖默认值:
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}"
}
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}")}"
...
}