怎么读 plan — 符号、退出码、漂移
一句话总结
apply是plan这只是执行我已经做出的决定。阻止事故的唯一时间是阅读计划的几分钟,而这些几分钟最终不是由人来完成,而是由脚本来完成。
为什么需要这个?
基础设施代码中最昂贵的错误是“错误地将可再生性误认为是原地修改”。在屏幕上出现的-/+的~误以为这样,生产数据库就会被删除后重新创建。计划输出很长,部署通常在晚些时候进行,人的眼睛如果看同一屏幕三次就会开始不看懂。
所以成熟的团队会做两件事。第一,把计划保存为文件,然后按照评论过的计划进行应用。如果不保存,评论过的计划和实际应用的计划可能会不同,因为在这期间有人可能会更改其他内容。第二,把计划以机器可以读取的形式提取出来,并用规则进行判断。像“如果有任何删除,必须由人批准”这样的规则,不是由人来遵守,而是由管道来遵守。
怎么行动
人们阅读的计划上附有符号。
| 符号 | 意思 | 危险度 |
|---|---|---|
+ |
生成 | 低 |
~ |
原地修正 | 普通 |
- |
删除 | 高 |
-/+ |
删除后再生 | 非常高 |
+/- |
生成后删除(create_before_destroy) |
高 |
<= |
读取数据源 | 无 |
产生再生性的原因通常是因为触及了不可改变的因素,对于这一点# forces replacement附有标记。最下面是缩写总结的Plan: X to add, Y to change, Z to destroy在再生中,再生量在add和destroy两边各被扣除1个,也需要记住这一点。
自动化所需的不是符号,而是两个。一个是-detailed-exitcode全部。
| 结束代码 | 含义 |
|---|---|
| 0 | 无变更 |
| 1 | 错误 |
| 2 | 有变更 |
多亏了这三个值,我们就可以用一行代码实现“如果有变化就通知”这样的定期漂移检测。另一个是JSON表示法。将计划文件转换为JSON的话resource_changes排列出来,各项目的change.actions去["create"],["update"],["delete"],如果是可再生的话["delete","create"]正在进去。还有resource_drift中包含了在查询阶段发现的代码以外的变更。这意味着可以区分反映在计划中的变更和已经发生的变更。
-target这是只选择部分曲线进行处理的选项。使用时,工具会发出警告。因为只应用部分,剩下的可能会与代码不一致,状态不一致。这是恢复情况的工具,不是平时的工作流程。
在现场相遇的样子
**第一,提供商升级后的大量漂移。**上传主要版本后,由于新添加的属性的默认值,数百个资源都会发生变化。大部分不是改变实际基础设施,而是填充状态中的属性。不区分这两个,惊慌失措地撤销或相反,在没有确认的情况下应用都会导致事故。用JSON提取,按操作数算的话判断会更快。
第二,检测本身的成本。plan对正在管理的所有资源调用提供商API。规模越大,就会受到API限制,在检测过程中会锁定状态,与部署发生冲突。检测周期不是免费的。
**第三,留在计划日志中的秘密。**计划输出时,资源属性会保持原样。将通知渠道或CI日志全部粘贴的习惯会成为泄露路径。只发送摘要,将全部放在受控的地方比较安全。
计划中必须用眼睛确认的三件事
terraform plan的输出很长。因为不能全部读完,所以先确定要找什么
看。
第一,总结行中的destroy个数。Plan: 3 to add, 1 to change, 2 to destroy从
不是0,而是destroy,总是有理由停下手来。如果是故意的,什么会被抹掉呢?
通过名称确认,如果不是故意的,通常是资源地址变更了(模块
搬过来了或者count的for_each换成了)。当时不是删除了而是做了。
moved只把地址用区块转移。
moved {
from = aws_instance.web[0]
to = aws_instance.web["a"]
}
**第二,# forces replacement附加的属性。**只是换了一个名字,但数据库
被替换的计划在这里显现出来。在有状态的资源中prevent_destroy挂起来
一想,在计划阶段就完全被阻挡了。
lifecycle { prevent_destroy = true }
**第三,(known after apply)挂在哪里了。如果这个价格高的话,计划
意思是很难提前知道具体要做什么。其他资源还没有的属性
因为是用来参考的,虽然本身是正常的,但是重要的决定(安全组规则、政策文件)
如果取决于这个价格,**应该知道在应用前不能进行审查。
**将计划作为文件接收并应用。**计划和应用之间有人改变了什么, 适用与本条不同的事项。
terraform plan -out=tfplan
terraform show -json tfplan | jq '[.resource_changes[]
| select(.change.actions | index("delete"))] | map(.address)'
terraform apply tfplan
在自动化中使用终止代码。-detailed-exitcode是0(没有变化),
退回1(错误)、2(有变更)。在CI中“如果有变更,需要获得人的批准”
流向在这里开始。
下次实习要做的事情
/root/tf/plan将计划从中保存为文件,转换为JSON,并按操作数统计并记录。-detailed-exitcode直接确认的两个结束代码,让原地修改和可重现性一起纳入一个计划。用手修改正在管理的文件。resource_drift看到,-target缩小范围,阅读工具的警告。最后,制作包含删除计划的自己判断的评论报告。