Terraform 表达式与条件 #

表达式概述 #

表达式是 Terraform 配置中用于计算值的核心语法。它可以引用变量、资源属性、函数调用等,是构建动态配置的基础。

text
┌─────────────────────────────────────────────────────────────┐
│                    表达式类型                                │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  字面量      字符串、数字、布尔值                           │
│  引用        变量、资源属性、模块输出                       │
│  运算符      算术、比较、逻辑                               │
│  条件        三元条件表达式                                 │
│  for         循环转换                                       │
│  splat       展开表达式                                     │
│  动态块      动态生成配置块                                 │
│                                                             │
└─────────────────────────────────────────────────────────────┘

条件表达式 #

基本语法 #

hcl
condition ? true_value : false_value

简单条件 #

hcl
variable "environment" {
  default = "prod"
}

locals {
  instance_type = var.environment == "prod" ? "t2.large" : "t2.micro"
}

resource "aws_instance" "example" {
  instance_type = local.instance_type
}

嵌套条件 #

hcl
locals {
  instance_type = var.environment == "prod" ? "t2.large" : (
    var.environment == "staging" ? "t2.medium" : "t2.micro"
  )
}

条件创建资源 #

hcl
variable "create_instance" {
  default = true
}

resource "aws_instance" "example" {
  count = var.create_instance ? 1 : 0
  
  ami           = "ami-0c55b159cbfafe1f0"
  instance_type = "t2.micro"
}

条件属性 #

hcl
resource "aws_instance" "example" {
  ami           = "ami-0c55b159cbfafe1f0"
  instance_type = "t2.micro"
  
  monitoring = var.enable_monitoring ? true : false
}

使用 coalesce #

hcl
locals {
  name = coalesce(var.name, "default-name")
}

locals {
  tags = coalesce(var.tags, {})
}

for 表达式 #

基本语法 #

hcl
[for item in list : expression]

[for item in list : expression if condition]

{for key, value in map : key => value}

列表转换 #

hcl
variable "names" {
  default = ["alice", "bob", "charlie"]
}

locals {
  upper_names = [for name in var.names : upper(name)]
}

output "upper_names" {
  value = local.upper_names
}

带过滤 #

hcl
variable "numbers" {
  default = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
}

locals {
  even_numbers = [for n in var.numbers : n if n % 2 == 0]
}

output "even_numbers" {
  value = local.even_numbers
}

带索引 #

hcl
variable "items" {
  default = ["a", "b", "c"]
}

locals {
  indexed = [for i, item in var.items : "${i}: ${item}"]
}

output "indexed" {
  value = local.indexed
}

映射转换 #

hcl
variable "users" {
  default = {
    alice = 30
    bob   = 25
    charlie = 35
  }
}

locals {
  user_list = [for name, age in var.users : "${name} is ${age}"]
  
  age_map = {for name, age in var.users : name => age * 365}
}

output "user_list" {
  value = local.user_list
}

对象列表转换 #

hcl
variable "servers" {
  default = [
    {
      name = "web-1"
      type = "t2.micro"
    },
    {
      name = "web-2"
      type = "t2.small"
    }
  ]
}

locals {
  server_names = [for s in var.servers : s.name]
  
  server_map = {for s in var.servers : s.name => s.type}
  
  filtered_servers = [for s in var.servers : s.name if s.type == "t2.micro"]
}

分组 #

hcl
variable "items" {
  default = [
    { name = "a", type = "web" },
    { name = "b", type = "api" },
    { name = "c", type = "web" }
  ]
}

locals {
  by_type = {
    for item in var.items : item.type => item.name...
  }
}

output "by_type" {
  value = local.by_type
}

splat 表达式 #

全属性展开 #

hcl
resource "aws_instance" "web" {
  count = 3
  
  ami           = "ami-0c55b159cbfafe1f0"
  instance_type = "t2.micro"
}

output "instance_ids" {
  value = aws_instance.web[*].id
}

output "instance_ips" {
  value = aws_instance.web[*].public_ip
}

嵌套属性 #

hcl
resource "aws_instance" "web" {
  count = 2
  
  ami           = "ami-0c55b159cbfafe1f0"
  instance_type = "t2.micro"
  
  tags = {
    Name = "web-${count.index}"
  }
}

output "instance_names" {
  value = aws_instance.web[*].tags.Name
}

条件展开 #

hcl
variable "create_instances" {
  default = true
}

resource "aws_instance" "web" {
  count = var.create_instances ? 3 : 0
  
  ami           = "ami-0c55b159cbfafe1f0"
  instance_type = "t2.micro"
}

output "instance_ids" {
  value = aws_instance.web[*].id
}

动态块 #

基本语法 #

hcl
resource "aws_security_group" "example" {
  name = "example"
  
  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
    }
  }
}

完整示例 #

hcl
variable "ingress_rules" {
  default = [
    {
      from_port   = 22
      to_port     = 22
      protocol    = "tcp"
      cidr_blocks = ["0.0.0.0/0"]
    },
    {
      from_port   = 80
      to_port     = 80
      protocol    = "tcp"
      cidr_blocks = ["0.0.0.0/0"]
    },
    {
      from_port   = 443
      to_port     = 443
      protocol    = "tcp"
      cidr_blocks = ["0.0.0.0/0"]
    }
  ]
}

