前言:在云時代,企業的IT基礎設施早已從“幾臺服務器”演變為“橫跨多云的復雜網絡、計算、存儲集群”。但隨之而來的,是管理復雜度的爆炸式增長:開發環境和生產環境不一致、手動配置容易出錯、多云平臺操作方式各異、資源變更難以追溯……這些問題不僅拖慢迭代速度,更可能埋下合規與安全隱患。
于是,“基礎設施即代碼(IaC)”成為破局的關鍵——用代碼定義基礎設施,像管理應用代碼一樣管理服務器、網絡和數據庫。而Terraform,正是這一領域的標桿工具。
它不綁定任何單一云廠商,能統一管理阿里云、Azure、AWS等所有主流平臺;它用聲明式語法描述“目標狀態”,無需關心“如何一步步實現”;它通過狀態文件記錄資源信息,自動處理變更與依賴……無論是初創公司的簡單部署,還是大型企業的多云架構,Terraform都能提供一致、可重復、可審計的基礎設施管理流程。
本文將從Terraform的起源講起,拆解其核心原理與功能,再通過兩個實戰案例(阿里云ECS與Azure VM完整部署),帶你掌握“配置文件定義→初始化→計劃→應用”的核心流程。即使是IaC新手,也能跟著步驟從零搭建起可用的云主機環境,真正體會“代碼即基礎設施”的高效與可靠。
一文帶你從 0 到 1 掌握 Terraform:了解它從哪里來、如何工作、能做什么,以及如何按“配置文件定義 → 初始化 → 計劃 → 應用”的核心流程,在阿里云 ECS和微軟 Azure上動手創建可用的云主機。AWS/GCP 等其他云的流程一致,僅資源與配置細節不同。
一、Terraform 是什么?為什么用它?
Terraform 是 HashiCorp 推出的 IaC(Infrastructure as Code,基礎設施即代碼)工具,通過聲明式配置統一管理多云(阿里云、Azure、AWS、GCP 等)與本地資源(網絡、主機、數據庫、K8s、DNS、CDN……)。
核心收益
- 可重復:同一份配置能在開發、測試、生產等多環境一致部署。
- 可審計:基礎設施改動以代碼形式記錄,配合 Git 可輕松審核、回滾。
- 可協作:支持模塊化、遠程狀態管理,便于團隊并行開發。
- 多云統一:一套工作流適配多個云廠商,避免被單一云平臺鎖定。
二、發展歷史(里程碑)
- 2014年:首個版本發布,提出“Plan/Apply”工作流與資源依賴圖(DAG)核心概念。
- 2015–2018年:生態快速擴張,支持的云廠商(Provider)持續增加;“遠程狀態存儲”“狀態鎖”等團隊協作最佳實踐逐漸形成。
- 2019年(v0.12):引入 HCL2 語法,語言表達力大幅增強(支持
for
循環、dynamic
塊、條件表達式等)。 - 2020年(v0.13):支持多 Provider 源,模塊的
count
/for_each
等特性更易用。 - 2021年(v1.0):發布標志性穩定版,承諾 1.x 版本兼容性。
- 2023年:許可協議調整為 BUSL,社區分叉出 OpenTofu(開源且與 Terraform 配置基本兼容)。
- 2024–2025年(1.x):持續迭代,在“漂移檢測”“供應鏈安全”“測試能力”等方面優化。
說明:本文以 Terraform 1.x 為例;若選擇 OpenTofu,命令與語法幾乎一致(將
terraform
替換為tofu
即可),可平滑遷移。
三、工作原理(核心概念)
Terraform 核心邏輯可概括為“聲明式描述 + 自動化執行 + 狀態記憶”,依賴以下關鍵概念:
- HCL 配置:通過
.tf
文件聲明式描述基礎設施的“期望狀態”(無需關心“如何一步步創建”)。 - 資源依賴圖(DAG):Terraform 會解析資源間的依賴關系,并行創建無依賴沖突的資源,保證執行效率與順序性。
- Plan/Apply 工作流:
terraform plan
:比對“期望狀態(配置文件)”與“當前狀態(State)”,生成“執行計劃”(告知會新增、變更、銷毀哪些資源)。terraform apply
:按計劃執行變更,讓基礎設施與配置“同步”。
- State(狀態):通過
.tfstate
文件記錄已創建資源的“實際狀態與 ID”,是 Terraform “記憶能力”的核心。支持狀態鎖(防止多人并發操作沖突)與遠程存儲(如 OSS、Azure Blob、S3,便于團隊協作)。 - Provider:與具體云平臺/服務交互的插件(如
alicloud
對接阿里云,azurerm
對接 Azure)。 - Resource / Data Source:
Resource
用于“創建/變更資源”;Data Source
用于只讀查詢現有資源信息(如“最新 Ubuntu 鏡像 ID”)。 - Module:可復用的配置單元,能在團隊內/外共享、版本化管理(類似“代碼函數”,封裝通用基礎設施邏輯)。
總結:Terraform = HCL(聲明期望) + Provider(執行操作) + State(記憶狀態) + DAG(并發/有序執行)。
四、核心功能一覽
- 多云/混合云統一管理:一套聲明式配置,同時管理阿里云、Azure、AWS、GCP 及本地資源。
- 冪等與并發:重復執行配置時,自動跳過“已符合期望狀態”的資源;并通過依賴圖并行創建無沖突資源。
- 遠程狀態與鎖:支持將
.tfstate
存儲在 OSS、Azure Storage、S3 等遠程服務,配合“狀態鎖”避免多人操作沖突。 - 漂移檢測(Drift):
terraform plan
階段可自動發現“手動修改控制臺資源”與“代碼配置”的不一致。 - 資源導入(Import):能將已有手動創建的資源,納入 Terraform 代碼管理。
- 模塊化復用:通過“模塊”封裝通用邏輯(如“生產級 VPC 模板”),結合 Terraform Registry(公共模塊庫)或私有模塊庫復用。
- 策略管控:配合 Sentinel、OPA 等工具,進行合規與安全檢查(如“禁止創建公網可訪問的數據庫”)。
五、上手前準備
- 安裝 Terraform:參考 官方安裝指南(建議 1.3+,推薦 1.6+)。
- 生成 SSH 公鑰:執行
ssh-keygen -t rsa -b 4096
(或ed25519
),生成~/.ssh/id_rsa.pub
(用于云主機免密登錄)。 - 云廠商憑據準備:
- 阿里云:建議通過環境變量傳遞(避免硬編碼):
export ALICLOUD_ACCESS_KEY="你的AccessKey ID" export ALICLOUD_SECRET_KEY="你的AccessKey Secret" export ALICLOUD_REGION="目標地域(如 cn-hongkong)"
- Azure:使用 Azure CLI 登錄并選擇訂閱:
az login az account set -s <你的訂閱ID>
- 阿里云:建議通過環境變量傳遞(避免硬編碼):
- 費用提示:創建云資源會產生費用,練習完成后請執行
terraform destroy
清理資源。
六、實戰:阿里云 ECS 完整部署(VPC + 子網 + 安全組 + EIP + 實例)
項目結構
創建如下目錄結構,分離配置文件:
terraform-demo/
├─ aliyun/ # 阿里云 ECS 示例
│ ├─ main.tf # 核心配置
│ ├─ variables.tf # 變量定義
│ ├─ outputs.tf # 輸出結果
│ └─ versions.tf # 版本約束
└─ .gitignore # 忽略敏感文件(如 .tfstate)
1. 版本約束(aliyun/versions.tf
)
terraform {required_version = ">= 1.3.0"required_providers {alicloud = {source = "aliyun/alicloud"version = ">= 1.0"}}
}
2. 變量定義(aliyun/variables.tf
)
variable "name" { type = string default = "tf-ecs-demo"
}
variable "region" { type = string default = "cn-hongkong"
}
variable "zone_id" { type = string default = "cn-hongkong-b"
}variable "vpc_cidr" { type = string default = "10.10.0.0/16" }
variable "vsw_cidr" { type = string default = "10.10.1.0/24" }
variable "instance_type" { type = string } # 示例:ecs.t5-lc1m1.small(需與地域匹配)variable "ssh_public_key" { type = string } # 傳入 ~/.ssh/id_rsa.pub 內容# 生產建議收斂為辦公網 IP 段,練習用 0.0.0.0/0
variable "allowed_ssh_cidr" { type = string default = "0.0.0.0/0" }# 可選:手動指定鏡像 ID,否則自動選最新 Ubuntu
variable "image_id" { type = string default = "" }
3. 核心配置(aliyun/main.tf
)
provider "alicloud" {region = var.region
}# 自動查詢最新 Ubuntu 22.04 鏡像(正則匹配,可按需調整)
data "alicloud_images" "ubuntu" {name_regex = "^ubuntu_22_04.*x64.*" owners = "system"most_recent = true
}# 創建 VPC
resource "alicloud_vpc" "this" {name = "${var.name}-vpc"cidr_block = var.vpc_cidr
}# 創建子網
resource "alicloud_vswitch" "this" {name = "${var.name}-vsw"vpc_id = alicloud_vpc.this.idcidr_block = var.vsw_cidravailability_zone = var.zone_id
}# 創建安全組
resource "alicloud_security_group" "this" {name = "${var.name}-sg"vpc_id = alicloud_vpc.this.id
}# 安全組規則:允許 SSH(22 端口)
resource "alicloud_security_group_rule" "ssh" {type = "ingress"ip_protocol = "tcp"port_range = "22/22"priority = 1cidr_ip = var.allowed_ssh_cidrsecurity_group_id = alicloud_security_group.this.id
}# 導入本地 SSH 公鑰為阿里云密鑰對
resource "alicloud_key_pair" "kp" {key_pair_name = "${var.name}-kp"public_key = var.ssh_public_key
}# 申請公網 EIP
resource "alicloud_eip" "eip" {name = "${var.name}-eip"bandwidth = 5
}# 創建 ECS 實例
resource "alicloud_instance" "this" {instance_name = var.nameavailability_zone = var.zone_idinstance_type = var.instance_type# 優先用手動指定的鏡像,否則用數據源查詢的最新 Ubuntuimage_id = var.image_id != "" ? var.image_id : data.alicloud_images.ubuntu.images[0].idsecurity_groups = [alicloud_security_group.this.id]vswitch_id = alicloud_vswitch.this.idsystem_disk_category = "cloud_efficiency"internet_charge_type = "PayByTraffic"key_name = alicloud_key_pair.kp.key_pair_nametags = {Project = "terraform-demo"Cloud = "alicloud"}
}# 綁定 EIP 到 ECS
resource "alicloud_eip_association" "bind" {allocation_id = alicloud_eip.eip.idinstance_id = alicloud_instance.this.id
}
4. 輸出結果(aliyun/outputs.tf
)
output "ecs_id" {value = alicloud_instance.this.id
}output "ecs_public_ip" {value = alicloud_eip.eip.ip_address
}
5. 執行部署
cd aliyun# 傳入變量(實例規格 + SSH 公鑰)
terraform init
terraform validate
terraform plan -var "instance_type=ecs.t5-lc1m1.small" \-var "ssh_public_key=$(cat ~/.ssh/id_rsa.pub)"
# 自動批準執行(生產建議先手動確認 plan)
terraform apply -auto-approve -var "instance_type=ecs.t5-lc1m1.small" \-var "ssh_public_key=$(cat ~/.ssh/id_rsa.pub)"# 登錄 ECS(用輸出的公網 IP)
ssh -i ~/.ssh/id_rsa root@$(terraform output -raw ecs_public_ip)# 清理資源(務必執行)
terraform destroy
小貼士:若
instance_type
與地域不匹配,可到阿里云控制臺查看“可用實例規格”,或更換zone_id
。
七、實戰:Azure Linux VM 完整部署(VNet + 子網 + NSG + 公網 IP + NIC + VM)
項目結構
類似阿里云,創建 azure/
目錄存放配置:
terraform-demo/
├─ azure/ # Azure VM 示例
│ ├─ main.tf
│ ├─ variables.tf
│ ├─ outputs.tf
│ └─ versions.tf
└─ .gitignore
1. 版本約束(azure/versions.tf
)
terraform {required_version = ">= 1.3.0"required_providers {azurerm = {source = "hashicorp/azurerm"version = ">= 3.0"}}
}
2. 變量定義(azure/variables.tf
)
variable "name" { type = string default = "tf-az-vm" }
variable "location" { type = string default = "East Asia" } # 香港區域variable "vnet_cidr" { type = string default = "10.20.0.0/16" }
variable "subnet_cidr" { type = string default = "10.20.1.0/24" }
variable "vm_size" { type = string default = "Standard_B1s" }variable "admin_username" { type = string default = "azureuser" }
variable "ssh_public_key" { type = string }
3. 核心配置(azure/main.tf
)
provider "azurerm" { features {} }# 創建資源組
resource "azurerm_resource_group" "rg" {name = "${var.name}-rg"location = var.location
}# 創建虛擬網絡(VNet)
resource "azurerm_virtual_network" "vnet" {name = "${var.name}-vnet"address_space = [var.vnet_cidr]location = var.locationresource_group_name = azurerm_resource_group.rg.name
}# 創建子網
resource "azurerm_subnet" "subnet" {name = "${var.name}-subnet"resource_group_name = azurerm_resource_group.rg.namevirtual_network_name = azurerm_virtual_network.vnet.nameaddress_prefixes = [var.subnet_cidr]
}# 創建網絡安全組(NSG)
resource "azurerm_network_security_group" "nsg" {name = "${var.name}-nsg"location = var.locationresource_group_name = azurerm_resource_group.rg.name# 允許 SSH(22 端口)入站security_rule {name = "Allow-SSH"priority = 100direction = "Inbound"access = "Allow"protocol = "Tcp"source_port_range = "*"destination_port_range = "22"source_address_prefix = "*" # 生產建議收斂為辦公網 IPdestination_address_prefix = "*"}
}# 關聯 NSG 與子網
resource "azurerm_subnet_network_security_group_association" "assoc" {subnet_id = azurerm_subnet.subnet.idnetwork_security_group_id = azurerm_network_security_group.nsg.id
}# 創建公網 IP
resource "azurerm_public_ip" "pip" {name = "${var.name}-pip"location = var.locationresource_group_name = azurerm_resource_group.rg.nameallocation_method = "Static"sku = "Standard"
}# 創建網絡接口(NIC)
resource "azurerm_network_interface" "nic" {name = "${var.name}-nic"location = var.locationresource_group_name = azurerm_resource_group.rg.nameip_configuration {name = "primary"subnet_id = azurerm_subnet.subnet.idprivate_ip_address_allocation = "Dynamic"public_ip_address_id = azurerm_public_ip.pip.id}
}# 創建 Linux 虛擬機
resource "azurerm_linux_virtual_machine" "vm" {name = var.namelocation = var.locationresource_group_name = azurerm_resource_group.rg.namesize = var.vm_sizeadmin_username = var.admin_usernamenetwork_interface_ids = [azurerm_network_interface.nic.id]# 注入 SSH 公鑰admin_ssh_key {username = var.admin_usernamepublic_key = var.ssh_public_key}os_disk {caching = "ReadWrite"storage_account_type = "Standard_LRS"}# 使用最新 Ubuntu 22.04 LTS 鏡像source_image_reference {publisher = "Canonical"offer = "0001-com-ubuntu-server-jammy"sku = "22_04-lts-gen2"version = "latest"}tags = {Project = "terraform-demo"Cloud = "azure"}
}
4. 輸出結果(azure/outputs.tf
)
output "vm_id" {value = azurerm_linux_virtual_machine.vm.id
}output "public_ip" {value = azurerm_public_ip.pip.ip_address
}
5. 執行部署
cd azure# Azure CLI 登錄并選擇訂閱
az login
az account set -s <你的訂閱ID>terraform init
terraform validate
terraform plan -var "ssh_public_key=$(cat ~/.ssh/id_rsa.pub)"
terraform apply -auto-approve -var "ssh_public_key=$(cat ~/.ssh/id_rsa.pub)"# 登錄 VM(默認用戶為 azureuser)
ssh -i ~/.ssh/id_rsa azureuser@$(terraform output -raw public_ip)# 清理資源
terraform destroy
八、核心工作流回顧(配置 → 初始化 → 計劃 → 應用)
Terraform 遵循**“描述期望 → 準備環境 → 預覽變更 → 執行變更”**的流程:
- 配置(Write):通過
.tf
文件聲明基礎設施的“期望狀態”。 - 初始化(Init):執行
terraform init
,下載 Provider 插件、初始化后端(如遠程狀態存儲)。 - 計劃(Plan):執行
terraform plan
,預覽將“新增、變更、銷毀”的資源。 - 應用(Apply):執行
terraform apply
,按計劃變更基礎設施。 - 銷毀(Destroy):執行
terraform destroy
,清理不再需要的資源。
常用輔助命令:
terraform fmt
:自動格式化配置文件,統一代碼風格。terraform validate
:校驗配置語法與邏輯合法性。terraform show
:查看當前狀態的詳細信息。terraform output
:讀取配置中定義的“輸出值”(如公網 IP)。terraform graph
:生成資源依賴關系圖(需安裝 Graphviz)。
九、進階技巧:團隊協作與生產級實踐
1. 遠程狀態與鎖(團隊必備)
默認狀態文件 .tfstate
存儲在本地,團隊協作時易沖突。推薦使用遠程后端(如阿里云 OSS、Azure Storage、AWS S3):
- 阿里云 OSS 后端(需先創建 Bucket):
在根模塊的terraform
塊中添加:terraform {backend "oss" {bucket = "你的OSS桶名"prefix = "envs/dev" # 按環境區分region = "cn-hangzhou"} }
- Azure Storage 后端(需先創建 Storage Account/Container):
terraform {backend "azurerm" {resource_group_name = "rg-tfstate"storage_account_name = "mystatestorage"container_name = "tfstate"key = "azure/dev.terraform.tfstate"} }
注意:后端配置初始化后,若需修改,需執行
terraform init -migrate-state
遷移狀態。
2. 變量、機密與環境區分
- 變量注入方式:
- 命令行參數:
terraform apply -var "instance_type=ecs.t6-c1m2.large"
。 - 變量文件:
-var-file=dev.tfvars
(將變量集中寫在dev.tfvars
文件)。 - 環境變量:以
TF_VAR_
為前綴(如TF_VAR_ssh_public_key
)。
- 命令行參數:
- 敏感信息處理:
不要將 AccessKey、私鑰、.tfstate
提交到 Git;推薦使用密鑰管理工具(如 HashiCorp Vault、Azure Key Vault)。 - 多環境管理(工作空間):
通過terraform workspace
管理多環境(如 dev、test、prod):
不同環境可復用同一份代碼,通過變量區分配置。terraform workspace new dev # 創建 dev 環境 terraform workspace select dev # 切換到 dev 環境
3. 排錯與最佳實踐
- 配額/規格不可用:若創建失敗,先到云平臺控制臺查看“資源配額”“實例規格是否支持當前可用區”。
- 鏡像/名稱匹配失敗:可通過
terraform console
進入交互模式,打印數據源結果(如data.alicloud_images.ubuntu.images
),調整name_regex
。 - 安全組/NSG 范圍過寬:練習時可用
0.0.0.0/0
,生產環境務必收斂到辦公網 IP 或堡壘機 IP。 - 模塊化復用:將“VPC 創建”“云主機初始化”等邏輯封裝為模塊,主配置只做“編排”;模塊可通過 Terraform Registry 共享或內部版本化管理。
- 資源導入:若已有手動創建的資源,可通過
terraform import <資源地址> <資源ID>
納入管理,隨后補齊配置(確保terraform plan
無變更)。 - 生命周期控制:通過
lifecycle
塊精細控制資源行為,如:resource "alicloud_instance" "this" {# ...其他配置...lifecycle {create_before_destroy = true # 先創建新實例,再銷毀舊實例(避免 downtime)ignore_changes = [tags] # 忽略 tags 變更(不觸發實例重建)} }
4. 與 OpenTofu 的關系
若你需要完全開源且社區治理的 IaC 工具,可考慮 OpenTofu。它與 Terraform 1.x 配置高度兼容(命令從 terraform
改為 tofu
即可),大部分示例可直接復用。
十、Terraform 一次支持納管多少個云平臺?
Terraform 幾乎沒有上限,可以一次性納管任意數量的云平臺,只要存在對應的 Provider 插件。目前官方和社區已經提供了數百個 Provider,覆蓋了:
- 主流公有云:AWS、Azure、Google Cloud、Alibaba Cloud、Oracle Cloud 等。
- 私有云與虛擬化平臺:VMware、OpenStack、vSphere 等。
- SaaS 與開發者服務:Cloudflare、GitHub、GitLab、Datadog、Kubernetes 等。
在實際項目中,你可以在同一個 Terraform 配置中同時引入多個 Provider,從而統一管理不同平臺的資源。例如:
- 在阿里云創建 ECS
- 在 Azure 部署 VM
- 在 AWS 配置 S3 存儲桶
- 在 GCP 啟動 GKE 集群
Terraform 會根據依賴關系自動生成執行計劃,確保資源按需順序或并行創建。
注意事項:
- Provider 覆蓋度:不同 Provider 的功能成熟度和覆蓋度不一,有些可能僅支持部分資源。
- 性能開銷:當資源數量達到數千甚至上萬時,
terraform plan
與terraform apply
的耗時會明顯增加。 - 狀態文件管理:建議通過模塊化拆分和遠程狀態存儲,避免單一
.tfstate
文件過大、難以維護。
十一、總結與下一步
通過本文,你已掌握 Terraform 的發展歷史、核心原理、核心功能,并完成了阿里云 ECS與Azure Linux VM從“網絡到主機”的完整部署。
下一步建議:
- 模塊化封裝:將“VPC 配置”“云主機創建”等邏輯封裝為模塊,形成可復用的基礎設施模板。
- 端到端環境編排:嘗試將“數據庫、對象存儲、負載均衡、域名解析”等資源一起編排,構建完整的應用環境。
- 自動化發布流水線:結合 CI/CD 工具(如 GitHub Actions、GitLab CI,或 Terraform Cloud/Atlantis),實現“代碼提交 → 自動 Plan → 人工審核 → 自動 Apply”的合規發布流程。
若配置需要適配你的實際“地域、實例規格、鏡像”,可根據云平臺控制臺的信息調整變量,快速跑通屬于自己的基礎設施代碼!