Terraform 基础设施即代码
概述
HCL 编写、状态管理、模块开发等技能。
基础命令
初始化
terraform init terraform init -upgrade # 升级 provider
格式化
terraform fmt terraform fmt -recursive
验证
terraform validate
计划
terraform plan terraform plan -out=plan.tfplan
应用
terraform apply terraform apply plan.tfplan terraform apply -auto-approve
销毁
terraform destroy terraform destroy -auto-approve
查看状态
terraform show terraform state list terraform state show resource_type.name
输出
terraform output terraform output -json
HCL 语法
Provider 配置
providers.tf
terraform { required_version = ">= 1.0"
required_providers { aws = { source = "hashicorp/aws" version = "~> 5.0" } }
backend "s3" { bucket = "my-terraform-state" key = "prod/terraform.tfstate" region = "us-east-1" } }
provider "aws" { region = var.aws_region
default_tags { tags = { Environment = var.environment ManagedBy = "Terraform" } } }
变量定义
variables.tf
variable "aws_region" { description = "AWS region" type = string default = "us-east-1" }
variable "instance_type" { description = "EC2 instance type" type = string default = "t3.micro" }
variable "environment" { description = "Environment name" type = string
validation { condition = contains(["dev", "staging", "prod"], var.environment) error_message = "Environment must be dev, staging, or prod." } }
variable "tags" { description = "Resource tags" type = map(string) default = {} }
variable "subnets" { description = "Subnet configuration" type = list(object({ cidr_block = string az = string })) }
资源定义
main.tf
resource "aws_vpc" "main" { cidr_block = "10.0.0.0/16" enable_dns_hostnames = true
tags = { Name = "${var.environment}-vpc" } }
resource "aws_subnet" "public" { count = length(var.subnets) vpc_id = aws_vpc.main.id cidr_block = var.subnets[count.index].cidr_block availability_zone = var.subnets[count.index].az
tags = { Name = "${var.environment}-public-${count.index + 1}" } }
resource "aws_instance" "web" { ami = data.aws_ami.ubuntu.id instance_type = var.instance_type subnet_id = aws_subnet.public[0].id
tags = merge(var.tags, { Name = "${var.environment}-web" }) }
数据源
data.tf
data "aws_ami" "ubuntu" { most_recent = true owners = ["099720109477"] # Canonical
filter { name = "name" values = ["ubuntu/images/hvm-ssd/ubuntu-jammy-22.04-amd64-server-*"] } }
data "aws_availability_zones" "available" { state = "available" }
输出
outputs.tf
output "vpc_id" { description = "VPC ID" value = aws_vpc.main.id }
output "instance_public_ip" { description = "Public IP of web instance" value = aws_instance.web.public_ip }
output "subnet_ids" { description = "Subnet IDs" value = aws_subnet.public[*].id }
状态管理
状态命令
列出资源
terraform state list
查看资源
terraform state show aws_instance.web
移动资源
terraform state mv aws_instance.web aws_instance.app
删除资源(从状态中)
terraform state rm aws_instance.web
导入现有资源
terraform import aws_instance.web i-1234567890abcdef0
拉取远程状态
terraform state pull > state.json
推送状态
terraform state push state.json
远程后端
S3 后端
terraform { backend "s3" { bucket = "my-terraform-state" key = "prod/terraform.tfstate" region = "us-east-1" encrypt = true dynamodb_table = "terraform-locks" } }
初始化后端
terraform init -backend-config="bucket=my-bucket"
模块
模块结构
modules/ └── vpc/ ├── main.tf ├── variables.tf ├── outputs.tf └── README.md
模块定义
modules/vpc/main.tf
resource "aws_vpc" "this" { cidr_block = var.cidr_block enable_dns_hostnames = var.enable_dns_hostnames
tags = merge(var.tags, { Name = var.name }) }
modules/vpc/variables.tf
variable "name" { type = string }
variable "cidr_block" { type = string }
variable "enable_dns_hostnames" { type = bool default = true }
variable "tags" { type = map(string) default = {} }
modules/vpc/outputs.tf
output "vpc_id" { value = aws_vpc.this.id }
使用模块
本地模块
module "vpc" { source = "./modules/vpc"
name = "my-vpc" cidr_block = "10.0.0.0/16" tags = var.tags }
远程模块
module "vpc" { source = "terraform-aws-modules/vpc/aws" version = "5.0.0"
name = "my-vpc" cidr = "10.0.0.0/16" }
引用模块输出
resource "aws_subnet" "public" { vpc_id = module.vpc.vpc_id
...
}
工作区
列出工作区
terraform workspace list
创建工作区
terraform workspace new dev terraform workspace new prod
切换工作区
terraform workspace select dev
删除工作区
terraform workspace delete dev
在配置中使用
locals { environment = terraform.workspace }
常见场景
场景 1:条件创建资源
variable "create_instance" { type = bool default = true }
resource "aws_instance" "web" { count = var.create_instance ? 1 : 0
ami = data.aws_ami.ubuntu.id instance_type = var.instance_type }
场景 2:for_each 循环
variable "instances" { type = map(object({ instance_type = string ami = string })) }
resource "aws_instance" "this" { for_each = var.instances
ami = each.value.ami instance_type = each.value.instance_type
tags = { Name = each.key } }
场景 3:动态块
resource "aws_security_group" "this" { name = "my-sg" 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 } } }
场景 4:依赖管理
resource "aws_instance" "web" {
隐式依赖
subnet_id = aws_subnet.public.id
显式依赖
depends_on = [aws_internet_gateway.main] }
故障排查
问题 排查方法
状态锁定 terraform force-unlock LOCK_ID
Provider 错误 terraform init -upgrade
状态不一致 terraform refresh
循环依赖 检查 depends_on
调试模式
TF_LOG=DEBUG terraform plan
查看详细计划
terraform plan -out=plan.tfplan terraform show -json plan.tfplan | jq
验证配置
terraform validate