Terraform 推送 Cloudformation 堆栈。如何从参数创建字符串列表
Terraform pushing Cloudformation stacks. How to make a string list from parameters
我正在与有线外壳作斗争。
我需要推送使用 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 因为缺少引号..
你知道我有一些偷偷摸摸的技巧是如何实现的吗?
构建表示序列化数据结构的字符串时,使用 Terraform 的内置序列化函数来构建结果要容易得多,而不是尝试使用字符串模板生成有效的字符串。
在这种情况下,我们可以使用jsonencode
to construct a JSON string representing the template_body
from a Terraform object value, which then allows using all of the Terraform language expression features来构建它:
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
,我使用 the flatten
function along with a for
expression 将嵌套的 local.single_az_node_groups
数据结构转换为目标组 ARN 字符串的平面列表。
CloudFormation 同时支持 JSON 和 YAML,Terraform 也有一个 yamlencode
function,您可以在这里使用它来代替 jsonencode
。我选择 jsonencode
既是因为 yamlencode
目前被标记为实验性的(它生成的确切 YAML 格式可能会在以后的版本中改变),也是因为 Terraform 在计划输出中对 JSON 格式有特殊支持它可以显示内部数据结构的结构差异,而不是基于字符串的差异。
我正在与有线外壳作斗争。 我需要推送使用 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 因为缺少引号..
你知道我有一些偷偷摸摸的技巧是如何实现的吗?
构建表示序列化数据结构的字符串时,使用 Terraform 的内置序列化函数来构建结果要容易得多,而不是尝试使用字符串模板生成有效的字符串。
在这种情况下,我们可以使用jsonencode
to construct a JSON string representing the template_body
from a Terraform object value, which then allows using all of the Terraform language expression features来构建它:
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
,我使用 the flatten
function along with a for
expression 将嵌套的 local.single_az_node_groups
数据结构转换为目标组 ARN 字符串的平面列表。
CloudFormation 同时支持 JSON 和 YAML,Terraform 也有一个 yamlencode
function,您可以在这里使用它来代替 jsonencode
。我选择 jsonencode
既是因为 yamlencode
目前被标记为实验性的(它生成的确切 YAML 格式可能会在以后的版本中改变),也是因为 Terraform 在计划输出中对 JSON 格式有特殊支持它可以显示内部数据结构的结构差异,而不是基于字符串的差异。