大家好,我是程序员柏风,AI 最全的 Vibecoding 学习地图 http://coderoadmap.cn 作者。
IaC 与 Terraform 入门
这一课你将能做到
- 说清楚什么是基础设施即代码(IaC),以及它解决了手工运维的哪些痛点
- 在本机安装 Terraform 1.7+,并用 AWS provider 创建、销毁第一个真实云资源
- 理解「声明式」「执行计划」「状态文件」三个核心概念,能看懂
terraform plan的输出
为什么要学
想象一下本站(CodeRoadMap,一个 Spring Boot + MySQL + Redis 的应用)要部署上 AWS:你需要 VPC、子网、安全组、一台 EC2 或一个 ECS 服务、一个 RDS 实例、一个 ElastiCache、一个 ALB、几条 DNS 记录、一个放静态资源的 S3 桶……如果靠人在控制台点,第一次能点出来,第二次换个区域重建就点不出一模一样的了;新同事接手时只能靠口口相传;某个人手动改了安全组,代码里完全没有记录,这叫「配置漂移」。
基础设施即代码(Infrastructure as Code)就是把这些资源用文本文件描述出来,放进 Git,像应用代码一样做评审、走 CI、可回滚。Terraform 是这个领域事实标准的工具:一份 HCL 配置,可以在 AWS、阿里云、Cloudflare、GitHub 等几百个平台上创建资源。对初学者来说,它也是把「云网络、计算、存储」这些零散知识串成一张图的最好抓手。
先建立图像
Terraform 的工作模型只有一句话:你写「想要什么」,它负责「变成那样」。
.tf 配置文件 执行计划 云上真实资源
┌──────────────┐ plan ┌──────────────┐ apply ┌──────────────┐
│ 我要一个 S3 │ ────────▶ │ + 新建 1 个 │ ───────▶ │ AWS 上真的 │
│ 桶,名叫 X │ │ 桶 │ │ 出现一个桶 │
└──────────────┘ └──────────────┘ └──────────────┘
▲ │
│ terraform.tfstate(记账本) │
└────────────────── 记录映射关系 ◀──────────────────┘
- 配置是「期望状态」,云上是「实际状态」,Terraform 不断对比两者并补齐差异;
plan只预演不改东西,像 SQL 事务先给你看影响行;state是它的记账本,记录「配置里的这个桶 = AWS 上那个 arn 的桶」。
跟着做
步骤 1:安装 Terraform 1.7+ 并验证
macOS:
brew tap hashicorp/tap
brew install hashicorp/tap/terraform
terraform version # 应显示 Terraform v1.7.x 或更高
Windows(PowerShell,管理员):
winget install Hashicorp.Terraform
terraform version
也可以从 https://developer.hashicorp.com/terraform/install 下载单文件放进 PATH。另装一个 AWS CLI 并配置凭证:
aws configure
# AWS Access Key ID / Secret Access Key / 默认区域填 ap-northeast-1(东京)
aws sts get-caller-identity # 能打印账号 ID 说明凭证可用
生产环境不要用长期 Access Key,本机练习可以;后面 CI 课会改用 OIDC 临时凭证。
步骤 2:写第一个配置
新建目录 tf-demo,创建 main.tf。这段配置为本站创建一个存放课程封面图的 S3 桶:
terraform {
required_version = ">= 1.7.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
}
provider "aws" {
region = "ap-northeast-1"
}
resource "aws_s3_bucket" "site_assets" {
bucket = "coderoadmap-assets-2026-demo" # S3 桶名全球唯一,请换成你自己的
tags = {
Project = "coderoadmap"
Env = "dev"
}
}
步骤 3:init、plan、apply 三步走
terraform init
init 会读取 required_providers,下载 AWS provider 插件,生成 .terraform 目录和 .terraform.lock.hcl 锁文件。第一次必须先 init。
terraform plan
输出里会有:
Terraform will perform the following actions:
# aws_s3_bucket.site_assets will be created
+ resource "aws_s3_bucket" "site_assets" {
+ bucket = "coderoadmap-assets-2026-demo"
+ id = (known after apply)
...
}
Plan: 1 to add, 0 to change, 0 to destroy.
+ 表示新建、- 表示删除、~ 表示修改、-/+ 表示替换(先删后建)。确认无误后执行:
terraform apply
# 最后会再次显示计划,输入 yes 回车
看到 Apply complete! Resources: 1 added 后,去 AWS 控制台 S3 页面,桶真的出现了。此时目录里多了一个 terraform.tfstate,打开能看到桶名、arn 等真实属性——这就是记账本。
步骤 4:体会幂等与修改
不做任何改动,再执行一次:
terraform apply
# 输出:No changes. Your infrastructure matches the configuration.
这就是幂等:同一个配置跑多少次结果都一样,不会重复建桶。现在把桶加个标签,把 Env 改成 "test",再跑 terraform plan,你会看到 ~ 修改动作而不是重建——Terraform 知道这是同一个资源。
步骤 5:销毁
练习资源要记得删掉,避免持续计费:
terraform destroy
# 输入 yes
destroy 不是去控制台手删,而是让 Terraform 根据 state 反推要删什么、按依赖逆序删。手删云上资源而不更新 state,是初学者最常见的事故,state 课会专门讲。
讲清楚要点
- 声明式,不是过程式脚本:你描述「要有一个桶」,不写「先调 CreateBucket、失败重试、轮询直到 Ready」这些步骤。Bash/CLI 脚本是命令式的,换个起始状态就可能出错;Terraform 只关心终态。
- 先 plan 再 apply 是硬规矩:plan 把「将要发生的变更」在真正动手前摊开看,团队里 apply 到生产前通常要求另一个人评审 plan 结果。
- state 是 Terraform 的真相来源之一:它用 state 把配置块和真实资源 ID 绑定。没有 state,Terraform 不知道你配置里那个桶是不是已经存在。
- 依赖关系自动推导:如果桶里还要放对象(
aws_s3_object),你引用aws_s3_bucket.site_assets.bucket,Terraform 自动先建桶再传对象,不需要你排顺序。 - 跨云靠 provider 生态:Terraform 核心不懂 AWS,懂 AWS 的是 provider 插件;换云等于换 provider,HCL 的写法、命令、工作流完全一致。
你可能会懵的地方
-
Terraform 和 CloudFormation、Pulumi、Ansible 有什么区别? CloudFormation 只覆盖 AWS 且用 YAML/JSON;Terraform 跨云、HCL 体验更好、生态最大。Pulumi 用通用编程语言(TS/Go/Python),灵活但门槛高。Ansible 偏「配置已有机器」(装软件、改文件),Terraform 偏「 provision 资源本身」,两者常配合使用。
-
IaC 是不是只能管云资源? 不是。Kubernetes、DNS(Cloudflare)、GitHub 仓库权限、Datadog 监控都能用 Terraform 管。本站的「云资源 + 监控告警 + 代码仓库权限」可以收敛到同一份代码里。
-
.tf文件就是 HCL 吗?HCL 和 JSON 什么关系? HCL(HashiCorp Configuration Language)是 Terraform 配置的语言,.tf文件默认用 HCL 语法;也可以写等价的.tf.json,但 HCL 可读性好得多,实际工程里几乎全用 HCL。 -
terraform apply直接改线上,会不会很危险? 所以才有 plan 评审、state 锁、分环境目录/workspace、CI 流水线等一整套防护。工具不危险,无评审地直连生产 apply 才危险。 -
免费吗?license 有什么坑? Terraform CLI 1.6 以后是 BSL(Business Source License),内部使用、学习、给客户做部署都免费,只是不能拿它做一个和 HashiCorp 竞争的托管服务。OpenTofu 是 Linux 基金会的开源分叉,语法基本兼容。
错法对照
| 错法 | 问题 | 正解 |
|---|---|---|
| 在控制台手动改 Terraform 管的资源 | 产生配置漂移,下次 apply 被悄悄改回 | 所有变更走代码;手改了要及时同步配置 |
写完 .tf 直接 apply | 跳过计划评审,可能误删生产 | 先 plan(或 plan -out)再 apply |
把 terraform.tfstate 提交进 Git | state 里可能有明文密钥且多人写会冲突 | state 远程化(第 7 课),.gitignore 忽略本地 state |
| 一个目录管所有环境 | dev 改错可能波及 prod | 按环境分目录或用 workspace + 独立 state |
用 aws configure 的个人 AK 跑 CI | 密钥泄露即长期失守 | CI 用 OIDC AssumeRole 拿临时凭证(第 11 课) |
卡点急救
init卡住或报 checksum 错误:公司网络拦截了 releases.hashicorp.com,配置镜像:设置环境变量TF_REGISTRY_DISCOVERY_RETRY无效时,在 CLI 配置~/.terraformrc里加provider_installation { network_mirror { url = "https://你的镜像/" } },或先配好代理。- plan 报
No valid credential sources:先跑aws sts get-caller-identity确认凭证;注意终端的AWS_PROFILE、AWS_REGION环境变量是否指向正确配置。 - 桶名报
BucketAlreadyExists:S3 桶名全球唯一,换一个带随机后缀或个人标识的名字;这也是云资源命名要加项目前缀的原因。
面试常问
-
介绍一下什么是 IaC,Terraform 的工作流程? 答出声明式描述期望状态、
init → plan → apply工作流、state 记录映射、幂等收敛,并补一句「变更走 Git 评审,避免手工漂移」就是优秀答案。 -
为什么需要 plan 这一步?直接 apply 不行吗? plan 提供变更预览和风险把关,尤其能暴露「destroy/replace」这类破坏性动作;plan 文件(
-out)还能保证「评审的就是执行的」,防止评审后配置被改动。 -
Terraform 管理的资源有人在控制台手改了怎么办? 下次 plan 会检测到漂移(部分资源依赖 Read),按代码为准纠正;正确做法是禁止手改(IAM 权限收口 + 标签说明),漂移检测纳入例行 plan。
自测三问
- 用自己的话说:命令式脚本和声明式 IaC,在「资源已经被人删掉一半」时行为有什么不同?
terraform.tfstate里大概记录了什么?为什么说它不能随便删?- 把本站部署上 AWS,你能想到哪些资源适合立刻纳入 Terraform 管理?
小结一句话
Terraform 用一份声明式 HCL 描述期望的基础设施,经 plan 预览、apply 收敛,并靠 state 记账,让云资源可复现、可评审、可回滚。
延伸
- Terraform 官方安装文档
- AWS Provider 文档(含所有资源索引)
- Why Terraform(官方白皮书)
- 下一课:HCL 语法精讲——块、表达式、
count/for_each与lifecycle,把配置写得简洁又安全。