状态手术 — 不碰实物,只修记忆
一句话总结
state mv哇state rm不改变基础设施。**只改变工具的记忆。**如果误解这句话就会出事故,理解的话就会使重构变得安全。
为什么需要这个?
基础设施代码必须经历重构。因为不喜欢资源的名字,所以想把几个资源打包成模块,因为状态文件太大,所以想分开。但是,在代码中更改名称的瞬间,工具判断旧名称的资源消失了,新名称的资源出现了。在计划中,破坏和创造并列出现。如果是实际运营DB的话,批准那个计划的瞬间就是结束。
也有相反方向的问题。在应对障碍时,有人在控制台上创建了安全组。虽然实体存在,但代码和状态中没有。下面的apply不知道该资源,所以没有触动它,但增加了一个没有人管理的资源。把这个资源带到代码管理下import全部。
这两种方向——移动地址和把外面的东西拿过来——就是状态手术的全部。
怎么行动
状态文件是记录“我制作的资源的地址和最后知道的属性”的账簿。手术工具有四个。
| 命令 | 做的事情 | 对实物的影响 |
|---|---|---|
state list |
输出地址列表 | 无 |
state show <주소> |
那个地址的所有属性输出 | 无 |
state mv A B |
将账簿中的A项目改名为B名 | 无 |
state rm A |
在账簿中删除A项目 | 无(实物保持原样) |
import |
将实物登记在账簿上 | 无 |
最常被误解的是state rm是的。这不是删除命令,而是管理放弃宣言。实物保持原样,只忘记工具。所以state rm在后面的代码中,如果不删除该块,下一步计划就会说“没有那个资源,重新创建吧”。在实际的云中,试图再创建名称重叠的资源时会失败,最坏的情况是产生重复资源。如果想删除实物的话destroy应该用。
state mv用代码做像这样的事情moved是区块。差异在记录中。state mv在某人的终端上执行一次后就会消失,moved留在代码中,团队成员plan即使转了10万韩元,也会自动发生同样的移交。所以单独使用的状态下state mv,在许多人使用的代码中moved 是基础。
import也有两种形式。命令行tofu import <주소> <ID>立即执行并改变状态。import {}区块在代码中进行声明,先用计划确认后通过apply反映。后者可以进行评论,并留下履历,所以在协作中区块方式更好。两者都必须**提前创建要带入的位置(资源区块)**这一点是一样的。如果没有空壳,工具可能不知道该把那个ID放在哪里。
在现场相遇的样子
**第一,手术前副本不是谈判对象。**在触摸状态的所有命令之前,请复制文件。如果是远程后端的话state pull接收。虽然很难恢复错误移动的地址,但如果有副本的话,只要恢复就可以了。确认副本是否真实的方法是lineage比较价格——必须是具有相同状态的文件。
**第二,状态损坏通常来自中断的apply。**如果网络中断后apply崩溃,文件就会损坏。通过远程后端的版本管理恢复以前版本apply -refresh-only将实物再次匹配是标准的恢复程序。只有一个本地文件运行的情况是危险的真正原因。
**第三,import后必须阅读第一个计划。**如果带来的资源的实际属性与代码不同,计划会试图消除差异。在将从控制台创建的资源的详细设置写入代码之前,如果apply的话,一进来就丢失了设置。import后prevent_destroy暂时挂起来也是常见的防御策。
**第四,转移状态的工作要和锁定一起考虑。**在多人使用的远程状态下,在手术中如果别人操作apply,就无法预测结果。通知工作时间,如果可能的话,暂时停止管道。
在处理状态之前必须做的
state rm,state mv,import虽然不会触动实际资源,但**Terraform会改变世界。
改变看待的眼光。**如果做错了,活着的资源就会被管理之外,下一个apply就会
删除那个。
**首先接收状态。**即使是远程后端,也会在本地留下副本。
terraform state pull > state.backup.json
terraform state list | tee resources.txt
决定是否有办法回溯,是否有办法依靠。
import只在状态中放入。如果没有代码,下一步计划中会出现“删除”。
所以顺序是先写代码,然后import,确认计划是否有效。
如果计划没有,意味着代码与实际资源不同,所以调整代码。
terraform plan -generate-config-out=generated.tf # 코드 초안을 만들어 준다
terraform import aws_s3_bucket.logs my-logs-bucket
terraform plan # 여기서 "No changes" 가 나와야 끝난 것이다
import如果把区块写在代码上的方式,可以在计划中提前看到,更安全。
import {
to = aws_s3_bucket.logs
id = "my-logs-bucket"
}
**state rm不是放弃资源,而是放手。**实际资源保持原样
只忘记了南高Terraform。用在移动到其他堆栈时,在移动到要移动的地方之前导入之前
因为会变成没有人管理的状态,所以在这期间没有人apply。
移动模块时,地址会全部变更。 一个资源一个state mv与其这样做
moved使用区块的话,会出现在计划中并接受审查。状态操作的记录是
虽然没有留下,但在代码中写下的移动会在提交中留下。
在操作之前确认是否有锁。 CI 运行期间如果修复状态,两边就会 上传彼此不同的状态。
下次实习要做的事情
首先打印副本,然后查看状态,state mv更改资源名称并确认计划是否被覆盖。用同样的命令将资源移动到模块内,state rm用计划证明不会删除这个实物的事实。然后import {}区块和tofu import命令用两种方法将外部资源纳入状态,最后-detailed-exitcode用代码证明和状态完全一致,用终止代码证明。