计划与状态 · 云与可靠性
怎么修改正在运行的基础设施,又不把它弄坏?
课程目录为什么需要它
Terraform 计划里最吓人的一行是 must be replaced:服务器、数据库或存储桶会被销毁,然后新建一个,常常意味着丢数据或者停机。文件里改一个词就可能引发它。应用之前读懂计划,知道哪些修改会导致替换,就能避免大部分云上的事故。
直觉理解
Terraform 把自己创建过的东西记在一个状态(state)文件里。计划会比较三样东西:你的文件、状态,以及(真实环境里的)云本身。对每个地址:
| 文件里有 | 状态里有 | 计划 |
|---|---|---|
| 有 | 没有 | + 创建 |
| 没有 | 有 | - 销毁 |
| 有,属性不同 | 有 | ~ 原地更新,或者 -/+ 替换 |
某个差异是更新还是替换,取决于是哪个属性。有些属性可以在运行中的资源上直接改(实例的 instance_type、tags);有些不行(实例的 ami、存储桶的名字),Terraform 只能销毁再重建。
两个陷阱:
- 重命名资源块(
web→frontend)会改变它的地址。Terraform 会认为一个资源没了、又要一个新的:销毁加创建。(真正的 Terraform 有moved块,专门用于有计划的重命名。) - 删掉一个块,就会销毁真实的资源。
输入 yes 之前,读一遍每一行 - 和 -/+。
定义
状态
Terraform's record of the resources it manages and their last known attributes.Terraform 对它所管理的资源及其最近已知属性的记录。
替换
Destroy and recreate a resource, because an attribute that can't change in place was changed.因为改了一个不能原地修改的属性,所以销毁并重建资源。
漂移
When the real infrastructure no longer matches the files, usually after a manual change.真实的基础设施和文件对不上了,通常是因为有人手动改过。
示例
更新、替换和销毁
在互动课里运行状态里有一台 web 服务器和两个存储桶。运行它,读一读计划。
resource "aws_instance" "web" {
ami = "ami-0abc123"
instance_type = "t3.large"
tags = {
Name = "web"
}
}
resource "aws_s3_bucket" "assets" {
bucket = "shop-assets-v2"
}- L3instance_type 可以原地修改:~ 更新。服务器还在(会重启一下)。
- L10存储桶的名字不能改:-/+ 替换。旧的存储桶和里面的文件都会消失。
- L9aws_s3_bucket.tmp 在状态里,但不在文件里:- 销毁。
常见错误
给资源改名
新名字就是新地址:Terraform 会销毁旧资源,再创建一个新的。有计划的改名要用 moved 块。
改了强制重建的属性
改数据库的引擎或服务器的镜像会导致替换。应用之前检查计划里有没有 -/+。
弄丢状态文件
没有状态,Terraform 会以为什么都不存在,试图把一切重新创建一遍。把状态放在共享、带锁的远程后端里。
小测验
1. 你从文件里删掉一个资源块,然后运行 plan。会怎样?
查看答案
答案:A
文件描述的是期望的最终状态;文件里没有的东西就不应该存在。
2. 计划里哪一行最值得留意?
查看答案
答案:A
替换数据库意味着销毁它,数据也随之消失,除非你事先做好了准备。
动手练习
3 道练习,分三层:先预测程序的输出,再按新需求改程序,最后从零写一个。代码在浏览器里运行,提交马上判题。
- 预测输出读懂计划
状态和本课例子里的一样(一台
ami-0abc123的 web 服务器,存储桶 assets 和 tmp)。这个计划会做什么? - 改需求改规格,但不替换
本来的目标只是把 web 服务器调大(
t3.medium)。但有人顺手给块改了名,又换了镜像,于是现在计划要销毁这台服务器。修好文件,让计划只原地更新aws_instance.web。 - 从零写安全地扩容
已经有两台 web 服务器和一个存储桶(见初始代码)。写出文件,让计划再创建两台服务器(
web[2]和web[3],镜像和规格相同,标签分别是web-2、web-3),其他什么都不改。用一个变量web_count,值设为4。
本课术语
| 术语 | 中文 | 英文定义 |
|---|---|---|
| Terraform state | Terraform 状态 | Terraform's record of what it manages. |
| Replacement | 替换(重建) | Destroy and recreate, for attributes that can't change in place. |
| Drift | 配置漂移 | Real infrastructure no longer matching the files. |