resource "aws_security_group" "web" {
  name        = "web-sg"
  description = "Web server security group"
  vpc_id      = aws_vpc.main.id
  
  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
    }
  }
  
  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }
}

使用迭代器 #

hcl
resource "aws_security_group" "example" {
  name = "example"
  
  dynamic "ingress" {
    for_each = var.ingress_rules
    iterator = rule
    
    content {
      from_port   = rule.value.from_port
      to_port     = rule.value.to_port
      protocol    = rule.value.protocol
      cidr_blocks = rule.value.cidr_blocks
    }
  }
}

嵌套动态块 #

hcl
variable "rules" {
  default = [
    {
      type        = "ingress"
      from_port   = 22
      to_port     = 22
      protocol    = "tcp"
      cidr_blocks = ["0.0.0.0/0"]
    }
  ]
}

resource "aws_security_group" "example" {
  name = "example"
  
  dynamic "ingress" {
    for_each = [for r in var.rules : r if r.type == "ingress"]
    content {
      from_port   = ingress.value.from_port
      to_port     = ingress.value.to_port
      protocol    = ingress.value.protocol
      cidr_blocks = ingress.value.cidr_blocks
    }
  }
  
  dynamic "egress" {
    for_each = [for r in var.rules : r if r.type == "egress"]
    content {
      from_port   = egress.value.from_port
      to_port     = egress.value.to_port
      protocol    = egress.value.protocol
      cidr_blocks = egress.value.cidr_blocks
    }
  }
}

动态标签 #

hcl
variable "tags" {
  default = {
    Environment = "production"
    Project     = "my-project"
  }
}

resource "aws_instance" "example" {
  ami           = "ami-0c55b159cbfafe1f0"
  instance_type = "t2.micro"
  
  dynamic "tags" {
    for_each = var.tags
    content {
      key   = tags.key
      value = tags.value
    }
  }
}

运算符 #

算术运算符 #

hcl
locals {
  sum        = 1 + 2
  difference = 10 - 5
  product    = 3 * 4
  quotient   = 15 / 3
  modulo     = 10 % 3
  negation   = -5
}

比较运算符 #

hcl
locals {
  equal        = 5 == 5
  not_equal    = 5 != 3
  greater      = 10 > 5
  less         = 3 < 5
  greater_eq   = 5 >= 5
  less_eq      = 3 <= 5
}

逻辑运算符 #

hcl
locals {
  and_op = true && false
  or_op  = true || false
  not_op = !true
}

复杂表达式示例 #

环境配置 #

hcl
variable "environment" {
  default = "prod"
}

locals {
  config = {
    dev = {
      instance_type = "t2.micro"
      min_size      = 1
      max_size      = 2
    }
    staging = {
      instance_type = "t2.small"
      min_size      = 2
      max_size      = 4
    }
    prod = {
      instance_type = "t2.large"
      min_size      = 3
      max_size      = 6
    }
  }
  
  current_config = local.config[var.environment]
}

resource "aws_autoscaling_group" "web" {
  min_size = local.current_config.min_size
  max_size = local.current_config.max_size
  
  launch_template {
    id = aws_launch_template.web.id
  }
}

子网 CIDR 计算 #

hcl
variable "vpc_cidr" {
  default = "10.0.0.0/16"
}

variable "availability_zones" {
  default = ["us-east-1a", "us-east-1b", "us-east-1c"]
}

locals {
  public_subnet_cidrs = [
    for i, az in var.availability_zones : cidrsubnet(var.vpc_cidr, 8, i)
  ]
  
  private_subnet_cidrs = [
    for i, az in var.availability_zones : cidrsubnet(var.vpc_cidr, 8, i + 10)
  ]
}

resource "aws_subnet" "public" {
  count             = length(var.availability_zones)
  vpc_id            = aws_vpc.main.id
  cidr_block        = local.public_subnet_cidrs[count.index]
  availability_zone = var.availability_zones[count.index]
}

标签合并 #

hcl
variable "default_tags" {
  default = {
    ManagedBy = "terraform"
  }
}

variable "extra_tags" {
  default = {}
}

locals {
  common_tags = merge(
    var.default_tags,
    {
      Environment = var.environment
      Project     = var.project_name
    },
    var.extra_tags
  )
}

resource "aws_instance" "example" {
  ami           = "ami-0c55b159cbfafe1f0"
  instance_type = "t2.micro"
  
  tags = merge(local.common_tags, {
    Name = "${var.project_name}-${var.environment}"
  })
}

条件资源创建 #

hcl
variable "create_vpc" {
  default = true
}

variable "vpc_id" {
  default = null
}

data "aws_vpc" "existing" {
  count = var.create_vpc ? 0 : 1
  id    = var.vpc_id
}

resource "aws_vpc" "main" {
  count = var.create_vpc ? 1 : 0
  
  cidr_block = "10.0.0.0/16"
}

locals {
  vpc_id = var.create_vpc ? aws_vpc.main[0].id : data.aws_vpc.existing[0].id
}

下一步 #

掌握了表达式与条件后,接下来学习 Provisioners,了解如何在资源创建后执行操作!

最后更新:2026-03-29