i007.cc

i007.cc

优先队列-降维打击

05.价值资料

Azure arm template也有state类似的设定么?它是如何比较新旧的差异的?

Azure Resource Manager(ARM)模板(以及基于它的 Bicep)在设计理念上和 Terraform 有一个根本区别:它没有一份独立维护的”state 文件”。

为什么不需要单独的 state

Terraform 之所以要自己维护 state,是因为 Terraform 本身不是云平台的一部分——它是个外部工具,操作各种 provider 的 API,所以它必须自己记一份”我上次看到资源长什么样”的账本,否则没法知道该改什么。而 ARM 模板不一样,它是 Azure 原生的部署机制,Azure Resource Manager 这个控制平面本身就是所有资源的实时数据库。当你提交一次部署时,ARM 直接去查询 Azure 里每个资源当前的真实属性,不需要一份本地或远程的缓存文件来告诉它”上次是什么样子”——因为它随时能拿到”现在是什么样子”的第一手数据。

所以可以说:Terraform 的 state 是一份”我认为现实是什么样”的快照,而 ARM 每次都直接问现实本身。

ARM 是怎么算差异的

ARM 部署有两种模式,这直接决定了它怎么比较新旧差异:

Incremental(增量模式,默认模式)下,ARM 只关心模板里声明的资源。对模板里列出的每个资源,它会去查 Azure 上这个资源当前的实际属性,和模板里期望的属性做逐字段比较,算出需要新建还是修改;对资源组里存在但模板没提到的资源,则完全不动、也不会考虑删除。

Complete(完全模式)下,ARM 除了做上面的增量比较之外,还会额外扫描整个目标资源组里所有当前存在的资源,凡是不在这次模板里出现的,统统删除。这个模式风险比较大,因为它判断”要不要删除”的依据是”资源组里现在有什么 vs 模板里写了什么”,而不是”这个资源当初是不是这个模板创建的”——如果同一个资源组里还有别的工具或别的模板部署过资源,用 Complete 模式很容易被误删。这一点和 Terraform 用 state 精确追踪”哪些资源归我管”是不同的哲学:Terraform 靠自己的账本认领资源,ARM 靠资源组这个物理边界加”是否出现在模板里”来判断。

预览差异:what-if

如果你想要类似 terraform plan 那种”部署前先看看会改什么”的体验,ARM/Bicep 提供的是 what-if 操作(az deployment group what-if 或 PowerShell 的 -WhatIf 参数)。它同样是实时查询 Azure 当前状态,和模板期望状态做对比,然后输出 Create / Modify / Delete / Ignore / NoChange 这几类变更预览,体验上和 Terraform plan 很像,但底层完全不依赖任何持久化的 state 文件,纯粹是当次查询、当次比较。

部署历史不是 state

Azure 确实会在资源组下保留部署历史(portal 里能看到”Deployments”记录,或者用 az deployment group list 查询,默认保留最近 800 次部署记录),但这只是一份操作日志,记录”什么时候用什么模板部署过什么参数”,并不参与差异计算,也不会被下次部署拿来做对比基准——它更像 Git 的 commit 历史,而不是 Terraform state 那种”当前真相的缓存”。

这带来的实际影响

好处是 ARM 天然不存在 Terraform 那种”state 和现实脱节(drift)却发现不了”的问题,因为它每次都是活查询,不需要 terraform import 那样专门”认领”手工创建的资源——只要资源在目标资源组里,Incremental 模式天然就会正确识别它的当前状态。坏处是没有本地缓存,所以每次操作都要付出实时查询整个资源组/资源的成本,而且 Complete 模式的”删除边界”是资源组级别而非模板所有权级别,团队协作时如果搞混了很容易误删别人的资源。

如果你是在纠结要不要从 ARM/Bicep 迁移到 Terraform,或者反过来,这个 state vs 无 state 的差异其实是两边协作模型、CI/CD 流水线设计上最值得权衡的一点,可以细说你的场景我再给具体建议。

发表回复