TT Lab
开始
学习 学习路径 课程

Terraform 实战

计划变慢后,大家开始跳过计划

在 TT Lab 中继续学习

目标

创建包含 300 个实例的状态,亲自测量计划时间,用保存的计划确认刷新、并行度、缩小目标范围、拆分状态这四个旋钮分别如何改变时间和计划内容,最后把测量记录整理成表格和结论。

为什么重要

计划变慢不是不方便,而是安全问题。如果必须等 3 分钟,人们就会在小变更上跳过计划,而那一刻,“应用前先看会改变什么”这条纪律就消失了。然而,处理缓慢计划的旋钮全都要付出代价。关闭刷新,就看不到外部发生的变化;缩小目标范围,这个计划就不能代表整个配置;拆分状态,各层之间必须用输出连接。所以顺序很重要——先测量,确认是什么在消耗时间,然后选择可以损失的东西,再拧旋钮。本实验的绝对时间与真实云环境不同(这个 Pod 的 provider 没有远程调用)。要学的不是数字,而是测量方法,以及每个旋钮如何改变计划的内容。

步骤

  1. 在 /root/tfa-perf/main.tf 中,用 count 声明 var.size 个 random_pet.n,以及把各自的名称写入 /root/tfa-perf/out/<인덱스>.txt(占位符为索引)的 local_file.n。在 /root/tfa-perf/terraform.tfvars 中写入 size = 150,然后执行 init 和 apply。状态中会有 300 个实例。
  2. 创建 /root/tfa-perf/measure.sh。它把第一个参数作为标签,把其余参数原样传给 tofu plan,以毫秒为单位测量耗时,把计划保存到 /root/tfa-perf/plans/<이름표>.tfplan,把输出保存到 /root/tfa-perf/plans/<이름표>.log(占位符为标签),并在 /root/tfa-perf/times.tsv 中用制表符写入 <이름표>、<밀리초>、<실행한 명령> 三列(占位符依次为标签、毫秒数、所执行的命令)。对同一个标签重新测量时,行数不能增加,而是要被替换。然后不带任何选项,以标签 full 测量一次。
  3. 在工具之外删除 /root/tfa-perf/out/7.txt 制造漂移,然后以标签 no-refresh 加上 -refresh=false 测量,接着以标签 refresh 不带选项测量。两个计划文件中所包含的变更数必须不同。最后执行 apply,把删除的文件恢复回来。
  4. 以标签 par1 加上 -parallelism=1 测量。保存的计划中所包含的变更项数必须与 full 相同。
  5. 以标签 target 加上 -target=random_pet.n[0] 测量。保存的计划中应只剩很少的项目,且 /root/tfa-perf/plans/target.log 中必须包含工具给出的警告。
  6. 在 /root/tfa-perf/split/a 和 /root/tfa-perf/split/b 中放置相同的配置,分别以 size = 75 执行 init 和 apply(合起来和最初一样是 300 个)。然后在各个目录中用标签 split-a 和 split-b 各运行一次 /root/tfa-perf/measure.sh。
  7. 以标签 stale 保存一个计划,然后在 /root/tfa-perf 中用 tofu apply -replace=random_pet.n[0] -auto-approve 改变状态。接着尝试应用已保存的 plans/stale.tfplan,并把输出保存到 /root/tfa-perf/stale.txt。最后计划必须是干净的。
  8. 创建 /root/tfa-perf/report.md。在以 | label | ms | command | 表头和分隔线开头的表格中,按标签顺序放入 times.tsv 的所有行,并在表格之后用一行写入 fastest: <가장 빠른 이름표>(占位符为最快的标签)。数字不要编造,要原样从 times.tsv 中抄录。

参考

创建一个值得测量的规模

在 /root/tfa-perf/main.tf 中,用 count 声明 var.size 个 random_pet.n,以及把各自的名称写入 /root/tfa-perf/out/<인덱스>.txt(占位符为索引)的 local_file.n。在 /root/tfa-perf/terraform.tfvars 中写入 size = 150,然后执行 init 和 apply。状态中会有 300 个实例。

这里使用 count,是为了通过索引相互引用,把两种资源配对地一起增加。如果是真实的基础设施,这 300 个实例每次都要通过远程 API 来确认——这个确认占了计划时间的大部分。

