人人都能学编程
English 开始学习
专项 · 云与 SRE第 2 课 / 共 5 课免费阅读

计划与状态 · 云与可靠性

怎么修改正在运行的基础设施,又不把它弄坏?

课程目录

为什么需要它

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"
}
逐步执行
  1. L3instance_type 可以原地修改:~ 更新。服务器还在(会重启一下)。
  2. L10存储桶的名字不能改:-/+ 替换。旧的存储桶和里面的文件都会消失。
  3. L9aws_s3_bucket.tmp 在状态里,但不在文件里:- 销毁。

常见错误

给资源改名

新名字就是新地址:Terraform 会销毁旧资源,再创建一个新的。有计划的改名要用 moved 块。

改了强制重建的属性

改数据库的引擎或服务器的镜像会导致替换。应用之前检查计划里有没有 -/+。

弄丢状态文件

没有状态,Terraform 会以为什么都不存在,试图把一切重新创建一遍。把状态放在共享、带锁的远程后端里。

小测验

1. 你从文件里删掉一个资源块,然后运行 plan。会怎样?

  1. A计划会销毁真实的资源
  2. BTerraform 忘掉它,但让它继续运行
  3. C什么都不发生
查看答案

答案:A

文件描述的是期望的最终状态;文件里没有的东西就不应该存在。

2. 计划里哪一行最值得留意?

  1. A-/+ aws_db_instance.main must be replaced
  2. B+ aws_s3_bucket.logs will be created
  3. C~ aws_instance.web will be updated in-place
查看答案

答案:A

替换数据库意味着销毁它,数据也随之消失,除非你事先做好了准备。

动手练习

3 道练习,分三层:先预测程序的输出,再按新需求改程序,最后从零写一个。代码在浏览器里运行,提交马上判题。

  1. 预测输出读懂计划

    状态和本课例子里的一样(一台 ami-0abc123 的 web 服务器,存储桶 assets 和 tmp)。这个计划会做什么?

  2. 改需求改规格,但不替换

    本来的目标只是把 web 服务器调大(t3.medium)。但有人顺手给块改了名,又换了镜像,于是现在计划要销毁这台服务器。修好文件,让计划只原地更新 aws_instance.web。

  3. 从零写安全地扩容

    已经有两台 web 服务器和一个存储桶(见初始代码)。写出文件,让计划再创建两台服务器(web[2] 和 web[3],镜像和规格相同,标签分别是 web-2、web-3),其他什么都不改。用一个变量 web_count,值设为 4。

在互动课里练这一课

打开互动课,这些例子都能直接改、直接运行,练习题提交马上判题。免费开始,不用注册。

互动课按顺序解锁:前面的课还没学,会先带你到课程地图。

本课术语

术语中文英文定义
Terraform stateTerraform 状态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.