Get the FREE Ultimate OpenClaw Setup Guide →
npx machina-cli add skill chaterm/terminal-skills/terraform --openclaw
Files (1)
SKILL.md
7.0 KB

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

Source

git clone https://github.com/chaterm/terminal-skills/blob/main/devops/terraform/SKILL.mdView on GitHub

Overview

Terraform 是一款基础设施即代码工具,允许你用 HCL 编写云资源的配置、通过 provider 与资源实现声明式部署、并借助后端管理状态。你可以在一个统一的工作流中定义、计划、应用和销毁资源,支持多云和本地资源,同时通过模块实现高可复用的基础设施组件。

How This Skill Works

你把资源、变量、数据源和模块写入 .tf 文件,配置 provider 与后端。执行 terraform plan 生成执行计划,确认后执行 terraform apply 以创建或更新资源。状态文件存放在本地或远端后端,确保团队对同一状态的可见性和并发保护。你可以使用数据源获取外部信息、通过模块实现复用、借助工作区隔离环境,并利用命令如 terraform state、terraform import 等管理现有资源与状态。

When to Use It

  • 在 AWS、Azure、GCP 等云环境中定义、部署和变更基础设施并实现可重复部署
  • 需要与团队共享基础设施状态并锁定并发修改,采用远程后端和状态锁
  • 希望把基础设施拆分为模块以实现可复用和版本化
  • 需要在同一配置中管理开发、测试、生产等环境,或跨账户/区域部署
  • 需要将现有资源纳入 IaC 流程并使用 Terraform 进行治理与持续交付

Quick Start

  1. 创建并配置 provider 与后端(如 AWS 与 S3/ DynamoDB 远端后端)
  2. 编写变量、资源和模块(如 VPC、子网、EC2)并运行 terraform init
  3. 执行 terraform plan -out=plan.tfplan 以查看将执行的变更
  4. 执行 terraform apply plan.tfplan 以应用变更并创建/更新资源

Best Practices

  • 将后端配置为远端存储并启用锁(如 S3 + DynamoDB)以实现团队协作与并发保护
  • 固定 provider 版本并使用具体版本号,避免意外升级
  • 将基础设施拆分为模块,根模块保持简洁,利于复用与版本控制
  • 对环境使用工作区(workspace)或变量进行区分,避免环境混淆
  • 使用 terraform fmt + terraform validate 在合并前确保代码规范与正确性
  • 把敏感信息和机密数据从代码中分离,使用外部化的证书和参数管理机制

Example Use Cases

  • 场景 1:在 AWS 上通过 VPC、子网、互联网网关等资源搭建一个可用的网络架构,并部署一台 Web 服务器,输出 VPC ID、子网 ID、Web 服务器公有 IP 等。
  • 场景 2:配置远端后端(如 S3 + DynamoDB 锁)以实现团队协作和状态一致性,并通过 terraform state 子命令进行状态查看、移动与导入。
  • 场景 3:使用模块化的 VPC 模块(如 modules/vpc)在不同账户/区域复用基础网络组件,并通过远程模块引用实现版本化部署。
  • 场景 4:将现有的云资源(如已存在的 EC2、RDS 等)通过 terraform import 纳入 Terraform 管理,以统一的 IaC 工作流进行后续变更。
  • 场景 5:结合数据源获取最新的 Ubuntu AMI 与可用区信息,动态配置实例与子网,提升自动化部署的可靠性。

Frequently Asked Questions

Add this skill to your agents

Related Skills

Sponsor this space

Reach thousands of developers