HCL 语法基础 #

什么是 HCL? #

HCL(HashiCorp Configuration Language)是 HashiCorp 开发的配置语言,专门用于定义基础设施配置。它是一种声明式语言,设计目标是既易于人类阅读和编写,又易于机器解析和处理。

text
┌─────────────────────────────────────────────────────────────┐
│                    HCL 特点                                  │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐         │
│  │  声明式      │  │  可读性强    │  │  JSON 兼容   │         │
│  └─────────────┘  └─────────────┘  └─────────────┘         │
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐         │
│  │  类型丰富    │  │  表达式强大  │  │  模块化      │         │
│  └─────────────┘  └─────────────┘  └─────────────┘         │
│                                                             │
└─────────────────────────────────────────────────────────────┘

基本语法结构 #

顶层结构 #

HCL 配置由一系列顶层块组成:

hcl
resource "aws_instance" "example" {
  ami           = "ami-0c55b159cbfafe1f0"
  instance_type = "t2.micro"
  
  tags = {
    Name = "example-instance"
  }
}

块(Block) #

块是 HCL 的核心结构,用于定义配置对象:

text
┌─────────────────────────────────────────────────────────────┐
│                    块的结构                                  │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  <块类型> "<标签1>" "<标签2>" {                             │
│    <参数名> = <参数值>                                      │
│    <参数名> = <参数值>                                      │
│  }                                                          │
│                                                             │
│  示例:                                                     │
│  resource "aws_instance" "example" {                        │
│    ami           = "ami-123456"                             │
│    instance_type = "t2.micro"                               │
│  }                                                          │
│                                                             │
│  组成部分:                                                 │
│  - 块类型:resource                                         │
│  - 标签:aws_instance, example                              │
│  - 块体:大括号内的内容                                     │
│                                                             │
└─────────────────────────────────────────────────────────────┘

常见块类型 #

hcl
terraform {
  required_version = ">= 1.0.0"
}

provider "aws" {
  region = "us-east-1"
}

resource "aws_instance" "example" {
  ami           = "ami-0c55b159cbfafe1f0"
  instance_type = "t2.micro"
}

data "aws_ami" "latest" {
  most_recent = true
  owners      = ["amazon"]
}

variable "instance_type" {
  default     = "t2.micro"
  description = "EC2 instance type"
}

output "instance_ip" {
  value = aws_instance.example.public_ip
}

locals {
  common_tags = {
    Environment = "dev"
    Project     = "my-project"
  }
}

module "vpc" {
  source = "./modules/vpc"
  
  cidr_block = "10.0.0.0/16"
}

参数与参数值 #

参数定义 #

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

参数值类型 #

text
┌─────────────────────────────────────────────────────────────┐
│                    基本类型                                  │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  字符串 (string)                                            │
│  ami = "ami-0c55b159cbfafe1f0"                              │
│  name = "my-instance"                                       │
│                                                             │
│  数字 (number)                                              │
│  count = 3                                                  │
│  port  = 8080                                               │
│  size   = 100.5                                             │
│                                                             │
│  布尔值 (bool)                                              │
│  enabled   = true                                           │
│  monitoring = false                                         │
│                                                             │
│  空值 (null)                                                │
│  description = null                                         │
│                                                             │
└─────────────────────────────────────────────────────────────┘

复合类型 #

hcl
list_of_strings = ["a", "b", "c"]

list_of_numbers = [1, 2, 3, 4, 5]

map_of_strings = {
  key1 = "value1"
  key2 = "value2"
}

map_of_numbers = {
  small  = 1
  medium = 2
  large  = 3
}

set_of_strings = toset(["a", "b", "c"])

object_type = {
  name = "example"
  size = 10
  tags = ["web", "frontend"]
}

tuple_type = ["string", 123, true]

注释 #

单行注释 #

hcl
provider "aws" {
  region = "us-east-1"
}

resource "aws_instance" "example" {
  ami           = "ami-0c55b159cbfafe1f0"
  instance_type = "t2.micro"
}

多行注释 #

hcl
/*
 * 这是一个多行注释
 * 可以跨越多行
 * 用于详细说明
 */
resource "aws_instance" "example" {
  ami           = "ami-0c55b159cbfafe1f0"
  instance_type = "t2.micro"
}

字符串 #

字符串字面量 #

hcl
name = "my-instance"

description = 'Simple description'

多行字符串 #

hcl
user_data = <<-EOF
  #!/bin/bash
  echo "Hello, World!"
  yum update -y
  yum install -y httpd
  systemctl start httpd
EOF

字符串插值 #

hcl
name = "instance-${var.environment}"

url = "https://${var.domain}/api"

message = "Hello, ${var.name}!"

字符串模板 #

hcl
policy = jsonencode({
  Version = "2012-10-17"
  Statement = [
    {
      Action   = "s3:GetObject"
      Effect   = "Allow"
      Resource = "arn:aws:s3:::${var.bucket_name}/*"
    }
  ]
})

集合类型 #

列表(List) #

hcl
variable "availability_zones" {
  type    = list(string)
  default = ["us-east-1a", "us-east-1b", "us-east-1c"]
}

resource "aws_subnet" "example" {
  count             = length(var.availability_zones)
  availability_zone = var.availability_zones[count.index]
}

