第10天— Terraform 条件表达式、动态块和 Splat 表达式
发布: (2025年12月4日 GMT+8 00:56)
5 min read
原文: Dev.to
Source: Dev.to
条件表达式
条件表达式会评估一个条件,并根据条件为真或为假返回两个值中的一个。
语法
condition ? true_value : false_value
使用场景
- 根据环境(
dev与prod)选择实例类型 - 根据配置启用/禁用监控
- 根据地区选择不同的 AMI
- 为不同环境设置不同的资源计数
- 应用特定环境的标签
好处
- 单一配置即可支持多个环境
- 减少代码重复
- 使环境差异显式化
- 简化配置管理
- 易于理解和维护
何时使用
- 环境特定的配置
- 功能标记(启用/禁用功能)
- 条件资源创建
- 区域特定设置
- 成本优化(在开发环境使用更小的资源)
不建议使用的情况
- 逻辑复杂且条件众多(此时请使用
locals) - 当单独的环境文件更清晰时
- 当所有环境应保持完全相同
示例
resource "aws_instance" "conditional_example" {
ami = "ami-28765345876"
instance_type = var.environment == "prod" ? "t3.large" : "t2.micro"
tags = {
Name = "conditional-instance-${var.environment}"
}
}
运行 terraform plan 会显示基于 environment 变量选择的实例类型:
terraform plan
data.aws_ami.amazon_linux: Reading...
data.aws_ami.amazon_linux: Read complete after 1s [id=ami-02610f36df0c59544]
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated
with the following symbols:
+ create
# aws_instance.conditional_example will be created
+ resource "aws_instance" "conditional_example" {
+ ami = "ami-02610f36df0c59544"
+ instance_type = "t2.micro"
# ... other attributes omitted for brevity
}
在此示例中,如果 var.environment 被设置为 "prod",实例类型将为 t3.large;否则默认使用 t2.micro。
动态块
动态块根据集合(列表或映射)生成资源内部的多个嵌套块,省去手动重复相似块配置的需求。
语法
dynamic "block_name" {
for_each = var.collection
content {
# 使用 each.key 和 each.value 的块配置
}
}
for_each用于遍历列表或映射。content定义每个生成块的内容。- 通过
each.key与each.value访问值。
使用场景
- 安全组的入站/出站规则
- EC2 实例上的多个 EBS 卷
- IAM 策略语句
- 负载均衡器监听器
- 路由表路由
- 任何需要重复的嵌套块结构
好处
- 消除重复代码
- 轻松添加或删除条目
- 配置由变量驱动
- 代码更清晰、更易维护
- 支持复杂的数据结构
何时使用
- 多个相似的嵌套块
- 配置数量可变
- 安全组规则
- 内联策略
- 任意重复的块模式
不建议使用的情况
- 单个或少量静态块(开销不值得)
- 当它使代码更难阅读时
- 对于顶层资源请使用
count或for_each(而非动态块)
示例
resource "aws_security_group" "dynamic_sg" {
name = "dynamic-sg-${var.environment}"
description = "Security group with dynamic rules"
dynamic "ingress" {
for_each = var.ingress_rules
content {
from_port = ingress.value.from_port
to_port = ingress.value.to_port
protocol = ingress.value.protocol
cidr_blocks = ingress.value.cidr_blocks
description = ingress.value.description
}
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
tags = {
Name = "dynamic-sg-${var.environment}"
}
}
variable "ingress_rules" {
description = "List of ingress rules for security group"
type = list(object({
from_port = number
to_port = number
protocol = string
cidr_blocks = list(string)
description = string
}))
default = [
{
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
description = "HTTP"
},
{
from_port = 443
to_port = 443
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
description = "HTTPS"
}
]
}
运行 terraform plan 会显示动态创建的入站规则:
# aws_security_group.dynamic_sg will be created
+ resource "aws_security_group" "dynamic_sg" {
+ arn = (known after apply)
+ description = "Security group with dynamic rules"
+ egress = [
{
+ cidr_blocks = ["0.0.0.0/0"]
+ from_port = 0
+ protocol = "-1"
+ to_port = 0
}
]
+ ingress = [
{
+ from_port = 80
+ to_port = 80
+ protocol = "tcp"
+ cidr_blocks = ["0.0.0.0/0"]
+ description = "HTTP"
},
{
+ from_port = 443
+ to_port = 443
+ protocol = "tcp"
+ cidr_blocks = ["0.0.0.0/0"]
+ description = "HTTPS"
}
]
# ... other attributes omitted for brevity
}
动态块遍历 var.ingress_rules,为每条规则创建一个 ingress 块,无需手动复制。
