Terraform速查手册
Terraform HCL/state/模块/常用函数速查
📝 HCL 基础语法
最核心的块:资源类型.本地名称 构成唯一地址。
resource "aws_instance" "web" {
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t3.micro"
tags = {
Name = "${var.project}-web"
Environment = var.env
}
}
支持三种注释;${} 内可放任意表达式;<<- 是多行字符串。
# 井号行注释
// 双斜杠行注释
/* 块注释 */
locals {
name = "${var.project}-${var.env}" # 插值
count = 3
raw = <<-EOT
line1 ${var.env}
line2
EOT
}
count.index 从 0 开始;count=0 可不创建。
resource "aws_instance" "web" {
count = var.instance_count
ami = "ami-xxx"
instance_type = "t3.micro"
tags = {
Name = "web-${count.index}"
}
}
# 引用:aws_instance.web[0].id
# 全部 ID:aws_instance.web[*].id
比 count 更稳:增删某键不影响其他资源的地址。
resource "aws_instance" "web" {
for_each = {
api = "t3.small"
job = "t3.micro"
}
ami = "ami-xxx"
instance_type = each.value
tags = {
Name = "web-${each.key}"
}
}
# 引用:aws_instance.web["api"].id
控制创建/更新/销毁策略;ignore_changes 忽略外部变更。
resource "aws_instance" "web" {
# ...
lifecycle {
create_before_destroy = true
prevent_destroy = false
ignore_changes = [
ami,
tags["LastScaledAt"]
]
}
}
循环生成 ingress/rule 这类重复嵌套块。
resource "aws_security_group" "web" {
name = "web-sg"
dynamic "ingress" {
for_each = var.allowed_ports
content {
from_port = ingress.value
to_port = ingress.value
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
}
}
🔌 provider
~> 允许补丁与次版本升级;建议提交 .terraform.lock.hcl。
terraform {
required_version = ">= 1.6.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
random = {
source = "hashicorp/random"
version = ">= 3.5.0"
}
}
}
provider "aws" {
region = "cn-north-1"
}
同类型多地域/多账号时用 alias,资源上显式选择。
provider "aws" {
region = "cn-north-1"
alias = "beijing"
}
provider "aws" {
region = "cn-northwest-1"
alias = "ningxia"
}
resource "aws_instance" "bj" {
provider = aws.beijing
# ...
}
resource "aws_instance" "nx" {
provider = aws.ningxia
# ...
}
🔎 data 与资源引用
查询已有基础设施信息,不创建/修改资源。
data "aws_ami" "ubuntu" {
most_recent = true
owners = ["099720109477"]
filter {
name = "name"
values = ["ubuntu/images/hvm-ssd/*/22.04/*"]
}
}
resource "aws_instance" "web" {
ami = data.aws_ami.ubuntu.id
}
data "aws_caller_identity" "current" {}
output "account_id" {
value = data.aws_caller_identity.current.account_id
}
通过引用隐式建立依赖;显式依赖用 depends_on。
resource "aws_vpc" "main" {
cidr_block = "10.0.0.0/16"
}
resource "aws_subnet" "app" {
vpc_id = aws_vpc.main.id # 隐式依赖
cidr_block = "10.0.1.0/24"
}
resource "aws_s3_bucket" "logs" {
depends_on = [aws_subnet.app] # 显式依赖
bucket = "my-logs"
}
🎛 variable 变量
string/number/bool;可给默认值、描述与校验规则。
variable "env" {
type = string
description = "部署环境:dev / staging / prod"
default = "dev"
validation {
condition = contains(["dev", "staging", "prod"], var.env)
error_message = "env 必须是 dev/staging/prod 之一"
}
}
variable "instance_count" {
type = number
default = 1
}
variable "enable_https" {
type = bool
default = true
}
list/map/set/object 组合表达结构化配置。
variable "ports" {
type = list(number)
default = [80, 443]
}
variable "tags" {
type = map(string)
default = {
Project = "demo"
Owner = "ops"
}
}
variable "app" {
type = object({
name = string
replicas = number
envs = map(string)
})
}
sensitive=true 后值不会出现在日志中。
variable "db_password" {
type = string
sensitive = true
nullable = false
}
variable "endpoint" {
type = string
default = null # 允许为空,代码中用条件判断
}
# 引用
resource "aws_db_instance" "main" {
password = var.db_password
}
terraform.tfvars 自动加载,其他文件用 -var-file 指定。
# prod.tfvars
env = "prod"
instance_count = 3
ports = [80, 443, 8080]
tags = {
Project = "demo"
}
# 命令行
terraform apply -var-file="prod.tfvars"
terraform apply -var="env=test" -var="instance_count=2"
TF_VAR_env=prod terraform plan
🧮 locals 与 output
给重复表达式命名,类似常量/派生配置,不暴露给外部。
locals {
name_prefix = "${var.project}-${var.env}"
common_tags = {
Project = var.project
Environment = var.env
ManagedBy = "terraform"
}
bucket_suffix = "abc123"
}
resource "aws_s3_bucket" "data" {
bucket = "${local.name_prefix}-data-${local.bucket_suffix}"
tags = local.common_tags
}
apply 后展示关键信息;sensitive 值会被打码;模块输出供外部引用。
output "public_ip" {
value = aws_instance.web.public_ip
description = "Web 服务器公网 IP"
}
output "db_password" {
value = var.db_password
sensitive = true
}
output "all_ips" {
value = aws_instance.web[*].private_ip
}
⌨️ 常用命令
日常三件套;plan 落盘后 apply 同一计划可保证不漂移。
terraform init
terraform init -upgrade # 升级 provider/模块版本
terraform plan
terraform plan -out=tfplan
terraform apply
terraform apply tfplan
terraform apply -auto-approve -var-file=prod.tfvars
state 是“真实世界”的映射,改动前先备份。
terraform destroy
terraform destroy -target=aws_instance.web
terraform state list
terraform state show aws_instance.web
terraform state mv aws_s3_bucket.a aws_s3_bucket.b
terraform state rm aws_s3_bucket.old # 解除托管但不删资源
terraform state pull > backup.tfstate
terraform state push backup.tfstate
import 纳管已有资源;-replace 强制重建单个资源。
terraform import aws_instance.web i-1234567890abcdef0
terraform import 'aws_route53_record.dns["www"]' Z123 www_example_com_A
terraform plan -replace=aws_instance.web
terraform apply -replace=aws_instance.web
terraform fmt
terraform validate
terraform console
terraform show tfplan
同一套代码在不同 state 间切换;大型项目也可用目录/后端分环境。
terraform workspace list
terraform workspace new dev
terraform workspace new prod
terraform workspace select prod
terraform workspace show # 当前工作区
# 代码中区分
resource "aws_instance" "web" {
tags = { Env = terraform.workspace }
}
🧱 模块 module
source 指定来源,version 固定模块版本。
module "vpc" {
source = "terraform-aws-modules/vpc/aws"
version = "5.8.1"
name = "main-vpc"
cidr = "10.0.0.0/16"
azs = ["cn-north-1a", "cn-north-1b"]
public_subnets = ["10.0.1.0/24", "10.0.2.0/24"]
private_subnets = ["10.0.11.0/24", "10.0.12.0/24"]
}
output "vpc_id" {
value = module.vpc.vpc_id
}
模块就是一个 .tf 目录,通过 variables.tf / outputs.tf 定义输入输出。
# modules/s3/main.tf
resource "aws_s3_bucket" "this" {
bucket = "${var.prefix}-${var.env}"
tags = var.tags
}
# 调用
module "data_bucket" {
source = "./modules/s3"
prefix = "demo"
env = var.env
tags = local.common_tags
}
# 其他 source 形式:
# source = "git::https://github.com/org/repo.git//modules/s3?ref=v1.0"
# source = "github.com/org/repo//modules/s3"
ƒ 常用内置函数
format/join/split/replace/lower/upper/chomp。
format("%s-%02d", "web", 1) # "web-01"
join(",", ["a", "b", "c"]) # "a,b,c"
split(",", "a,b,c") # ["a","b","c"]
replace("a-b-c", "-", "_") # "a_b_c"
lower("ABC") # "abc"
trimspace(" x ") # "x"
substr("hello", 0, 3) # "hel"
chomp("line\n") # "line"
merge/concat/lookup/element/flatten/zipmap 等。
merge({a=1}, {b=2}, {a=10}) # {a=10,b=2}
concat([1,2], [3,4]) # [1,2,3,4]
lookup({a="x"}, "b", "default") # "default"
element(["a","b"], 1) # "b"
flatten([[1,2],[3]]) # [1,2,3]
toset(["a","a","b"]) # ["a","b"]
keys({a=1, b=2}) # ["a","b"]
values({a=1, b=2}) # [1,2]
zipmap(["a","b"], [1,2]) # {a=1,b=2}
tonumber("12") # 12
在 HCL 内做 map/list 转换与过滤。
[for s in ["a", "bb", "ccc"] : upper(s)]
# ["A","BB","CCC"]
[for k, v in var.tags : "${k}=${v}"]
{for k, v in var.users : k => v.name if v.active}
[for p in var.ports : p if p > 1024] # 过滤
templatefile 渲染脚本模板;jsonencode/yamlencode 序列化。
file("${path.module}/conf/nginx.conf")
fileexists("${path.module}/conf/x.conf")
templatefile("${path.module}/userdata.sh", {
name = "web"
port = 8080
})
jsonencode({ name = "Tom", age = 18 })
jsondecode("{\"a\":1}")
yamlencode({ a = 1 })
base64encode("hello")
md5(file("data.txt"))
cidrsubnet("10.0.0.0/16", 8, 1) # 划子网
😶 没有匹配的条目,换个关键词试试
📖 使用说明
全程在浏览器本地运行。
操作步骤:
- 搜索或浏览分类条目;
- 查看HCL示例;
- 点击复制代码块。
💬 用户评论 (0)
还没有评论,快来抢沙发!