0

我正在与有线案例作斗争。我需要推送使用 terraform 动态参数化的 cloudformation 堆栈。

我的资源看起来像这样。

resource "aws_cloudformation_stack" "eks-single-az" {
  count = length(var.single_az_node_groups)
  name = "eks-${var.cluster_name}-${var.single_az_node_groups[count.index].name}"

  template_body = <<EOF
Description: "eks-${var.cluster_name}-${var.single_az_node_groups[count.index].name}"

Resources:
  ASG:
    Type: AWS::AutoScaling::AutoScalingGroup
    Properties:
      AutoScalingGroupName: "eks-${var.cluster_name}-${var.single_az_node_groups[count.index].name}"
      VPCZoneIdentifier: ["${var.private_subnet_ids[count.index]}"]
      MinSize: "${lookup(var.single_az_node_groups[count.index], "asg_min", "0")}"
      MaxSize: "${lookup(var.single_az_node_groups[count.index], "asg_max", "10")}"
      HealthCheckType: EC2
      TargetGroupARNs: [] < - here is error. 
      MixedInstancesPolicy:
        InstancesDistribution:
          OnDemandBaseCapacity: "0"
          OnDemandPercentageAboveBaseCapacity: "${lookup(var.single_az_node_groups[count.index], "on_demand_percentage", "0")}"
        LaunchTemplate:
          LaunchTemplateSpecification:
            LaunchTemplateId: "${aws_launch_template.eks-single-az[count.index].id}"
            Version: "${aws_launch_template.eks-single-az[count.index].latest_version}"
          Overrides:
            - 
              InstanceType: m5.large
      Tags:
        - Key: "Name"
          Value: "eks-${var.cluster_name}-${var.single_az_node_groups[count.index].name}"
          PropagateAtLaunch: true
        - Key: "kubernetes.io/cluster/${var.cluster_name}"
          Value: "owned"
          PropagateAtLaunch: true
        - Key: "k8s.io/cluster-autoscaler/enabled"
          Value: "true"
          PropagateAtLaunch: true
        - Key: "k8s.io/cluster-autoscaler/${var.cluster_name}"
          Value: "true"
          PropagateAtLaunch: true
    UpdatePolicy:
      AutoScalingRollingUpdate:
        MinSuccessfulInstancesPercent: 80
        MinInstancesInService: "${lookup(data.external.desired_capacity.result, "eks-${var.cluster_name}-${var.single_az_node_groups[count.index].name}", "0")}"
        PauseTime: PT4M
        SuspendProcesses:
          - HealthCheck
          - ReplaceUnhealthy
          - AZRebalance
          - AlarmNotification
          - ScheduledActions
        WaitOnResourceSignals: true
  EOF

depends_on = [
  aws_launch_template.eks-single-az
]

}

我需要从包含 json 对象的列表中放入目标组:

single_az_node_groups = [
  {
    "name"          : "workload-az1",
    "instance_type" : "t2.micro",
    "asg_min"       : "1",
    "asg_max"       : "7",
    "target_group_arns" : "arnA, arnB, arnC"
  },
  ...
]

我什么都试过了。问题是我尝试了许多 terraform 函数,并且一直 terraform 添加一些 cloudformation 不支持的双引号,或者 terraform 由于缺少引号而无法处理 template_body 。
你知道一些偷偷摸摸的技巧如何实现吗?

4

1 回答 1

0

在构建表示序列化数据结构的字符串时,使用 Terraform 的内置序列化函数来构建结果要容易得多,而不是尝试使用字符串模板生成有效的字符串。

在这种情况下,我们可以使用从 Terraform 对象值jsonencode构造表示 的 JSON 字符串template_body,然后允许使用所有Terraform 语言表达式功能来构建它:

  template_body = jsonencode({
    Description: "eks-${var.cluster_name}-${var.single_az_node_groups[count.index].name}",

    Resources: {
      ASG: {
        Type: "AWS::AutoScaling::AutoScalingGroup",
        Properties: {
          AutoScalingGroupName: "eks-${var.cluster_name}-${var.single_az_node_groups[count.index].name}",
          VPCZoneIdentifier: [var.private_subnet_ids[count.index]],
          MinSize: lookup(var.single_az_node_groups[count.index], "asg_min", "0"),
          MaxSize: lookup(var.single_az_node_groups[count.index], "asg_max", "10"),
          HealthCheckType: "EC2",
          TargetGroupArns: flatten([
            for g in local.single_az_node_groups : [
              split(", ", g.target_group_arns)
            ]
          ]),
          # etc, etc
        },
      },
    },
  })

正如您在上面看到的,通过使用jsonencode整个数据结构,我们可以使用 Terraform 表达式运算符来构建值。在TargetGroupArns上面的示例中,我使用函数flatten表达式for嵌套local.single_az_node_groups数据结构转换为目标组 ARN 字符串的平面列表。


CloudFormation 支持 JSON 和 YAML,Terraform 也有一个你可以使用的yamlencode函数jsonencode,而不是这里。我选择jsonencode这两个是因为yamlencode目前被标记为实验性的(它产生的确切 YAML 格式可能会在以后的版本中更改)并且因为 Terraform 在计划输出中对 JSON 格式有特殊支持,它可以显示内部数据结构的结构差异,而不是比基于字符串的差异。

于 2020-01-23T18:37:13.030 回答