能否合并Azure资源现有状态与Bicep/Pulumi IaC模板?
当前使用ARM/Bicep部署Azure Application Gateway(简称AppGw)的方案存在典型的配置覆盖问题:
- 随着业务迭代,接入该AppGw的其他应用会在自身部署阶段,通过Az CLI在中心基础设施IaC管道流程之外,为AppGw新增规则、后端池、监听器等配置
- AppGw为单实例资源,通过ARM/Bicep模板执行中心侧重部署/更新时,会删除所有未在模板中定义的新增配置
此前采用的临时规避方案为:部署前先检查AppGw是否存在,导出已有的规则、后端池等配置,合并到待部署的ARM/Bicep JSON内容中再执行部署,该方案早期可正常运行。但随着AppGw配置规模和复杂度提升,通过Azure DevOps构建管道部署时已经触发Bash字符数上限,无法继续使用。
之后曾尝试将现有配置导出为文件,通过Azure Bicep的file load功能引入配置,但由于需要在全球多区域部署配置各不相同的多套AppGw,受Bicep编译期文件引用的限制,该方案无法适配多区域部署需求。
确保AppGw基线模板中定义的TLS版本、诊断设置等核心配置生效,同时不覆盖其他独立部署流程新增的配置调整。
需要确认两个问题:
- 是否可以实现现有AppGw的资源状态与基线模板的合并?
- 该能力是可直接通过Azure Bicep实现,还是需要切换到Pulumi/Terraform这类工具才可获得对应支持?
- 管道中的CLI任务先检查目标AppGw是否已存在
- 若不存在,则使用满足最小部署要求的基线模板完成部署
- 若已存在,则拉取现有后端池、监听器等配置,或是拉取资源全量状态
- 将拉取的现有状态与IaC模板文件内容做比对
- 完成状态合并,确保IaC文件定义的核心设置(如诊断设置、TLS版本等)被正确应用,同时保留存量的后端池、监听器等外置新增配置
目前已知Pulumi提供ignoreChanges、transformations相关特性,但无实际使用经验,不确定这类特性能否覆盖当前使用场景。虽然清楚该诉求可能与声明式IaC的设计初衷存在冲突,仍希望了解可行的实现思路。
Bicep/ARM原生能力边界
Bicep/ARM原生不支持子资源级的增量合并,两种官方部署模式都解决不了核心问题:
Complete模式会直接删除所有模板未定义的资源,完全不适用当前场景Incremental模式仅保证顶层AppGw资源本身不被删除,但AppGw的后端池、监听器、路由规则等都属于资源属性下的集合项,不是独立的顶层资源,增量部署时会直接用模板内的集合全量覆盖线上现有值,不会自动保留模板未定义的子项。
之前用的导出合并方案逻辑本身没有问题,触发Bash字符上限是因为把全量配置存在shell变量里拼接,属于实现方式的缺陷,不是思路错误,但多区域场景下长期维护自定义合并脚本的成本会很高。
Terraform/Pulumi适配性
这两类第三代IaC工具都可以直接覆盖需求,不需要自行编写全量合并逻辑:
- Terraform AzureRM provider:通过资源的
lifecycle.ignore_changes配置,指定忽略backend_address_pools、http_listeners、request_routing_rules这类业务侧自主维护的属性集合即可。需要中心管控的TLS版本、诊断设置、SKU、WAF关联这类核心配置正常写在模板里,部署时只会更新这些管控项,完全不会触碰被忽略的子资源集合。只要不把业务侧新增的子资源纳入Terraform状态管理,就不会出现配置覆盖问题。 - Pulumi:提到的
ignoreChanges特性和Terraform的ignore_changes逻辑完全一致,用来实现核心诉求足够用。transformations是更高阶的能力,可以实现比如强制给所有监听器挂统一安全策略、自动给新增配置打中心标签这类全局规则,属于加分项,不是实现基础需求的必需能力。
不换技术栈的折中优化方案
如果暂时不想从Bicep/ARM迁移,可以调整之前合并方案的实现方式,绕开Bash字符数限制:
- 管道中检测到AppGw已存在时,用
az network application-gateway show -g <资源组> -n <AppGw名称>直接把线上全量配置导出为管道工作目录下的临时JSON文件,不要把内容读到shell变量里 - 用
jq做属性合并:仅把基线模板中定义的核心管控属性(TLS策略、诊断配置、WAF绑定等)覆盖到导出的JSON文件中,后端池、监听器、路由规则这类业务属性完全保留导出文件的原值 - 最后执行部署时直接传入合并后的本地JSON文件路径作为模板输入,不需要在命令行拼接长字符串,自然不会触发字符数上限。多区域部署时针对每个区域拉取对应区域的AppGw实例配置做合并即可,不受Bicep编译期文件引用的限制。
注意这个方案需要维护一份明确的中心管控属性路径清单,避免漏管核心配置,长期来看自定义脚本的维护成本还是会高于使用Terraform/Pulumi的原生能力。
内容的提问来源于stack exchange,提问作者Carv