先做好测量工具

创建 /root/tfa-perf/measure.sh。它把第一个参数作为标签,把其余参数原样传给 tofu plan,以毫秒为单位测量耗时,把计划保存到 /root/tfa-perf/plans/<이름표>.tfplan,把输出保存到 /root/tfa-perf/plans/<이름표>.log(占位符为标签),并在 /root/tfa-perf/times.tsv 中用制表符写入 <이름표>、<밀리초>、<실행한 명령> 三列(占位符依次为标签、毫秒数、所执行的命令)。对同一个标签重新测量时,行数不能增加,而是要被替换。然后不带任何选项,以标签 full 测量一次。

毫秒数用 date 的 %s%3N 格式得到。如果先删除同一标签的旧行再写入新行,多次测量后记录也是干净的——如果测量记录只靠 append 累积,以后就无法知道哪一行是最新的。之所以用 -out 保存计划,是因为以后可以再看当时里面有什么。

关闭刷新,什么变快了,又损失了什么

在工具之外删除 /root/tfa-perf/out/7.txt 制造漂移,然后以标签 no-refresh 加上 -refresh=false 测量,接着以标签 refresh 不带选项测量。两个计划文件中所包含的变更数必须不同。最后执行 apply,把删除的文件恢复回来。

刷新就是逐个确认状态中记录的内容在实际中是否仍然保持原样。关闭它就整个跳过这个确认,所以变快了,但看不到外部发生的变化。请用 tofu show -json 打开保存的计划,统计变更数。

调低并行度,只有时间改变,结果不变

以标签 par1 加上 -parallelism=1 测量。保存的计划中所包含的变更项数必须与 full 相同。

并行度是决定工具同时进行多少项操作(主要是远程调用)的值。它与计划的内容无关,所以结果相同,只有时间不同。反过来,调高是否总是更快呢?并非如此——如果对方的 API 设置了速率限制,重试会增加,反而变慢。

缩小目标范围,计划就只剩那么多

以标签 target 加上 -target=random_pet.n[0] 测量。保存的计划中应只剩很少的项目,且 /root/tfa-perf/plans/target.log 中必须包含工具给出的警告。

缩小目标范围后,工具只会把这个资源以及它所依赖的内容放进计划。因此这个计划不能代表整个配置,工具也会用警告告诉你这一点。官方文档写明,只应在从失误中恢复这类例外情况下使用这个选项。

把状态拆成两份,重新测量同样的规模

在 /root/tfa-perf/split/a 和 /root/tfa-perf/split/b 中放置相同的配置,分别以 size = 75 执行 init 和 apply(合起来和最初一样是 300 个)。然后在各个目录中用标签 split-a 和 split-b 各运行一次 /root/tfa-perf/measure.sh。

measure.sh 以自己所在的位置为基准进行记录,所以无论在哪个目录中调用,记录都会汇集到同一处。即使拆分后两个时间相加比最初的一个还大,关键在于每个人只需要等待自己的那一份状态——拆分缩短的不是总时间,而是一个人的等待时间。

状态一变,保存的计划就不能用了

以标签 stale 保存一个计划,然后在 /root/tfa-perf 中用 tofu apply -replace=random_pet.n[0] -auto-approve 改变状态。接着尝试应用已保存的 plans/stale.tfplan,并把输出保存到 /root/tfa-perf/stale.txt。最后计划必须是干净的。

保存的计划是“在当时的那个状态下做这个变更”的承诺。状态在那之后发生了变化,承诺的前提就被破坏了,所以工具会拒绝应用。在 CI 中把 plan 和 apply 分开运行时,这条规则就是安全装置。

把测量记录整理成表格并写下结论

创建 /root/tfa-perf/report.md。在以 | label | ms | command | 表头和分隔线开头的表格中,按标签顺序放入 times.tsv 的所有行,并在表格之后用一行写入 fastest: <가장 빠른 이름표>(占位符为最快的标签)。数字不要编造,要原样从 times.tsv 中抄录。

结论行必须出自你测得的数字——评分器也会读取 times.tsv 做同样的计算。哪个旋钮缩短得最多,可能因机器而异,这正是“先测量再选择”这句话的含义。