#terraform #terraform-provider-aws
#terraform #terraform-provider-aws
Вопрос:
Я хотел бы поместить пару ресурсов в модуль terrafrom. у этого одного из ресурсов есть aws_ecs_service
некоторые необязательные аргументы, которые мне могут понадобиться или не понадобиться, и я хотел бы передать значения при вызове модулей.
Например, рассмотрим ordered_placement_strategy
аргумент. Служба может иметь один или несколько ordered_placement_strategy . Некоторые службы могут иметь или не иметь placement_constraints
. Как я могу написать гибкий универсальный модуль для aws_ecs_service.
resource "aws_ecs_service" "mongo" {
name = "mongodb"
cluster = aws_ecs_cluster.foo.id
task_definition = aws_ecs_task_definition.mongo.arn
desired_count = 3
iam_role = aws_iam_role.foo.arn
depends_on = [aws_iam_role_policy.foo]
ordered_placement_strategy {
type = "binpack"
field = "cpu"
}
load_balancer {
target_group_arn = aws_lb_target_group.foo.arn
container_name = "mongo"
container_port = 8080
}
placement_constraints {
type = "memberOf"
expression = "attribute:ecs.availability-zone in [us-west-2a, us-west-2b]"
}
}
Ответ №1:
Выглядит как надежный вариант использования для локальных динамических блоков.
Это поможет, если вы уже знаете стратегии размещения задач, которые должны поддерживаться в модуле. Вы можете предоставить конечным пользователям входную переменную и использовать ее для создания соответствующей службы.
Например: допустим, мы хотим поддерживать два вида сервисов:
- простой
- сложный
Сначала я бы определил входную переменную с такой проверкой, чтобы избежать неизвестных:
variable "ecs_service_type" {
type = string
description = "What kind of service is this?"
validation {
condition = can(regex("^(simple|complex)$", var.ecs_service_type))
error_message = "The service type must be in (simple|complex)."
}
}
Вы можете определить поддерживаемые стратегии размещения задач и ограничения, используя локальные значения, подобные этому:
locals {
ordered_placement_strategy = {
simple = [
{
"field" : "instanceId",
"type" : "spread"
}
]
complex = [
{
type = "spread"
field = "attribute:ecs.availability-zone"
},
{
type = "spread"
field = "instanceId"
}
]
}
placement_constraints = {
simple = []
complex = [
{
type = "distinctInstance"
}
]
}
}
И, в конце концов, создайте сервис соответствующим образом, используя динамические блоки:
resource "aws_ecs_service" "service" {
...
...
dynamic "ordered_placement_strategy" {
for_each = local.ordered_placement_strategy[var.ecs_service_type]
content {
type = ordered_placement_strategy.value.type
field = ordered_placement_strategy.value.field
}
}
dynamic "placement_constraints" {
for_each = local.placement_constraints[var.ecs_service_type]
content {
type = placement_constraints.value.type
}
}
}
PS: этот конкретный фрагмент кода не тестировался, но я использовал аналогичные подходы. Дайте мне знать, если вам понадобится помощь в чем-либо.
Комментарии:
1. Спасибо, это полезно, но два вопроса. нужно ли нам использовать local или мы можем использовать variable? Это делается для того, чтобы затем иметь все значения в my .tfvars. Во-вторых, я не понимаю этого local.placement_constraints[var.ecs_service_type]. В локальном определении нет ссылки на ecs_service_type .
2. @kumar — Итак, есть много способов сделать это. Я предпочел locals для этого варианта использования, поскольку хотел упростить принятие решений для конечных пользователей. Подробнее по этой теме: — learn.hashicorp.com/tutorials/terraform/locals — medium.com/@pavloosadchyi /… Вы можете проверить эти общедоступные модули ecs и решить, какой подход соответствует вашим потребностям: — github.com/infrablocks/terraform-aws-ecs-service — github.com/trussworks/terraform-aws-ecs-service