计划变慢后,大家开始跳过计划
目标
创建包含 300 个实例的状态,亲自测量计划时间,用保存的计划确认刷新、并行度、缩小目标范围、拆分状态这四个旋钮分别如何改变时间和计划内容,最后把测量记录整理成表格和结论。
为什么重要
计划变慢不是不方便,而是安全问题。如果必须等 3 分钟,人们就会在小变更上跳过计划,而那一刻,“应用前先看会改变什么”这条纪律就消失了。然而,处理缓慢计划的旋钮全都要付出代价。关闭刷新,就看不到外部发生的变化;缩小目标范围,这个计划就不能代表整个配置;拆分状态,各层之间必须用输出连接。所以顺序很重要——先测量,确认是什么在消耗时间,然后选择可以损失的东西,再拧旋钮。本实验的绝对时间与真实云环境不同(这个 Pod 的 provider 没有远程调用)。要学的不是数字,而是测量方法,以及每个旋钮如何改变计划的内容。
步骤
- 在
/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 个实例。 - 创建
/root/tfa-perf/measure.sh。它把第一个参数作为标签,把其余参数原样传给tofu plan,以毫秒为单位测量耗时,把计划保存到/root/tfa-perf/plans/<이름표>.tfplan,把输出保存到/root/tfa-perf/plans/<이름표>.log(占位符为标签),并在/root/tfa-perf/times.tsv中用制表符写入<이름표>、<밀리초>、<실행한 명령>三列(占位符依次为标签、毫秒数、所执行的命令)。对同一个标签重新测量时,行数不能增加,而是要被替换。然后不带任何选项,以标签full测量一次。 - 在工具之外删除
/root/tfa-perf/out/7.txt制造漂移,然后以标签no-refresh加上-refresh=false测量,接着以标签refresh不带选项测量。两个计划文件中所包含的变更数必须不同。最后执行 apply,把删除的文件恢复回来。 - 以标签
par1加上-parallelism=1测量。保存的计划中所包含的变更项数必须与full相同。 - 以标签
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。 - 以标签
stale保存一个计划,然后在/root/tfa-perf中用tofu apply -replace=random_pet.n[0] -auto-approve改变状态。接着尝试应用已保存的plans/stale.tfplan,并把输出保存到/root/tfa-perf/stale.txt。最后计划必须是干净的。 - 创建
/root/tfa-perf/report.md。在以| label | ms | command |表头和分隔线开头的表格中,按标签顺序放入times.tsv的所有行,并在表格之后用一行写入fastest: <가장 빠른 이름표>(占位符为最快的标签)。数字不要编造,要原样从 times.tsv 中抄录。
参考
- Pod 中有 OpenTofu 1.9.0 以及 local、random provider 的 mirror,无需联网即可运行。
- 保存的计划(-out)可以用 tofu show -json 打开并统计变更项。与时间不同,这个数字在不同机器上也是相同的。
- 常见错误:测量记录只用 append 累积,导致同一个标签出现多行。以后就无法知道哪一行是最新的。
- 常见错误:只测一次就下结论。第一次运行时缓存是空的,所以很慢——请用同一个标签测两次,采用第二次的结果。
- Command: plan · Command: apply · Resource Addressing · terraform_remote_state
创建一个值得测量的规模
在 /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 做同样的计算。哪个旋钮缩短得最多,可能因机器而异,这正是“先测量再选择”这句话的含义。