1. Azure IaC与环境治理全景

在传统 Azure 运维中,资源通常通过门户点击、PowerShell 脚本或 CLI 命令逐项创建。这种方式在资源数量少、变更频率低时可行,但当环境扩展到多订阅、多区域、多团队协作时,问题会迅速暴露:同一套应用在开发、测试、生产环境中的配置不一致;有人手动修改了网络安全组规则却没有记录;灾难恢复时无法快速重建一套完全相同的环境。基础设施即代码(Infrastructure as Code,IaC)正是为了解决这类问题而出现的工程实践。

IaC 的核心思想是:把服务器、网络、存储、数据库、身份权限等基础设施资源,用可版本控制的声明式代码描述出来,由工具负责将代码转换为 Azure 中的真实资源。它带来的价值可以归纳为四点:可重复——同一份代码可以反复部署出结构一致的环境;可审计——每次变更都通过代码提交记录留痕;可测试——部署前可以用静态检查和假设验证发现错误;可协作——代码评审、分支策略、CI/CD 流水线都能直接作用于基础设施变更。

ARM 模板与 Bicep 的定位

Azure 原生的 IaC 能力由 Azure 资源管理器(Azure Resource Manager,ARM)提供。ARM 是 Azure 的控制平面,所有资源的创建、更新、删除最终都要经过它。ARM 模板是 JSON 格式的声明式文件,描述目标状态,由 ARM 负责计算差异并执行部署。它的优势是平台原生、无需额外安装代理、支持完整的资源类型和部署模式(增量、完整、验证)。但 JSON 模板冗长,嵌套复杂,参数和变量引用依赖大量函数表达式,可读性较差。

Bicep 是 ARM 模板的领域特定语言(DSL),最终会编译为 ARM 模板 JSON。它保留了 ARM 的全部能力,同时提供更简洁的语法:声明式资源定义、类型系统、模块化、循环与条件、自动依赖推断。对于新项目,Bicep 通常是更推荐的编写方式;对于已有大量 JSON 模板的组织,可以逐步迁移或混合使用。理解两者的关系很重要:Bicep 不是替代 ARM,而是 ARM 的更友好书写层。

Azure IaC 与环境治理全景 编写层 ARM 模板 (JSON) 声明式 · 平台原生 · 冗长 Bicep (DSL) 简洁 · 模块化 · 类型安全 编译 ARM 控制平面 解析模板 计算差异 依赖排序 执行部署 部署 Azure 资源 计算 VM / AKS 网络 VNet / NSG 存储 Storage 身份 RBAC / MI 环境治理目标与挑战 一致性 开发/测试/生产同构 合规性 策略与标签强制 可追溯 变更历史与审计 可恢复 快速重建与回滚 主要挑战:状态漂移 · 多环境参数差异 · 权限边界 · 资源依赖复杂 · 团队协作冲突 应对:代码评审 + CI/CD 流水线 + 策略即代码 + 环境参数分层

环境治理的目标与挑战

环境治理要回答的问题是:如何让多个环境在长期演进中保持可控、一致、合规。具体目标包括:一致性,即开发、测试、生产环境由同一套模板驱动,差异仅体现在参数文件;合规性,通过 Azure Policy 和资源标签强制命名规范、区域限制、加密要求;可追溯,每次部署对应一次代码提交和一条部署记录;可恢复,环境损坏或需要复制时能快速重建。

实际落地时会遇到几类典型挑战。第一是状态漂移:有人通过门户手动改了配置,导致代码描述的状态与真实状态不一致。第二是多环境参数差异:不同环境的 SKU、副本数、网络地址段不同,需要参数化但不能失控。第三是权限边界:部署身份需要哪些权限、如何避免过度授权。第四是资源依赖复杂:资源之间存在隐式依赖,顺序错误会导致部署失败。第五是团队协作冲突:多人同时修改同一模板可能产生覆盖。

应对这些挑战的工程手段包括:用 Git 分支策略和拉取请求评审管理变更;用 CI/CD 流水线自动执行验证和部署;用 Azure Policy 作为策略即代码在订阅或管理组层面兜底;用参数文件按环境分层,把差异集中到少量变量;用 Bicep 模块拆分大型模板,降低单文件复杂度。这些手段会在后续章节逐步展开。

学习建议:先建立“代码是唯一事实来源”的心智模型。任何手动修改都应视为临时操作,最终要回写到代码中。这样后续学习 Bicep 语法、模块化、CI/CD 时,才能理解每个机制在治理链条中的位置。

一个最小示例:从 Bicep 到部署

下面用一个存储账户的 Bicep 片段说明声明式部署的基本形态。它不包含完整参数文件,仅用于展示资源定义、参数引用和输出。

param location string = resourceGroup().location
param storageName string
param skuName string = 'Standard_LRS'

resource stg 'Microsoft.Storage/storageAccounts@2023-01-01' = {
  name: storageName
  location: location
  sku: {
    name: skuName
  }
  kind: 'StorageV2'
  properties: {
    minimumTlsVersion: 'TLS1_2'
    allowBlobPublicAccess: false
  }
}

output storageId string = stg.id

部署时使用 Azure CLI 执行:

az deployment group create \
  --resource-group rg-iac-demo \
  --template-file main.bicep \
  --parameters storageName=stiacdemo001 skuName=Standard_GRS

执行后,ARM 会解析模板、检查资源是否存在、计算需要创建或更新的属性,然后按依赖顺序执行。如果资源已存在且属性一致,部署会报告“无更改”;如果属性有差异,则执行更新。观察部署结果时,重点看三个信息:部署状态(Succeeded/Failed)、资源变更列表、以及输出值是否符合预期。若失败,错误信息通常会指出具体资源类型和属性路径,可据此回到模板修正。

这个最小闭环体现了 IaC 的基本工作方式:编写声明式代码 → 提交到版本控制 → 通过流水线或命令行部署 → 观察部署结果 → 修正代码。环境治理则是在这个闭环之上增加策略、参数分层、权限控制和审计,使多环境、多团队的协作不会退化为混乱的手动操作。