问题背景
很多公司过去几年里一步步从单云走向多云,原因各有不同:
业务出海,需要在多个地域部署。 监管要求数据在境内保存,但海外用户多,需要海外资源。 单一云厂商出过故障,迫使做灾备。 不同业务用不同云服务(AWS 的 Lambda、阿里云的 ACK、Azure 的 AAD),整合管理。 公司收购,IT 资产在不同云上。
但多云管理是个大坑:
阿里云 ECS、AWS EC2、Azure VM 各有各的 API,各有各的 SDK。 IAM 体系不同,权限模型不同。 资源状态没有统一视图,盘点困难。 不同云的同名概念含义不同(VPC 在 AWS 和 Azure 里范围不一样)。 手工创建的资源没人记得,改了哪个、删了哪个都对不上账。 出了安全事件需要排查所有云上的资源,散落在多个控制台。
Terraform 是目前最主流的多云基础设施即代码(IaC)工具。阿里云、AWS、Azure、GCP、腾讯云、华为云都提供官方或社区的 Terraform Provider。这篇文章讲清楚怎么用 Terraform 统一管理多云资源,避开常见陷阱,建立可维护的 IaC 项目。
适用读者
负责多云架构的运维工程师、SRE、DevOps。 想从手工控制台 / 自研脚本迁移到 IaC 的同学。 维护 Terraform 项目、解决漂移 / 状态冲突 / 漂移检测的工程师。 准备把 Terraform 集成到 CI/CD 流水线的同学。
适用场景
中大规模基础设施(10~10000 个云资源)。 多云或混合云(AWS + 阿里云 + 私有 K8s)。 应用、数据库、网络、监控的代码化管理。 与 Jenkins、GitLab CI、GitHub Actions、Argo CD 配合的 GitOps 流水线。
核心知识点
Terraform 是什么
Terraform 是 HashiCorp 公司开发的基础设施即代码工具,用声明式 HCL(HashiCorp Configuration Language)描述"我要什么资源",然后由 Terraform 协调云厂商 API 把现实拉到这个状态。
关键概念:
Provider:对接云厂商 / 服务商的插件,例如 aws、alicloud、azurerm、google、tencentcloud。Resource:要管理的资源,例如 aws_instance、alicloud_vpc。Data Source:查询已有资源,例如 aws_ami、alicloud_zones。State:Terraform 维护的"实际状态"文件,对比期望状态和实际状态。 Plan:根据期望和状态算出要做的操作(create / read / update / delete)。 Apply:执行 plan,把实际状态推到期望状态。 Module:可复用的 Terraform 代码单元。
Terraform 生命周期
1. 写代码(HCL) → *.tf 文件
2. terraform init → 下载 provider / module
3. terraform plan → 算出 diff
4. terraform apply → 推送到云
5. terraform destroy → 销毁(慎用)
6. terraform state → 操作 state 文件
7. terraform import → 把已有资源纳入管理
安装
# macOS
brew tap hashicorp/tap
brew install hashicorp/tap/terraform
# Ubuntu / Debian
sudo apt-get update && sudo apt-get install -y gnupg software-properties-common
wget -O- https://apt.releases.hashicorp.com/gpg |
gpg --dearmor |
sudo tee /usr/share/keyrings/hashicorp-archive-keyring.gpg
echo"deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg]
https://apt.releases.hashicorp.com $(lsb_release -cs) main" |
sudo tee /etc/apt/sources.list.d/hashicorp.list
sudo apt-get update && sudo apt-get install terraform
# 验证
terraform version
多云场景的核心挑战
Provider 差异:每个云有自己的资源模型,跨云抽象困难。 身份认证:每个云的 AK/SK、IAM Role 都不一样。 State 同步:多云资源在同一个 state 里,要考虑一致性。 网络打通:跨云网络(VPC Peering、VPN、SD-WAN)需要规划。 统一监控:跨云指标、日志、告警需要统一平台。 合规:不同云合规要求不同,数据驻留、加密、审计。 成本管理:多云账单合并分析。
Terraform 解决的是"用统一的语言描述资源",但具体落地仍然要懂每个云。
实战一:第一个多云 Terraform 项目
项目结构
terraform-multi-cloud/
├── main.tf # 入口
├── versions.tf # provider / terraform 版本
├── variables.tf # 输入变量
├── outputs.tf # 输出
├── terraform.tfvars # 变量值(不进版本控制)
├── backend.tf # state 后端
├── providers/
│ ├── aws.tf
│ ├── alicloud.tf
│ └── azurerm.tf
├── modules/
│ ├── vpc/
│ │ ├── main.tf
│ │ ├── variables.tf
│ │ ├── outputs.tf
│ │ └── README.md
│ ├── ecs/
│ └── rds/
├── environments/
│ ├── dev/
│ │ ├── main.tf
│ │ └── terraform.tfvars
│ ├── staging/
│ └── production/
└── .gitignore
versions.tf
# versions.tf
terraform {
required_version = ">= 1.6.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
alicloud = {
source = "aliyun/alicloud"
version = "~> 1.200"
}
azurerm = {
source = "hashicorp/azurerm"
version = "~> 3.0"
}
google = {
source = "hashicorp/google"
version = "~> 5.0"
}
tencentcloud = {
source = "tencentcloudstack/terraform-provider-tencentcloud"
version = "~> 1.80"
}
}
}
provider 配置
# providers/aws.tf
provider "aws" {
region = "ap-southeast-1"
default_tags {
Environment = "production"
ManagedBy = "terraform"
Project = "myapp"
}
}
# providers/alicloud.tf
provider "alicloud" {
region = "cn-hangzhou"
profile = "default"
}
# providers/azurerm.tf
provider "azurerm" {
features {}
subscription_id = var.azure_subscription_id
}
# providers/google.tf
provider "google" {
project = var.gcp_project_id
region = "asia-southeast1"
}
风险提示:每个 provider 都需要认证信息,不要把 AK/SK 写进代码。建议用环境变量、CI secret、Vault。
后端配置
# backend.tf
terraform {
backend "s3" {
bucket = "myorg-terraform-state"
key = "multi-cloud/terraform.tfstate"
region = "ap-southeast-1"
encrypt = true
kms_key_id = "arn:aws:kms:ap-southeast-1:111122223333:key/abcd-1234"
dynamodb_table = "terraform-lock"
}
}
不同云的后端:
# 阿里云 OSS 后端
terraform {
backend "oss" {
bucket = "myorg-terraform-state"
key = "multi-cloud/terraform.tfstate"
region = "cn-hangzhou"
prefix = "terraform/state"
encrypt = true
}
}
# 腾讯云 COS 后端
terraform {
backend "cos" {
secret_id = var.tencent_secret_id
secret_key = var.tencent_secret_key
region = "ap-shanghai"
bucket = "myorg-terraform-state-1234567890"
prefix = "terraform/state"
key = "multi-cloud/terraform.tfstate"
}
}
变量
# variables.tf
variable "environment" {
description = "环境名"
type = string
default = "dev"
validation {
condition = contains(["dev", "staging", "production"], var.environment)
error_message = "环境必须是 dev、staging 或 production。"
}
}
variable "aws_region" {
description = "AWS 区域"
type = string
default = "ap-southeast-1"
}
variable "alicloud_region" {
description = "阿里云区域"
type = string
default = "cn-hangzhou"
}
variable "instance_type" {
description = "ECS/EC2 实例规格"
type = string
default = "ecs.t5.large"
}
variable "vpc_cidr" {
description = "VPC CIDR"
type = string
default = "10.0.0.0/16"
validation {
condition = can(cidrnetmask(var.vpc_cidr))
error_message = "VPC CIDR 必须是合法的 CIDR。"
}
}
变量值文件(每个环境一个):
# environments/production/terraform.tfvars
environment = "production"
aws_region = "ap-southeast-1"
alicloud_region = "cn-hangzhou"
instance_type = "ecs.g6.xlarge"
vpc_cidr = "10.0.0.0/16"
风险提示:tfvars 文件可能含敏感信息(数据库密码、IP 白名单),建议不进 Git,用 CI secret 注入。
创建 VPC(多云)
# modules/vpc/main.tf
variable "vpc_cidr" {
type = string
description = "VPC CIDR"
}
variable "vpc_name" {
type = string
description = "VPC 名称"
}
variable "environment" {
type = string
description = "环境"
}
# AWS VPC
resource "aws_vpc" "this" {
cidr_block = var.vpc_cidr
tags = {
Name = "${var.vpc_name}-aws"
Environment = var.environment
}
}
resource "aws_subnet" "public" {
count = 3
vpc_id = aws_vpc.this.id
cidr_block = cidrsubnet(var.vpc_cidr, 8, count.index)
availability_zone = data.aws_availability_zones.available.names[count.index]
tags = {
Name = "${var.vpc_name}-public-${count.index + 1}"
}
}
data "aws_availability_zones" "available" {
state = "available"
}
# 阿里云 VPC
resource "alicloud_vpc" "this" {
vpc_name = "${var.vpc_name}-aliyun"
cidr_block = var.vpc_cidr
}
resource "alicloud_vswitch" "public" {
count = 3
vpc_id = alicloud_vpc.this.id
cidr_block = cidrsubnet(var.vpc_cidr, 8, count.index + 10)
zone_id = data.alicloud_zones.available.zones[count.index].id
vswitch_name = "${var.vpc_name}-public-${count.index + 1}"
}
data "alicloud_zones" "available" {
available_resource_creation = "VSwitch"
}
output "aws_vpc_id" {
value = aws_vpc.this.id
}
output "alicloud_vpc_id" {
value = alicloud_vpc.this.id
}
创建 ECS / EC2
# macOS
brew tap hashicorp/tap
brew install hashicorp/tap/terraform
# Ubuntu / Debian
sudo apt-get update && sudo apt-get install -y gnupg software-properties-common
wget -O- https://apt.releases.hashicorp.com/gpg |
gpg --dearmor |
sudo tee /usr/share/keyrings/hashicorp-archive-keyring.gpg
echo"deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg]
https://apt.releases.hashicorp.com $(lsb_release -cs) main" |
sudo tee /etc/apt/sources.list.d/hashicorp.list
sudo apt-get update && sudo apt-get install terraform
# 验证
terraform version
0编排入口
# macOS
brew tap hashicorp/tap
brew install hashicorp/tap/terraform
# Ubuntu / Debian
sudo apt-get update && sudo apt-get install -y gnupg software-properties-common
wget -O- https://apt.releases.hashicorp.com/gpg |
gpg --dearmor |
sudo tee /usr/share/keyrings/hashicorp-archive-keyring.gpg
echo"deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg]
https://apt.releases.hashicorp.com $(lsb_release -cs) main" |
sudo tee /etc/apt/sources.list.d/hashicorp.list
sudo apt-get update && sudo apt-get install terraform
# 验证
terraform version
1跑起来
# macOS
brew tap hashicorp/tap
brew install hashicorp/tap/terraform
# Ubuntu / Debian
sudo apt-get update && sudo apt-get install -y gnupg software-properties-common
wget -O- https://apt.releases.hashicorp.com/gpg |
gpg --dearmor |
sudo tee /usr/share/keyrings/hashicorp-archive-keyring.gpg
echo"deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg]
https://apt.releases.hashicorp.com $(lsb_release -cs) main" |
sudo tee /etc/apt/sources.list.d/hashicorp.list
sudo apt-get update && sudo apt-get install terraform
# 验证
terraform version
2风险提示:第一次跑前必须用 terraform plan 看清要做的操作。apply 前再加一次 --dry-run 或者让同事帮忙 review plan 输出。
实战二:State 管理
State 是什么
State 是 Terraform 记录"上次 apply 后实际状态"的文件。每次 apply 之后,Terraform 会更新 state 与云上资源保持一致。
State 存在哪里、谁能访问、是分布式还是本地,关系到协作能力和安全。
远程后端选择
S3 + DynamoDB 后端
# macOS
brew tap hashicorp/tap
brew install hashicorp/tap/terraform
# Ubuntu / Debian
sudo apt-get update && sudo apt-get install -y gnupg software-properties-common
wget -O- https://apt.releases.hashicorp.com/gpg |
gpg --dearmor |
sudo tee /usr/share/keyrings/hashicorp-archive-keyring.gpg
echo"deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg]
https://apt.releases.hashicorp.com $(lsb_release -cs) main" |
sudo tee /etc/apt/sources.list.d/hashicorp.list
sudo apt-get update && sudo apt-get install terraform
# 验证
terraform version
3State 命令
# macOS
brew tap hashicorp/tap
brew install hashicorp/tap/terraform
# Ubuntu / Debian
sudo apt-get update && sudo apt-get install -y gnupg software-properties-common
wget -O- https://apt.releases.hashicorp.com/gpg |
gpg --dearmor |
sudo tee /usr/share/keyrings/hashicorp-archive-keyring.gpg
echo"deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg]
https://apt.releases.hashicorp.com $(lsb_release -cs) main" |
sudo tee /etc/apt/sources.list.d/hashicorp.list
sudo apt-get update && sudo apt-get install terraform
# 验证
terraform version
4State 锁
并发 apply 同一个 state 会冲突。S3 后端用 DynamoDB 表做锁,OSS 后端用 OSS 自带锁。开启后,同一时间只能有一个 apply 在跑。
如果 apply 中途失败(比如网络断),锁可能没释放,会阻塞后续操作:
# macOS
brew tap hashicorp/tap
brew install hashicorp/tap/terraform
# Ubuntu / Debian
sudo apt-get update && sudo apt-get install -y gnupg software-properties-common
wget -O- https://apt.releases.hashicorp.com/gpg |
gpg --dearmor |
sudo tee /usr/share/keyrings/hashicorp-archive-keyring.gpg
echo"deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg]
https://apt.releases.hashicorp.com $(lsb_release -cs) main" |
sudo tee /etc/apt/sources.list.d/hashicorp.list
sudo apt-get update && sudo apt-get install terraform
# 验证
terraform version
5风险提示:force-unlock 是高风险操作,确认没有其他人正在 apply 才能执行。
实战三:模块化设计
模块基础
模块是 Terraform 的复用单元。source 可以是本地路径、Git 地址、Terraform Registry。
# macOS
brew tap hashicorp/tap
brew install hashicorp/tap/terraform
# Ubuntu / Debian
sudo apt-get update && sudo apt-get install -y gnupg software-properties-common
wget -O- https://apt.releases.hashicorp.com/gpg |
gpg --dearmor |
sudo tee /usr/share/keyrings/hashicorp-archive-keyring.gpg
echo"deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg]
https://apt.releases.hashicorp.com $(lsb_release -cs) main" |
sudo tee /etc/apt/sources.list.d/hashicorp.list
sudo apt-get update && sudo apt-get install terraform
# 验证
terraform version
6# macOS
brew tap hashicorp/tap
brew install hashicorp/tap/terraform
# Ubuntu / Debian
sudo apt-get update && sudo apt-get install -y gnupg software-properties-common
wget -O- https://apt.releases.hashicorp.com/gpg |
gpg --dearmor |
sudo tee /usr/share/keyrings/hashicorp-archive-keyring.gpg
echo"deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg]
https://apt.releases.hashicorp.com $(lsb_release -cs) main" |
sudo tee /etc/apt/sources.list.d/hashicorp.list
sudo apt-get update && sudo apt-get install terraform
# 验证
terraform version
7# macOS
brew tap hashicorp/tap
brew install hashicorp/tap/terraform
# Ubuntu / Debian
sudo apt-get update && sudo apt-get install -y gnupg software-properties-common
wget -O- https://apt.releases.hashicorp.com/gpg |
gpg --dearmor |
sudo tee /usr/share/keyrings/hashicorp-archive-keyring.gpg
echo"deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg]
https://apt.releases.hashicorp.com $(lsb_release -cs) main" |
sudo tee /etc/apt/sources.list.d/hashicorp.list
sudo apt-get update && sudo apt-get install terraform
# 验证
terraform version
8模块版本约束
# macOS
brew tap hashicorp/tap
brew install hashicorp/tap/terraform
# Ubuntu / Debian
sudo apt-get update && sudo apt-get install -y gnupg software-properties-common
wget -O- https://apt.releases.hashicorp.com/gpg |
gpg --dearmor |
sudo tee /usr/share/keyrings/hashicorp-archive-keyring.gpg
echo"deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg]
https://apt.releases.hashicorp.com $(lsb_release -cs) main" |
sudo tee /etc/apt/sources.list.d/hashicorp.list
sudo apt-get update && sudo apt-get install terraform
# 验证
terraform version
9version 是强烈建议。ref 锁定 Git tag 能保证可复现。
模块输入输出
terraform-multi-cloud/
├── main.tf # 入口
├── versions.tf # provider / terraform 版本
├── variables.tf # 输入变量
├── outputs.tf # 输出
├── terraform.tfvars # 变量值(不进版本控制)
├── backend.tf # state 后端
├── providers/
│ ├── aws.tf
│ ├── alicloud.tf
│ └── azurerm.tf
├── modules/
│ ├── vpc/
│ │ ├── main.tf
│ │ ├── variables.tf
│ │ ├── outputs.tf
│ │ └── README.md
│ ├── ecs/
│ └── rds/
├── environments/
│ ├── dev/
│ │ ├── main.tf
│ │ └── terraform.tfvars
│ ├── staging/
│ └── production/
└── .gitignore
0模块组合
terraform-multi-cloud/
├── main.tf # 入口
├── versions.tf # provider / terraform 版本
├── variables.tf # 输入变量
├── outputs.tf # 输出
├── terraform.tfvars # 变量值(不进版本控制)
├── backend.tf # state 后端
├── providers/
│ ├── aws.tf
│ ├── alicloud.tf
│ └── azurerm.tf
├── modules/
│ ├── vpc/
│ │ ├── main.tf
│ │ ├── variables.tf
│ │ ├── outputs.tf
│ │ └── README.md
│ ├── ecs/
│ └── rds/
├── environments/
│ ├── dev/
│ │ ├── main.tf
│ │ └── terraform.tfvars
│ ├── staging/
│ └── production/
└── .gitignore
1多云资源在一个 module 里
terraform-multi-cloud/
├── main.tf # 入口
├── versions.tf # provider / terraform 版本
├── variables.tf # 输入变量
├── outputs.tf # 输出
├── terraform.tfvars # 变量值(不进版本控制)
├── backend.tf # state 后端
├── providers/
│ ├── aws.tf
│ ├── alicloud.tf
│ └── azurerm.tf
├── modules/
│ ├── vpc/
│ │ ├── main.tf
│ │ ├── variables.tf
│ │ ├── outputs.tf
│ │ └── README.md
│ ├── ecs/
│ └── rds/
├── environments/
│ ├── dev/
│ │ ├── main.tf
│ │ └── terraform.tfvars
│ ├── staging/
│ └── production/
└── .gitignore
2但要谨慎:多云资源耦合在一起会让 state 变大、apply 变慢。建议多云资源分模块,按云或按业务域拆分。
实战四:多环境管理
方案 A:目录分层
terraform-multi-cloud/
├── main.tf # 入口
├── versions.tf # provider / terraform 版本
├── variables.tf # 输入变量
├── outputs.tf # 输出
├── terraform.tfvars # 变量值(不进版本控制)
├── backend.tf # state 后端
├── providers/
│ ├── aws.tf
│ ├── alicloud.tf
│ └── azurerm.tf
├── modules/
│ ├── vpc/
│ │ ├── main.tf
│ │ ├── variables.tf
│ │ ├── outputs.tf
│ │ └── README.md
│ ├── ecs/
│ └── rds/
├── environments/
│ ├── dev/
│ │ ├── main.tf
│ │ └── terraform.tfvars
│ ├── staging/
│ └── production/
└── .gitignore
3每个环境独立 state、独立 plan、独立 apply。
terraform-multi-cloud/
├── main.tf # 入口
├── versions.tf # provider / terraform 版本
├── variables.tf # 输入变量
├── outputs.tf # 输出
├── terraform.tfvars # 变量值(不进版本控制)
├── backend.tf # state 后端
├── providers/
│ ├── aws.tf
│ ├── alicloud.tf
│ └── azurerm.tf
├── modules/
│ ├── vpc/
│ │ ├── main.tf
│ │ ├── variables.tf
│ │ ├── outputs.tf
│ │ └── README.md
│ ├── ecs/
│ └── rds/
├── environments/
│ ├── dev/
│ │ ├── main.tf
│ │ └── terraform.tfvars
│ ├── staging/
│ └── production/
└── .gitignore
4优点:环境间完全隔离,state 独立。缺点:环境多了要切目录、init 多次。
方案 B:Workspace
terraform-multi-cloud/
├── main.tf # 入口
├── versions.tf # provider / terraform 版本
├── variables.tf # 输入变量
├── outputs.tf # 输出
├── terraform.tfvars # 变量值(不进版本控制)
├── backend.tf # state 后端
├── providers/
│ ├── aws.tf
│ ├── alicloud.tf
│ └── azurerm.tf
├── modules/
│ ├── vpc/
│ │ ├── main.tf
│ │ ├── variables.tf
│ │ ├── outputs.tf
│ │ └── README.md
│ ├── ecs/
│ └── rds/
├── environments/
│ ├── dev/
│ │ ├── main.tf
│ │ └── terraform.tfvars
│ ├── staging/
│ └── production/
└── .gitignore
5Workspace 把 state 按目录存到同一个后端,前缀是 env:/<workspace_name>。
优点:不用切目录。缺点:环境间差异不直观、容易误操作、不适合大差异(不同 region、不同云)。
方案 C:Terragrunt
Terragrunt 是 Terraform 的 wrapper,提供更复杂的多环境管理(DRY 配置、依赖管理、远程 state 自动化)。
terraform-multi-cloud/
├── main.tf # 入口
├── versions.tf # provider / terraform 版本
├── variables.tf # 输入变量
├── outputs.tf # 输出
├── terraform.tfvars # 变量值(不进版本控制)
├── backend.tf # state 后端
├── providers/
│ ├── aws.tf
│ ├── alicloud.tf
│ └── azurerm.tf
├── modules/
│ ├── vpc/
│ │ ├── main.tf
│ │ ├── variables.tf
│ │ ├── outputs.tf
│ │ └── README.md
│ ├── ecs/
│ └── rds/
├── environments/
│ ├── dev/
│ │ ├── main.tf
│ │ └── terraform.tfvars
│ ├── staging/
│ └── production/
└── .gitignore
6terraform-multi-cloud/
├── main.tf # 入口
├── versions.tf # provider / terraform 版本
├── variables.tf # 输入变量
├── outputs.tf # 输出
├── terraform.tfvars # 变量值(不进版本控制)
├── backend.tf # state 后端
├── providers/
│ ├── aws.tf
│ ├── alicloud.tf
│ └── azurerm.tf
├── modules/
│ ├── vpc/
│ │ ├── main.tf
│ │ ├── variables.tf
│ │ ├── outputs.tf
│ │ └── README.md
│ ├── ecs/
│ └── rds/
├── environments/
│ ├── dev/
│ │ ├── main.tf
│ │ └── terraform.tfvars
│ ├── staging/
│ └── production/
└── .gitignore
7优势:
多模块共享配置(remote state、provider)。 自动管理依赖(module 间依赖)。 terragrunt run-all plan一键跑多个模块。
学习曲线略陡,但大项目必备。
实战五:流水线集成
典型流程
terraform-multi-cloud/
├── main.tf # 入口
├── versions.tf # provider / terraform 版本
├── variables.tf # 输入变量
├── outputs.tf # 输出
├── terraform.tfvars # 变量值(不进版本控制)
├── backend.tf # state 后端
├── providers/
│ ├── aws.tf
│ ├── alicloud.tf
│ └── azurerm.tf
├── modules/
│ ├── vpc/
│ │ ├── main.tf
│ │ ├── variables.tf
│ │ ├── outputs.tf
│ │ └── README.md
│ ├── ecs/
│ └── rds/
├── environments/
│ ├── dev/
│ │ ├── main.tf
│ │ └── terraform.tfvars
│ ├── staging/
│ └── production/
└── .gitignore
8GitHub Actions
terraform-multi-cloud/
├── main.tf # 入口
├── versions.tf # provider / terraform 版本
├── variables.tf # 输入变量
├── outputs.tf # 输出
├── terraform.tfvars # 变量值(不进版本控制)
├── backend.tf # state 后端
├── providers/
│ ├── aws.tf
│ ├── alicloud.tf
│ └── azurerm.tf
├── modules/
│ ├── vpc/
│ │ ├── main.tf
│ │ ├── variables.tf
│ │ ├── outputs.tf
│ │ └── README.md
│ ├── ecs/
│ └── rds/
├── environments/
│ ├── dev/
│ │ ├── main.tf
│ │ └── terraform.tfvars
│ ├── staging/
│ └── production/
└── .gitignore
9风险提示:CI 上 apply 是高风险操作,建议加手动审批(environment: production + when: manual)。
GitLab CI
# versions.tf
terraform {
required_version = ">= 1.6.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
alicloud = {
source = "aliyun/alicloud"
version = "~> 1.200"
}
azurerm = {
source = "hashicorp/azurerm"
version = "~> 3.0"
}
google = {
source = "hashicorp/google"
version = "~> 5.0"
}
tencentcloud = {
source = "tencentcloudstack/terraform-provider-tencentcloud"
version = "~> 1.80"
}
}
}
0Atlantis
Atlantis 是 Terraform 专用 CI 工具,通过 PR 评论触发 plan/apply:
# versions.tf
terraform {
required_version = ">= 1.6.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
alicloud = {
source = "aliyun/alicloud"
version = "~> 1.200"
}
azurerm = {
source = "hashicorp/azurerm"
version = "~> 3.0"
}
google = {
source = "hashicorp/google"
version = "~> 5.0"
}
tencentcloud = {
source = "tencentcloudstack/terraform-provider-tencentcloud"
version = "~> 1.80"
}
}
}
1在 PR 上评论:
# versions.tf
terraform {
required_version = ">= 1.6.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
alicloud = {
source = "aliyun/alicloud"
version = "~> 1.200"
}
azurerm = {
source = "hashicorp/azurerm"
version = "~> 3.0"
}
google = {
source = "hashicorp/google"
version = "~> 5.0"
}
tencentcloud = {
source = "tencentcloudstack/terraform-provider-tencentcloud"
version = "~> 1.80"
}
}
}
2Atlantis 会自动评论 plan 输出,需要 maintainer 加 atlantis approve 才能 apply。
Spacelift / Env0
商业化 Terraform 平台,提供 SaaS / Private 部署。功能齐全:policy as code、drift detection、cost estimation、并行执行。
实战六:漂移检测
什么是漂移
"漂移(Drift)"是 Terraform 期望状态和云上实际状态不一致。可能因为:
有人在控制台手工改了资源。 自动化脚本(非 Terraform)改资源。 资源被云厂商主动调整(比如磁盘扩容)。 资源被外部删除。
漂移会导致 Terraform 状态不准确,下次 plan 会显示 reconcile 操作。
漂移检测方法
方法 1:定时 plan
# versions.tf
terraform {
required_version = ">= 1.6.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
alicloud = {
source = "aliyun/alicloud"
version = "~> 1.200"
}
azurerm = {
source = "hashicorp/azurerm"
version = "~> 3.0"
}
google = {
source = "hashicorp/google"
version = "~> 5.0"
}
tencentcloud = {
source = "tencentcloudstack/terraform-provider-tencentcloud"
version = "~> 1.80"
}
}
}
3-detailed-exitcode:
0:无 diff 1:执行出错 2:有 diff,需要 apply
方法 2:Driftctl
Driftctl 是专门做漂移检测的开源工具,比 terraform plan 更专业,能并行检测大量资源:
# versions.tf
terraform {
required_version = ">= 1.6.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
alicloud = {
source = "aliyun/alicloud"
version = "~> 1.200"
}
azurerm = {
source = "hashicorp/azurerm"
version = "~> 3.0"
}
google = {
source = "hashicorp/google"
version = "~> 5.0"
}
tencentcloud = {
source = "tencentcloudstack/terraform-provider-tencentcloud"
version = "~> 1.80"
}
}
}
4Driftctl 还能识别"已删除"和"未管理"的资源。
方法 3:Spacelift / Env0
商业化平台自带漂移检测。
方法 4:refresh-only plan
Terraform 1.5+ 提供 refresh-only plan:
# versions.tf
terraform {
required_version = ">= 1.6.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
alicloud = {
source = "aliyun/alicloud"
version = "~> 1.200"
}
azurerm = {
source = "hashicorp/azurerm"
version = "~> 3.0"
}
google = {
source = "hashicorp/google"
version = "~> 5.0"
}
tencentcloud = {
source = "tencentcloudstack/terraform-provider-tencentcloud"
version = "~> 1.80"
}
}
}
5只刷新 state,不做 create/update/delete。用来识别"什么资源实际状态变了"。
处理漂移
发现漂移后,处理方式:
真漂移(应该恢复到 Terraform 期望): terraform apply。云上调整(云厂商主动扩容):更新 Terraform 代码反映新状态。 真删除(云上资源应该被删):从 state 中移除。 非预期修改:人工 review 决定。
实战七:常见陷阱
陷阱 1:把密码写进代码
# versions.tf
terraform {
required_version = ">= 1.6.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
alicloud = {
source = "aliyun/alicloud"
version = "~> 1.200"
}
azurerm = {
source = "hashicorp/azurerm"
version = "~> 3.0"
}
google = {
source = "hashicorp/google"
version = "~> 5.0"
}
tencentcloud = {
source = "tencentcloudstack/terraform-provider-tencentcloud"
version = "~> 1.80"
}
}
}
6正确做法:
# versions.tf
terraform {
required_version = ">= 1.6.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
alicloud = {
source = "aliyun/alicloud"
version = "~> 1.200"
}
azurerm = {
source = "hashicorp/azurerm"
version = "~> 3.0"
}
google = {
source = "hashicorp/google"
version = "~> 5.0"
}
tencentcloud = {
source = "tencentcloudstack/terraform-provider-tencentcloud"
version = "~> 1.80"
}
}
}
7# versions.tf
terraform {
required_version = ">= 1.6.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
alicloud = {
source = "aliyun/alicloud"
version = "~> 1.200"
}
azurerm = {
source = "hashicorp/azurerm"
version = "~> 3.0"
}
google = {
source = "hashicorp/google"
version = "~> 5.0"
}
tencentcloud = {
source = "tencentcloudstack/terraform-provider-tencentcloud"
version = "~> 1.80"
}
}
}
8或者用 data "aws_ssm_parameter" 读 AWS Parameter Store / Secrets Manager / 阿里云 KMS。
陷阱 2:循环依赖
# versions.tf
terraform {
required_version = ">= 1.6.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
alicloud = {
source = "aliyun/alicloud"
version = "~> 1.200"
}
azurerm = {
source = "hashicorp/azurerm"
version = "~> 3.0"
}
google = {
source = "hashicorp/google"
version = "~> 5.0"
}
tencentcloud = {
source = "tencentcloudstack/terraform-provider-tencentcloud"
version = "~> 1.80"
}
}
}
9正确做法:解耦,安全组规则用 CIDR 块而不是 IP。
陷阱 3:State 锁死
现象:Error: Error acquiring the state lock。
原因:上一次 apply 没正常结束,锁没释放。
处理:
# providers/aws.tf
provider "aws" {
region = "ap-southeast-1"
default_tags {
Environment = "production"
ManagedBy = "terraform"
Project = "myapp"
}
}
# providers/alicloud.tf
provider "alicloud" {
region = "cn-hangzhou"
profile = "default"
}
# providers/azurerm.tf
provider "azurerm" {
features {}
subscription_id = var.azure_subscription_id
}
# providers/google.tf
provider "google" {
project = var.gcp_project_id
region = "asia-southeast1"
}
0风险提示:force-unlock 是高危操作,必须先确认。
陷阱 4:误删资源
# providers/aws.tf
provider "aws" {
region = "ap-southeast-1"
default_tags {
Environment = "production"
ManagedBy = "terraform"
Project = "myapp"
}
}
# providers/alicloud.tf
provider "alicloud" {
region = "cn-hangzhou"
profile = "default"
}
# providers/azurerm.tf
provider "azurerm" {
features {}
subscription_id = var.azure_subscription_id
}
# providers/google.tf
provider "google" {
project = var.gcp_project_id
region = "asia-southeast1"
}
1会删除所有管理的资源。生产环境必须用 -target 限定范围或 -var 切换环境。
风险提示:永远不要在生产跑 terraform destroy。如果要下线环境,先在测试环境试一遍,限制 IAM 权限加 MFA。
陷阱 5:漂移导致 apply 失败
# providers/aws.tf
provider "aws" {
region = "ap-southeast-1"
default_tags {
Environment = "production"
ManagedBy = "terraform"
Project = "myapp"
}
}
# providers/alicloud.tf
provider "alicloud" {
region = "cn-hangzhou"
profile = "default"
}
# providers/azurerm.tf
provider "azurerm" {
features {}
subscription_id = var.azure_subscription_id
}
# providers/google.tf
provider "google" {
project = var.gcp_project_id
region = "asia-southeast1"
}
2资源在 apply 中被外部改了。解决:
# providers/aws.tf
provider "aws" {
region = "ap-southeast-1"
default_tags {
Environment = "production"
ManagedBy = "terraform"
Project = "myapp"
}
}
# providers/alicloud.tf
provider "alicloud" {
region = "cn-hangzhou"
profile = "default"
}
# providers/azurerm.tf
provider "azurerm" {
features {}
subscription_id = var.azure_subscription_id
}
# providers/google.tf
provider "google" {
project = var.gcp_project_id
region = "asia-southeast1"
}
3陷阱 6:Provider 版本不兼容
# providers/aws.tf
provider "aws" {
region = "ap-southeast-1"
default_tags {
Environment = "production"
ManagedBy = "terraform"
Project = "myapp"
}
}
# providers/alicloud.tf
provider "alicloud" {
region = "cn-hangzhou"
profile = "default"
}
# providers/azurerm.tf
provider "azurerm" {
features {}
subscription_id = var.azure_subscription_id
}
# providers/google.tf
provider "google" {
project = var.gcp_project_id
region = "asia-southeast1"
}
4升级 provider 后资源字段可能变。先在测试环境升级,看 plan 输出。
陷阱 7:模块地狱
module 套 module 套 module,每个 module 有大量 input,最后没人能改。
经验法则:
最多 3 层嵌套。 module inputs ≤ 10 个。 module outputs 越少越好。 业务模块和基础设施模块分开。
陷阱 8:多云网络误配置
# providers/aws.tf
provider "aws" {
region = "ap-southeast-1"
default_tags {
Environment = "production"
ManagedBy = "terraform"
Project = "myapp"
}
}
# providers/alicloud.tf
provider "alicloud" {
region = "cn-hangzhou"
profile = "default"
}
# providers/azurerm.tf
provider "azurerm" {
features {}
subscription_id = var.azure_subscription_id
}
# providers/google.tf
provider "google" {
project = var.gcp_project_id
region = "asia-southeast1"
}
5跨云网络是独立的,强行合并配置会增加耦合。
陷阱 9:IAM 权限过宽
# providers/aws.tf
provider "aws" {
region = "ap-southeast-1"
default_tags {
Environment = "production"
ManagedBy = "terraform"
Project = "myapp"
}
}
# providers/alicloud.tf
provider "alicloud" {
region = "cn-hangzhou"
profile = "default"
}
# providers/azurerm.tf
provider "azurerm" {
features {}
subscription_id = var.azure_subscription_id
}
# providers/google.tf
provider "google" {
project = var.gcp_project_id
region = "asia-southeast1"
}
6正确做法:给 Terraform 创建专用 IAM 用户 / 角色,权限最小化。
陷阱 10:日志泄露敏感信息
# providers/aws.tf
provider "aws" {
region = "ap-southeast-1"
default_tags {
Environment = "production"
ManagedBy = "terraform"
Project = "myapp"
}
}
# providers/alicloud.tf
provider "alicloud" {
region = "cn-hangzhou"
profile = "default"
}
# providers/azurerm.tf
provider "azurerm" {
features {}
subscription_id = var.azure_subscription_id
}
# providers/google.tf
provider "google" {
project = var.gcp_project_id
region = "asia-southeast1"
}
7正确做法:
# providers/aws.tf
provider "aws" {
region = "ap-southeast-1"
default_tags {
Environment = "production"
ManagedBy = "terraform"
Project = "myapp"
}
}
# providers/alicloud.tf
provider "alicloud" {
region = "cn-hangzhou"
profile = "default"
}
# providers/azurerm.tf
provider "azurerm" {
features {}
subscription_id = var.azure_subscription_id
}
# providers/google.tf
provider "google" {
project = var.gcp_project_id
region = "asia-southeast1"
}
8sensitive = true 后,Terraform 默认不在 plan/apply 输出中显示这个变量值。
实战八:迁移现有资源到 Terraform
方法 1:terraform import
# providers/aws.tf
provider "aws" {
region = "ap-southeast-1"
default_tags {
Environment = "production"
ManagedBy = "terraform"
Project = "myapp"
}
}
# providers/alicloud.tf
provider "alicloud" {
region = "cn-hangzhou"
profile = "default"
}
# providers/azurerm.tf
provider "azurerm" {
features {}
subscription_id = var.azure_subscription_id
}
# providers/google.tf
provider "google" {
project = var.gcp_project_id
region = "asia-southeast1"
}
9导入后,Terraform 接管该资源。下次 plan 时会显示资源的当前状态(不是 Terraform 代码写的状态)。
风险提示:导入只能导入已有资源,要让 Terraform 真的不重新创建,需要把资源的当前属性写到 Terraform 代码里。
方法 2:Terraformer
Terraformer 是 Google 出的工具,能自动从云上扫描资源并生成 Terraform 代码:
# backend.tf
terraform {
backend "s3" {
bucket = "myorg-terraform-state"
key = "multi-cloud/terraform.tfstate"
region = "ap-southeast-1"
encrypt = true
kms_key_id = "arn:aws:kms:ap-southeast-1:111122223333:key/abcd-1234"
dynamodb_table = "terraform-lock"
}
}
0生成的代码放在 generated/ 目录。
方法 3:手动写 + moved 块
Terraform 1.1+ 提供 moved 块,资源重命名时不需要 destroy/import:
# backend.tf
terraform {
backend "s3" {
bucket = "myorg-terraform-state"
key = "multi-cloud/terraform.tfstate"
region = "ap-southeast-1"
encrypt = true
kms_key_id = "arn:aws:kms:ap-southeast-1:111122223333:key/abcd-1234"
dynamodb_table = "terraform-lock"
}
}
1实战九:跨云灾备
案例:阿里云主 + AWS 备
# backend.tf
terraform {
backend "s3" {
bucket = "myorg-terraform-state"
key = "multi-cloud/terraform.tfstate"
region = "ap-southeast-1"
encrypt = true
kms_key_id = "arn:aws:kms:ap-southeast-1:111122223333:key/abcd-1234"
dynamodb_table = "terraform-lock"
}
}
2跨云灾备的关键:
数据同步(OSS → S3、PolarDB → RDS、Redis AOF)。 健康检查 + DNS 切换(Route 53 / 阿里云 DNS)。 演练(季度 / 半年一次)。
实战十:Policy as Code(Sentinel / OPA)
商业版 Terraform Cloud / Enterprise 提供 Sentinel 策略引擎。开源方案是 OPA + Conftest。
# backend.tf
terraform {
backend "s3" {
bucket = "myorg-terraform-state"
key = "multi-cloud/terraform.tfstate"
region = "ap-southeast-1"
encrypt = true
kms_key_id = "arn:aws:kms:ap-southeast-1:111122223333:key/abcd-1234"
dynamodb_table = "terraform-lock"
}
}
3# backend.tf
terraform {
backend "s3" {
bucket = "myorg-terraform-state"
key = "multi-cloud/terraform.tfstate"
region = "ap-southeast-1"
encrypt = true
kms_key_id = "arn:aws:kms:ap-southeast-1:111122223333:key/abcd-1234"
dynamodb_table = "terraform-lock"
}
}
4CI 流水线里加这一步骤,违规就阻断。
实战十一:成本管理
成本估算
Terraform Cloud / Infracost 提供 cost estimation:
# backend.tf
terraform {
backend "s3" {
bucket = "myorg-terraform-state"
key = "multi-cloud/terraform.tfstate"
region = "ap-southeast-1"
encrypt = true
kms_key_id = "arn:aws:kms:ap-southeast-1:111122223333:key/abcd-1234"
dynamodb_table = "terraform-lock"
}
}
5CI 集成 Infracost,每次 PR 显示 cost 变化:
# backend.tf
terraform {
backend "s3" {
bucket = "myorg-terraform-state"
key = "multi-cloud/terraform.tfstate"
region = "ap-southeast-1"
encrypt = true
kms_key_id = "arn:aws:kms:ap-southeast-1:111122223333:key/abcd-1234"
dynamodb_table = "terraform-lock"
}
}
6标签规范
# backend.tf
terraform {
backend "s3" {
bucket = "myorg-terraform-state"
key = "multi-cloud/terraform.tfstate"
region = "ap-southeast-1"
encrypt = true
kms_key_id = "arn:aws:kms:ap-southeast-1:111122223333:key/abcd-1234"
dynamodb_table = "terraform-lock"
}
}
7标签让账单分析、权限管理、自动化都更容易。
实战十二:实战案例:完整的多云项目
背景
某 SaaS 公司:AWS 主力(数据库 + 核心服务)、阿里云辅助(中国用户)、Cloudflare 全球 CDN。
项目结构
# backend.tf
terraform {
backend "s3" {
bucket = "myorg-terraform-state"
key = "multi-cloud/terraform.tfstate"
region = "ap-southeast-1"
encrypt = true
kms_key_id = "arn:aws:kms:ap-southeast-1:111122223333:key/abcd-1234"
dynamodb_table = "terraform-lock"
}
}
8跨云共享:CDN
# backend.tf
terraform {
backend "s3" {
bucket = "myorg-terraform-state"
key = "multi-cloud/terraform.tfstate"
region = "ap-southeast-1"
encrypt = true
kms_key_id = "arn:aws:kms:ap-southeast-1:111122223333:key/abcd-1234"
dynamodb_table = "terraform-lock"
}
}
9实战十三:常见监控和告警
CloudWatch 告警
# 阿里云 OSS 后端
terraform {
backend "oss" {
bucket = "myorg-terraform-state"
key = "multi-cloud/terraform.tfstate"
region = "cn-hangzhou"
prefix = "terraform/state"
encrypt = true
}
}
# 腾讯云 COS 后端
terraform {
backend "cos" {
secret_id = var.tencent_secret_id
secret_key = var.tencent_secret_key
region = "ap-shanghai"
bucket = "myorg-terraform-state-1234567890"
prefix = "terraform/state"
key = "multi-cloud/terraform.tfstate"
}
}
0阿里云云监控
# 阿里云 OSS 后端
terraform {
backend "oss" {
bucket = "myorg-terraform-state"
key = "multi-cloud/terraform.tfstate"
region = "cn-hangzhou"
prefix = "terraform/state"
encrypt = true
}
}
# 腾讯云 COS 后端
terraform {
backend "cos" {
secret_id = var.tencent_secret_id
secret_key = var.tencent_secret_key
region = "ap-shanghai"
bucket = "myorg-terraform-state-1234567890"
prefix = "terraform/state"
key = "multi-cloud/terraform.tfstate"
}
}
1实战十四:故障案例复盘
案例 1:state 锁死导致 apply 卡 6 小时
现象:CI pipeline terraform apply 卡在 acquiring state lock 6 小时。
根因:上一次 CI job OOM 退出,state 锁未释放。
修复:
# 阿里云 OSS 后端
terraform {
backend "oss" {
bucket = "myorg-terraform-state"
key = "multi-cloud/terraform.tfstate"
region = "cn-hangzhou"
prefix = "terraform/state"
encrypt = true
}
}
# 腾讯云 COS 后端
terraform {
backend "cos" {
secret_id = var.tencent_secret_id
secret_key = var.tencent_secret_key
region = "ap-shanghai"
bucket = "myorg-terraform-state-1234567890"
prefix = "terraform/state"
key = "multi-cloud/terraform.tfstate"
}
}
2复盘:CI 加超时机制,apply 超时后清理 lock。Terraform 1.6+ 锁有自动过期。
案例 2:误删生产 RDS
现象:测试环境跑 terraform destroy 时忘记切环境变量,误删了生产 RDS 实例。
根因:terraform destroy 不带 -target 会销毁所有 state 里的资源,工程师切错 profile。
修复:
强制使用 prevent_destroy标记关键资源:
# 阿里云 OSS 后端
terraform {
backend "oss" {
bucket = "myorg-terraform-state"
key = "multi-cloud/terraform.tfstate"
region = "cn-hangzhou"
prefix = "terraform/state"
encrypt = true
}
}
# 腾讯云 COS 后端
terraform {
backend "cos" {
secret_id = var.tencent_secret_id
secret_key = var.tencent_secret_key
region = "ap-shanghai"
bucket = "myorg-terraform-state-1234567890"
prefix = "terraform/state"
key = "multi-cloud/terraform.tfstate"
}
}
3IAM 权限隔离:测试 IAM 不能动生产资源。 terraform destroy加二次确认。数据库开启自动备份 + Point-in-Time Recovery。
案例 3:Provider 升级导致资源重建
现象:升级 hashicorp/aws 5.0 → 5.50,plan 显示要重建 200 个 EC2 实例。
根因:新版本对某些字段默认值做了调整,触发资源属性变更。
修复:
升级前在测试环境 plan,diff 确认。 强制锁定资源不重建:
# 阿里云 OSS 后端
terraform {
backend "oss" {
bucket = "myorg-terraform-state"
key = "multi-cloud/terraform.tfstate"
region = "cn-hangzhou"
prefix = "terraform/state"
encrypt = true
}
}
# 腾讯云 COS 后端
terraform {
backend "cos" {
secret_id = var.tencent_secret_id
secret_key = var.tencent_secret_key
region = "ap-shanghai"
bucket = "myorg-terraform-state-1234567890"
prefix = "terraform/state"
key = "multi-cloud/terraform.tfstate"
}
}
4Provider 升级拆小步,不要一次跳多个 minor。
案例 4:跨 region 资源错配
现象:plan 在 ap-southeast-1,但实际创建在 us-east-1。
根因:CI 环境变量没传,Terraform 用了默认 region。
修复:CI 强制注入 AWS_REGION、ALICLOUD_REGION 等变量,并在 plan 输出中校验。
风险提示清单
**生产 terraform destroy**:必须加审批,必须用-target限制范围。** force-unlock**:确认无人在 apply。provider 升级:测试环境先 plan,prod 环境不变更字段。 资源 attribute 变化:用 lifecycle { ignore_changes = [...] }屏蔽。敏感信息:用 Vault / KMS / Parameter Store / 环境变量,不要写代码。 IAM 权限:Terraform 用专用账号,最小权限。 状态文件加密:S3 / OSS 开启 SSE-KMS。 跨云网络:VPC Peering / VPN / SD-WAN 配置要单独管理。 CI 流水线泄露 plan:plan 输出可能含敏感信息,加 sensitive = true标记。destroy protection:关键资源加 lifecycle { prevent_destroy = true }。State 备份:S3 开启 versioning,定期备份到异地。 多云账户:用 AWS Organizations / 阿里云资源目录 / GCP Folders 统一管理。
最佳实践 Checklist
[ ] 项目分层: modules/、environments/、providers/分离。[ ] 状态后端用远程(不用 local),加锁、加密。 [ ] 变量用 variable块定义,敏感变量标记sensitive。[ ] 资源命名规范: {project}-{env}-{role}-{instance}。[ ] 统一标签: Environment、ManagedBy、Project、CostCenter、Owner。[ ] 模块化:业务模块和基础设施模块分开。 [ ] 版本约束: required_version、required_providers、module.version。[ ] terraform fmt统一格式。[ ] terraform validate静态检查。[ ] tflint静态检查(社区 linter)。[ ] checkov/tfsec安全扫描。[ ] 关键资源加 prevent_destroy。[ ] 漂移检测:定时 plan / driftctl。 [ ] CI 集成:plan → review → apply 流程。 [ ] 敏感信息用 Vault / KMS,不进代码。 [ ] Policy as Code:OPA / Conftest 阻断违规。 [ ] 成本监控:Infracost / 账单分析。 [ ] 文档:每个 module 有 README,说明 inputs / outputs / 用途。
常见问题 FAQ
Q1:Terraform 1.5+ 跟以前有什么不一样?
A:1.1+ 引入 moved 块做资源重命名,1.2+ 引入 removed 块,1.5+ 引入 import block、refresh-only plan、check block,1.6+ 加 state lock 自动过期。生产建议 1.6+。
Q2:Terraform 1.x 之后还有 Terraform 0.x 吗?
A:没有了。Terraform 0.13 之后改为 1.0。当前最新是 1.7+(以实际版本为准)。
Q3:OpenTofu 是什么?
A:HashiCorp 把 Terraform 改 BSL 协议后,社区 fork 出 OpenTofu(基于 Terraform 1.5)。OpenTofu 是 MPL 协议开源,兼容 Terraform 1.5 API。
Q4:Terraform 和 Pulumi 选哪个?
A:Terraform 是声明式 HCL,生态最大。Pulumi 用通用语言(Python、Go、TypeScript)写 IaC,对程序员更友好,但生态略小。多数团队用 Terraform。
Q5:Terraform 怎么加密敏感变量?
A:三种方式:(1) sensitive = true 标记,CI 输出不显示;(2) 后端用 SSE-KMS;(3) 敏感值从 Vault / KMS / Parameter Store 读,不写在 tfvars 里。
Q6:Terraform 的 state 文件能共享吗?
A:可以,但要避免多人同时改。用远程后端 + 锁,每个环境一个 state,按目录或 workspace 隔离。
Q7:怎么从云控制台手工创建的资源迁移到 Terraform?
A:用 terraform import(单资源)或 terraformer(批量)。导入后把资源属性写进 Terraform 代码。
Q8:Terraform 怎么管理已经存在但不在 state 里的资源?
A:terraform import 把资源加入 state,然后写 Terraform 代码描述它。
Q9:Terraform 跑在 K8s 里?
A:可以,常见的做法是 terraform-operator / Spacelift Agent / Atlantis。生产里用 Kubernetes 跑 Atlantis Pod 比较常见。
Q10:怎么减少 apply 时间?
A:(1) 用 -target 限定范围;(2) 用 -parallelism 提高并发;(3) 把大 state 拆成小 state;(4) 用 -refresh=false 跳过 refresh(不推荐,可能漏掉漂移)。
Q11:Terraform Cloud / Enterprise 值得用吗?
A:团队规模小(< 5 人)、项目少(< 10 个),用 GitHub Actions + S3 后端足够。规模大了上 Terraform Cloud / Spacelift / Env0,节省状态管理、policy、审计成本。
Q12:如何处理跨云资源依赖?
A:避免强耦合。把多云资源分到不同 module / state,跨云信息通过 output + 远程 state 数据源传递(terraform_remote_state)。
Q13:Terraform drift 怎么处理?
A:定期 terraform plan -detailed-exitcode 或用 driftctl。漂移原因通常是人手工改了云上资源。处理:(1) 重新 apply 让 state 同步;(2) 把真实状态写进 Terraform 代码;(3) 严禁手工改云上资源(这是 IaC 的核心约定)。
Q14:怎么测试 Terraform 代码?
A:商业版有 Sentinel / OPA。开源自建:单元测试用 terraform plan 验证资源数 / 属性,集成测试用 terratest(Go)。
总结
Terraform 解决的是"用统一语言描述多云资源"的问题。但实际落地需要:
理解每个云的资源模型和差异。 严格管理 state(远程、加密、加锁)。 模块化设计(避免一个 state 太大)。 流水线集成(plan → review → apply)。 漂移检测(保证期望和实际一致)。 Policy as Code(安全合规)。 成本监控(多云账单分析)。
核心心法:
所有资源用代码描述,禁手工改云上。 状态用远程后端,加锁加密。 流水线审批后才 apply。 模块化拆分,避免大 state。 漂移检测,定时 plan。 敏感信息走 Vault / KMS。 关键资源 prevent_destroy。
把这套流程走完,多云管理能上一个台阶。
附录:常用命令速查
# 阿里云 OSS 后端
terraform {
backend "oss" {
bucket = "myorg-terraform-state"
key = "multi-cloud/terraform.tfstate"
region = "cn-hangzhou"
prefix = "terraform/state"
encrypt = true
}
}
# 腾讯云 COS 后端
terraform {
backend "cos" {
secret_id = var.tencent_secret_id
secret_key = var.tencent_secret_key
region = "ap-shanghai"
bucket = "myorg-terraform-state-1234567890"
prefix = "terraform/state"
key = "multi-cloud/terraform.tfstate"
}
}
5附录:HCL 语法速查
# 阿里云 OSS 后端
terraform {
backend "oss" {
bucket = "myorg-terraform-state"
key = "multi-cloud/terraform.tfstate"
region = "cn-hangzhou"
prefix = "terraform/state"
encrypt = true
}
}
# 腾讯云 COS 后端
terraform {
backend "cos" {
secret_id = var.tencent_secret_id
secret_key = var.tencent_secret_key
region = "ap-shanghai"
bucket = "myorg-terraform-state-1234567890"
prefix = "terraform/state"
key = "multi-cloud/terraform.tfstate"
}
}
6附录:资源属性与字段示例
AWS EC2
# 阿里云 OSS 后端
terraform {
backend "oss" {
bucket = "myorg-terraform-state"
key = "multi-cloud/terraform.tfstate"
region = "cn-hangzhou"
prefix = "terraform/state"
encrypt = true
}
}
# 腾讯云 COS 后端
terraform {
backend "cos" {
secret_id = var.tencent_secret_id
secret_key = var.tencent_secret_key
region = "ap-shanghai"
bucket = "myorg-terraform-state-1234567890"
prefix = "terraform/state"
key = "multi-cloud/terraform.tfstate"
}
}
7阿里云 ECS
# 阿里云 OSS 后端
terraform {
backend "oss" {
bucket = "myorg-terraform-state"
key = "multi-cloud/terraform.tfstate"
region = "cn-hangzhou"
prefix = "terraform/state"
encrypt = true
}
}
# 腾讯云 COS 后端
terraform {
backend "cos" {
secret_id = var.tencent_secret_id
secret_key = var.tencent_secret_key
region = "ap-shanghai"
bucket = "myorg-terraform-state-1234567890"
prefix = "terraform/state"
key = "multi-cloud/terraform.tfstate"
}
}
8腾讯云 CVM
# 阿里云 OSS 后端
terraform {
backend "oss" {
bucket = "myorg-terraform-state"
key = "multi-cloud/terraform.tfstate"
region = "cn-hangzhou"
prefix = "terraform/state"
encrypt = true
}
}
# 腾讯云 COS 后端
terraform {
backend "cos" {
secret_id = var.tencent_secret_id
secret_key = var.tencent_secret_key
region = "ap-shanghai"
bucket = "myorg-terraform-state-1234567890"
prefix = "terraform/state"
key = "multi-cloud/terraform.tfstate"
}
}
9附录:常见资源 type 速查
不同 provider 版本字段可能略有差异,以实际版本为准。
附录:参考资源
Terraform 官方文档:https://developer.hashicorp.com/terraform Terraform Registry:https://registry.terraform.io/ AWS Provider 文档:https://registry.terraform.io/providers/hashicorp/aws/latest/docs 阿里云 Provider 文档:https://registry.terraform.io/providers/aliyun/alicloud/latest/docs Infracost:https://www.infracost.io/ Driftctl:https://driftctl.com/ Atlantis:https://www.runatlantis.io/ Terragrunt:https://terragrunt.gruntwork.io/ Checkov:https://www.checkov.io/ tflint:https://github.com/terraform-linters/tflint Conftest:https://www.conftest.dev/
推荐站内搜索:最好用的开发软件、免费开源系统、渗透测试工具云盘下载、最新渗透测试资料、最新黑客工具下载……




发表评论