映射(Map) #

hcl
variable "instance_types" {
  type = map(string)
  default = {
    dev     = "t2.micro"
    staging = "t2.small"
    prod    = "t2.medium"
  }
}

resource "aws_instance" "example" {
  instance_type = var.instance_types[var.environment]
}

集合(Set) #

hcl
variable "ports" {
  type    = set(number)
  default = [80, 443, 8080]
}

resource "aws_security_group_rule" "ingress" {
  for_each = var.ports
  
  type              = "ingress"
  from_port         = each.value
  to_port           = each.value
  protocol          = "tcp"
  security_group_id = aws_security_group.example.id
}

对象与元组 #

对象类型 #

hcl
variable "server_config" {
  type = object({
    name          = string
    instance_type = string
    volume_size   = number
    tags          = map(string)
  })
  default = {
    name          = "web-server"
    instance_type = "t2.micro"
    volume_size   = 20
    tags = {
      Environment = "dev"
    }
  }
}

元组类型 #

hcl
variable "mixed_values" {
  type    = tuple([string, number, bool])
  default = ["hello", 42, true]
}

表达式 #

算术运算 #

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

比较运算 #

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

逻辑运算 #

hcl
and_op  = true && false
or_op   = true || false
not_op  = !true

条件表达式 #

hcl
instance_type = var.environment == "prod" ? "t2.large" : "t2.micro"

size = var.create_large ? 100 : 50

name = var.name != "" ? var.name : "default-name"

for 表达式 #

hcl
simple_list = [for s in var.list : upper(s)]

with_filter = [for s in var.list : upper(s) if s != ""]

map_transform = {for s in var.list : s => upper(s)}

with_index = [for i, s in var.list : "${i}: ${s}"]

nested = [for item in var.items : item.name if item.enabled]

展开表达式 #

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

resource "aws_subnet" "example" {
  for_each = toset(var.availability_zones)
  
  availability_zone = each.value
}

subnets = aws_subnet.example[*].id

names = [for item in var.items : item.name...]

splat 表达式 #

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

all_ids = aws_instance.example[*].id

all_ips = aws_instance.example[*].public_ip

first_ip = aws_instance.example[0].public_ip

动态块 #

基本语法 #

hcl
resource "aws_security_group" "example" {
  name = "example-sg"
  
  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
resource "aws_security_group" "example" {
  name = "example-sg"
  
  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
resource "aws_instance" "example" {
  ami           = "ami-0c55b159cbfafe1f0"
  instance_type = "t2.micro"
  
  dynamic "ebs_block_device" {
    for_each = var.ebs_volumes
    content {
      device_name = ebs_block_device.value.device_name
      volume_size = ebs_block_device.value.size
      
      dynamic "tags" {
        for_each = ebs_block_device.value.tags
        content {
          key   = tags.key
          value = tags.value
        }
      }
    }
  }
}

类型约束 #

基本类型约束 #

hcl
variable "name" {
  type = string
}

variable "count" {
  type = number
}

variable "enabled" {
  type = bool
}

复杂类型约束 #

hcl
variable "names" {
  type = list(string)
}

variable "ports" {
  type = list(number)
}

variable "tags" {
  type = map(string)
}

variable "config" {
  type = object({
    name = string
    size = number
  })
}

variable "items" {
  type = tuple([string, number, bool])
}

any 类型 #

hcl
variable "value" {
  type = any
}

可选属性 #

hcl
variable "config" {
  type = object({
    name = string
    size = optional(number, 10)
    tags = optional(map(string), {})
  })
}

文件组织 #

推荐的文件结构 #

text
project/
├── main.tf          主配置文件
├── variables.tf     输入变量定义
├── outputs.tf       输出值定义
├── providers.tf     Provider 配置
├── locals.tf        本地值定义
├── data.tf          数据源定义
├── versions.tf      版本约束
├── terraform.tfvars 变量值文件
└── README.md        项目说明

文件命名约定 #

hcl
main.tf         主要资源配置
variables.tf    变量定义
outputs.tf      输出定义
providers.tf    Provider 配置
backend.tf      后端配置
versions.tf     版本约束
data.tf         数据源
locals.tf       本地值
modules.tf      模块调用

JSON 语法 #

HCL 也支持 JSON 格式:

json
{
  "resource": {
    "aws_instance": {
      "example": {
        "ami": "ami-0c55b159cbfafe1f0",
        "instance_type": "t2.micro",
        "tags": {
          "Name": "example-instance"
        }
      }
    }
  }
}

代码风格 #

格式化 #

bash
terraform fmt

推荐风格 #

hcl
resource "aws_instance" "example" {
  ami           = "ami-0c55b159cbfafe1f0"
  instance_type = "t2.micro"
  
  tags = {
    Name        = "example-instance"
    Environment = var.environment
  }
  
  root_block_device {
    volume_size = 20
    volume_type = "gp3"
  }
}

对齐参数 #

hcl
resource "aws_instance" "example" {
  ami                    = "ami-0c55b159cbfafe1f0"
  instance_type          = "t2.micro"
  monitoring             = true
  disable_api_termination = false
}

下一步 #

掌握了 HCL 语法基础后,接下来学习 第一个资源,实际创建一个基础设施资源!

最后更新:2026-03-29