创建灵活的地形模块以自定义可选参数时

When creating flexible terraform module to customize optional parameters

我想将一些资源放入 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]"
  }
}

看起来像是 locals + dynamic blocks 的可靠用例。

如果您已经了解模块中应支持的任务放置策略,将会有所帮助。您可以向最终用户公开一个输入变量,并使用它来相应地创建服务。

例如:假设我们要支持两种服务:

  • 简单
  • 复杂

我会首先像这样定义一个带有验证的输入变量,以避免未知数:

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:这段特定的代码没有经过测试,但我使用了类似的方法。如果您需要任何帮助,请告诉我。