Terraform 入门:基础概念与核心组件

一、Terraform 到底管什么

Terraform 是 HashiCorp 出品的 IaC(基础设施即代码)工具。核心就是一句话:把云资源写成代码,用 git 管起来,一条命令部署

它和 Ansible 经常放在一起提,但职责完全不同:

Terraform Ansible
管什么 云资源本身(VPC、ECS、RDS) 机器内部状态(装软件、改配置)
怎么管 声明式,写清楚「要什么」 命令式,写清楚「怎么做」
状态 有 state 文件追踪 无状态
幂等 天然幂等 需要自己保证模块幂等

简单记:Terraform 管房子造不造得起来,Ansible 管房子里面怎么装修。实际项目里两者经常搭配用——Terraform 先把机器开出来,Ansible 上去装 Docker、配内核参数。

另外,Terraform 不只管云资源。它还可以管理:

K8s 集群对象(Deployment、Service、ConfigMap)
DNS 记录
Datadog / Prometheus 监控
GitHub 仓库与权限
本地文件(local_file)
随机密码(random_password)
TLS 证书(tls_private_key)

只要有对应的 provider,什么都能管。这是 Terraform 和 CloudFormation、ROS 这类云厂商专属工具最大的区别——一套语法,管所有平台

二、核心概念

Provider

Provider 是 Terraform 和外部平台的"翻译官"。阿里云用 aliyun/alicloud,AWS 用 hashicorp/aws,Kubernetes 用 hashicorp/kubernetes

terraform {
  required_providers {
    alicloud = {
      source  = "aliyun/alicloud"
      version = "1.280.0"
    }
  }
}

provider "alicloud" {
  region     = "cn-shanghai"
  access_key = var.access_key
  secret_key = var.secret_key
}

terraform {} 块声明 provider 来源和版本;provider {} 块配置认证。同一个 provider 可以声明多个 alias,对应不同的账号或 region——做多账号管理很实用。

Resource

Resource 是 Terraform 管理的最小单元,一个云资源对应一个 resource 块:

resource "alicloud_vpc" "my_vpc" {
  vpc_name   = "prod-vpc"
  cidr_block = "10.0.0.0/16"
}

resource "alicloud_vswitch" "my_vswitch" {
  vpc_id     = alicloud_vpc.my_vpc.id
  cidr_block = "10.0.1.0/24"
  zone_id    = "cn-shanghai-b"
}

注意:上面的 alicloud_vswitch.my_vpc.id 是 Terraform 的隐式依赖引用,Terraform 会自动推导创建顺序,不需要你手动声明依赖关系。

Data Source

Data Source 是只读查询,从云平台获取已有资源的信息,不创建任何东西:

data "alicloud_zones" "default" {
  available_resource_creation = "VSwitch"
}

data "alicloud_images" "centos" {
  name_regex = "^centos_7"
}

典型场景:查可用区列表、查已经存在的 VPC ID、获取最新的镜像 ID。

Variable 与 Output

Variable 让配置参数化,避免硬编码:

variable "region" {
  type    = string
  default = "cn-shanghai"
}

variable "password" {
  type      = string
  sensitive = true
}

加了 sensitive = true 的变量,tf plan 和日志里都不会打印,防止泄密。

Output 把模块的关键信息暴露出来:

output "vpc_id" {
  value = alicloud_vpc.my_vpc.id
}

模块之间通过 output 传递信息,调用方用 module.xxx.vpc_id 引用。

Module

Module 是 Terraform 的复用机制。一个大项目写成几十个 module 比堆在一个文件里强太多:

├── main.tf
├── modules/
│   ├── network/   # VPC、子网、NAT、路由
│   ├── k8s/       # 集群、节点池
│   ├── rds/       # 数据库
│   └── ram/       # 用户与权限

调用方式:

module "network" {
  source = "./modules/network"

  vpc_name   = "prod-vpc"
  cidr_block = "10.0.0.0/16"
}

source 可以是本地路径、git 仓库、Terraform Registry。不同环境(dev / prod)各自一个目录调用同一套 module,保证一致性的同时能做到差异化管理。

State 与 Backend

State 文件是 Terraform 的"账本",记录它管过哪些资源以及资源当前的状态:

  • tf plan 时,Terraform 对比 .tf 文件(期望状态)和 state 文件(实际状态),算出差异
  • tf apply 后,state 更新为最新状态

默认 state 存本地,但多人协作用远程后端。阿里云上用的是 OSS:

terraform {
  backend "oss" {
    bucket  = "my-terraform-states"
    key     = "terraform.tfstate"
    region  = "cn-shanghai"
  }
}

远程后端还能自动加锁——你 apply 的时候别人不能同时 apply,防止状态冲突。

三、一个文件里有哪些关键字

拿一个典型的 main.tf 作为参考:

# 1. 版本与 provider 声明
terraform {
  required_version = ">= 1.5"
  required_providers {
    alicloud = { source = "aliyun/alicloud", version = "~> 1.280" }
  }
  backend "oss" { ... }
}

# 2. Provider 配置
provider "alicloud" {
  alias      = "prod"
  region     = var.region
  access_key = var.ak
  secret_key = var.sk
}

# 3. 本地变量
locals {
  common_tags = {
    managed_by = "terraform"
    env        = var.env
  }
}

# 4. Data Source(只读查询)
data "alicloud_zones" "default" {
  available_resource_creation = "VSwitch"
}

# 5. Resource
resource "alicloud_vpc" "main" { ... }

# 6. Module
module "k8s" {
  source   = "./modules/k8s"
  vpc_id   = alicloud_vpc.main.id
  vswitch_ids = alicloud_vswitch.main[*].id
}

# 7. Output
output "vpc_id" {
  value = alicloud_vpc.main.id
}

Terraform 的执行顺序不按文件里的书写顺序,而是靠 依赖图 自动推导——你引用了 alicloud_vpc.main.id,Terraform 就知道 VPC 必须先于 K8s 创建。

四、基本工作流

日常开发就 3 个命令来回转:

tf init     # 初始化:下载 provider、配置 backend
tf plan     # 干跑:看将要创建/修改/删除什么
tf apply    # 执行:真正动手

我习惯把 terraform 别名成 tf,每天敲得最多就是这三个。

init 改完 provider 或 backend 的时候跑一次就行。plan 是每次 apply 前必跑的,生产环境尤其——输出里会告诉你 Plan: X to add, Y to change, Z to destroy,看到 destroy 先停下来审查一遍。

还有一个常用组合:

tf fmt -recursive   # 格式化所有 .tf 文件
tf validate         # 语法检查

提交 git 之前跑一下,团队协作风格统一。


作者:舞鹤Roc
链接:https://www.jianshu.com/p/bab97b6b2c15
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

友情链接更多精彩内容