mcpField
A
azure-verified-modules

azure-verified-modules

github.com/hashicorp云与 DevOps9093.3k 次安装今天更新
代码仓库

关于 azure-verified-modules

这份指南面向希望让 Terraform 模块符合 Azure Verified Modules 认证要求的作者,涵盖模块结构、Provider 约束、测试、文档和变更管理。

主要功能

  1. 01固定版本的 AVM 模块引用
  2. 02Azure Provider 版本规则
  3. 03Terraform 命名与区块排序
  4. 04变量和输出要求
  5. 05测试与文档规范

适用场景

  1. 01核对 Terraform 模块的 AVM 要求
  2. 02指导 Azure 模块变更
  3. 03检查 Provider、测试和文档配置

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/hashicorp/agent-skills --skill azure-verified-modules

安装后在 Claude Code 中输入/azure-verified-modules确认已加载。

详细介绍

Azure Verified Modules(AVM)要求

本指南介绍 Azure Verified Modules 认证的强制要求。这些要求旨在确保 Azure Terraform 模块的一致性、质量和可维护性。

参考资料:

目录


模块交叉引用

严重性: 必须 | 要求: TFFR1

构建资源模块或模式模块时,模块所有者可以交叉引用其他模块。但是:

  • 必须使用 HashiCorp Terraform Registry 引用指定固定版本的模块
    • 示例:source = "Azure/xxx/azurerm",并设置 version = "1.2.3"
  • 不得使用 git 引用(例如,git::https://xxx.yyy/xxx.git 或 github.com/xxx/yyy)
  • 不得引用非 AVM 模块

Azure Provider 要求

严重性: 必须 | 要求: TFFR3

作者必须仅使用以下 Azure Provider:

Provider最低版本最高版本
azapi>= 2.0< 3.0
azurerm>= 4.0< 5.0

要求:

  • 作者可以选择 Azurerm、Azapi,或同时使用这两种 Provider
  • 必须使用 required_providers 块来限定 Provider 版本
  • 建议使用悲观版本约束运算符(~>)

示例:

terraform {
  required_providers {
    azurerm = {
      source  = "hashicorp/azurerm"
      version = "~> 4.0"
    }
    azapi = {
      source  = "Azure/azapi"
      version = "~> 2.0"
    }
  }
}

代码风格标准

小写蛇形命名

严重性: 必须 | 要求: TFNFR4

以下名称必须使用小写蛇形命名:

  • 本地值
  • 变量
  • 输出
  • 资源(符号名称)
  • 模块(符号名称)

示例:snake_casing_example

资源与数据源排序

严重性: 建议 | 要求: TFNFR6

  • 被其他资源依赖的资源建议排在前面
  • 有依赖关系的资源建议彼此靠近定义
count 与 for_each 的用法

严重性: 必须 | 要求: TFNFR7

  • 使用 count 有条件地创建资源
  • 资源的 for_each 集合必须使用 map(xxx) 或 set(xxx)
  • map 的键或 set 的元素必须是静态字面值

示例:

resource "azurerm_subnet" "pair" {
  for_each             = var.subnet_map  # map(string)
  name                 = "${each.value}-pair"
  resource_group_name  = azurerm_resource_group.example.name
  virtual_network_name = azurerm_virtual_network.example.name
  address_prefixes     = ["10.0.1.0/24"]
}
资源与数据块内部排序

严重性: 建议 | 要求: TFNFR8

资源块/数据块中的顺序:

  1. 元参数(顶部):

    • provider
    • count
    • for_each
  2. 参数/块(中间,按字母顺序):

    • 必需参数
    • 可选参数
    • 必需嵌套块
    • 可选嵌套块
  3. 元参数(底部):

    • depends_on
    • lifecycle(子项顺序:create_before_destroy、ignore_changes、prevent_destroy)

各部分之间用空行分隔。

模块块排序

严重性: 建议 | 要求: TFNFR9

模块块中的顺序:

  1. 顶部元参数:

    • source
    • version
    • count
    • for_each
  2. 参数(按字母顺序):

    • 必需参数
    • 可选参数
  3. 底部元参数:

    • depends_on
    • providers
Lifecycle ignore_changes 语法

严重性: MUST | 要求: TFNFR10

ignore_changes 属性不得用双引号括起来。

正确:

lifecycle {
  ignore_changes = [tags]
}

错误:

lifecycle {
  ignore_changes = ["tags"]
}
条件创建的 Null 比较

严重性: SHOULD | 要求: TFNFR11

对于需要条件创建资源的参数,请用 object 类型包装,以避免在计划阶段出现“应用后已知”的问题。

建议:

variable "security_group" {
  type = object({
    id = string
  })
  default = null
}
可选嵌套对象的 Dynamic 块

严重性: MUST | 要求: TFNFR12

条件下的嵌套块必须使用以下模式:

dynamic "identity" {
  for_each = <condition> ? [<some_item>] : []

  content {
    # block content
  }
}
使用 coalesce/try 设置默认值

严重性: SHOULD | 要求: TFNFR13

正确:

coalesce(var.new_network_security_group_name, "${var.subnet_name}-nsg")

错误:

var.new_network_security_group_name == null ? "${var.subnet_name}-nsg" : var.new_network_security_group_name
模块中的 Provider 声明

严重性: MUST | 要求: TFNFR27

  • 模块中不得声明 provider(configuration_aliases 除外)
  • 模块中的 provider 块只能使用 alias
  • 建议由模块用户传入 Provider 配置

变量要求

不允许的变量

严重性: MUST | 要求: TFNFR14

模块所有者不得添加 enabled 或 module_depends_on 之类的变量来控制整个模块的运行。针对特定资源的布尔功能开关可以使用。

变量定义顺序

严重性: SHOULD | 要求: TFNFR15

变量建议按以下顺序排列:

  1. 所有必填字段(按字母顺序)
  2. 所有可选字段(按字母顺序)
变量命名规则

严重性: SHOULD | 要求: TFNFR16

带说明的变量

严重性: SHOULD | 要求: TFNFR17

  • description 建议准确描述参数的用途和预期数据类型
  • 目标受众是模块用户,而非开发者
  • 对于 object 类型,请使用 HEREDOC 格式
带类型的变量

严重性: MUST | 要求: TFNFR18

  • 必须为每个变量定义 type
  • type 建议尽可能精确
  • 只有在理由充分时才可以使用 any
  • 对于 true/false 值,使用 bool 而非 string/number
  • 使用具体的 object,而非 map(any)
敏感数据变量

严重性: SHOULD | 要求: TFNFR19

如果变量类型为 object 且包含敏感字段,则整个变量建议设置为 sensitive = true,或将敏感字段提取为单独的变量。

集合类型使用非空默认值

严重性: SHOULD | 要求: TFNFR20

在循环中使用集合值(set、map、list)时,nullable 建议设置为 false。对于标量值,null 可能具有语义含义。

默认情况下避免可空

严重性: MUST | 要求: TFNFR21

除非 null 值有特定的语义需求,否则必须避免使用 nullable = true。

避免 sensitive = false

严重性: MUST | 要求: TFNFR22

必须避免使用 sensitive = false(这是默认值)。

敏感默认值条件

严重性: MUST | 要求: TFNFR23

不得为敏感输入设置默认值(例如默认密码)。

处理已弃用的变量

严重性: MUST | 要求: TFNFR24

  • 将已弃用的变量移至 deprecated_variables.tf
  • 在说明开头标注 DEPRECATED
  • 声明替代变量的名称
  • 在主要版本发布期间清理

输出要求

其他 Terraform 输出

严重性: SHOULD | 要求: TFFR2

作者 SHOULD NOT 输出整个资源对象,因为其中可能包含敏感数据,且架构可能随 API 或提供程序版本而变化。

最佳实践:

  • 将资源的计算得出的属性作为独立输出输出(防腐层模式)
  • SHOULD NOT 输出已经作为输入的值(name 除外)
  • 对敏感属性使用 sensitive = true
  • 对使用 for_each 部署的资源,以映射结构输出计算得出的属性

示例:

# Single resource computed attribute
output "foo" {
  description = "MyResource foo attribute"
  value       = azurerm_resource_myresource.foo
}

# for_each resources
output "childresource_foos" {
  description = "MyResource children's foo attributes"
  value = {
    for key, value in azurerm_resource_mychildresource : key => value.foo
  }
}

# Sensitive output
output "bar" {
  description = "MyResource bar attribute"
  value       = azurerm_resource_myresource.bar
  sensitive   = true
}
敏感数据输出

严重性: MUST | 要求: TFNFR29

包含机密数据的输出 MUST 声明为 sensitive = true。

处理已弃用的输出

严重性: MUST | 要求: TFNFR30

  • 将已弃用的输出移至 deprecated_outputs.tf
  • 在 outputs.tf 中定义新输出
  • 在主版本发布期间进行清理

本地值规范

locals.tf 组织

严重性: MAY | 要求: TFNFR31

  • locals.tf SHOULD 仅包含 locals 块
  • 在高级场景中,MAY 在资源旁声明 locals 块
本地值按字母顺序排列

严重性: MUST | 要求: TFNFR32

locals 块中的表达式 MUST 按字母顺序排列。

精确的本地值类型

严重性: SHOULD | 要求: TFNFR33

使用精确的类型(例如,年龄使用 number 而非 string)。


Terraform 配置要求

Terraform 版本要求

严重性: MUST | 要求: TFNFR25

terraform.tf 要求:

  • MUST 仅包含一个 terraform 块
  • 第一行 MUST 定义 required_version
  • MUST 包含最低版本约束
  • MUST 包含最高主版本约束
  • SHOULD 使用 ~> #.# 或 >= #.#.#, < #.#.# 格式

示例:

terraform {
  required_version = "~> 1.6"
  required_providers {
    azurerm = {
      source  = "hashicorp/azurerm"
      version = "~> 4.0"
    }
  }
}
required_providers 中的提供程序

严重性: MUST | 要求: TFNFR26

  • terraform 块 MUST 包含 required_providers 块
  • 每个提供程序 MUST 指定 source 和 version
  • 提供程序 SHOULD 按字母顺序排列
  • 仅包含直接需要的提供程序
  • source MUST 采用 namespace/name 格式
  • version MUST 包含最低和最高主版本约束
  • SHOULD 使用 ~> #.# 或 >= #.#.#, < #.#.# 格式

测试要求

测试工具

严重性: MUST | 要求: TFNFR5

AVM 必需的测试工具:

  • Terraform(terraform validate/fmt/test)
  • terrafmt
  • Checkov
  • tflint(使用 azurerm 规则集)
  • Go(可选,用于自定义测试)
测试提供程序配置

严重性: SHOULD | 要求: TFNFR36

为确保稳健测试,测试提供程序配置中 SHOULD 显式将 prevent_deletion_if_contains_resources 设为 false。


文档要求

模块文档生成

严重性: MUST | 要求: TFNFR2

  • 文档 MUST 通过 Terraform Docs 自动生成
  • 模块根目录 MUST 包含 .terraform-docs.yml 文件

破坏性变更与功能管理

使用功能开关

严重性: MUST | 要求: TFNFR34

在次版本或补丁版本中新增的资源 MUST 配备一个开关变量,以避免默认创建:

variable "create_route_table" {
  type     = bool
  default  = false
  nullable = false
}

resource "azurerm_route_table" "this" {
  count = var.create_route_table ? 1 : 0
  # ...
}
审查潜在的破坏性变更

严重性: MUST | 要求: TFNFR35

需要谨慎处理的破坏性变更:

资源块:

  1. 添加资源时未进行条件创建
  2. 添加非默认值的参数
  3. 添加未使用 dynamic 的嵌套块
  4. 重命名资源时未添加 moved 块
  5. 将 count 改为 for_each,或反之

变量/输出块:

  1. 删除/重命名变量
  2. 更改变量 type
  3. 更改变量 default 值
  4. 将 nullable 改为 false
  5. 将 sensitive 从 false 改为 true
  6. 添加未设置 default 的变量
  7. 删除输出
  8. 更改输出 value
  9. 更改输出 sensitive 值

贡献标准

GitHub 仓库分支保护

严重性: MUST | 要求: TFNFR3

模块所有者 必须 在默认分支(通常为 main)上设置分支保护策略:

  1. 合并前必须提交 Pull Request
  2. 必须批准最近一次可审查的推送
  3. 推送新提交时,取消过时的 PR 批准
  4. 要求线性历史
  5. 禁止强制推送
  6. 不允许删除分支
  7. 要求 CODEOWNERS 审查
  8. 不允许绕过设置
  9. 对管理员强制执行

合规性检查清单

开发或审查 Azure Verified Modules 时,请使用此检查清单:

模块结构
  • 模块交叉引用使用带固定版本的注册表源
  • Azure 提供程序(azurerm/azapi)版本符合 AVM 要求
  • 模块根目录中存在 .terraform-docs.yml
  • 存在 CODEOWNERS 文件
代码风格
  • 所有名称均使用小写蛇形命名法
  • 资源按依赖项优先的顺序排列
  • for_each 使用具有静态键的 map() 或 set()
  • resource/data/module 块遵循正确的内部排序
  • ignore_changes 不加引号
  • 条件嵌套对象使用动态块
  • 默认值使用 coalesce() 或 try()
变量
  • 不含 enabled 或 module_depends_on 变量
  • 变量排序:必需变量(按字母顺序),然后是可选变量(按字母顺序)
  • 所有变量均具有精确类型(避免使用 any)
  • 所有变量均有说明
  • 集合设置了 nullable = false
  • 不声明 sensitive = false
  • 敏感输入不设置默认值
  • 弃用的变量移至 deprecated_variables.tf
输出
  • 输出采用防腐层模式(离散属性)
  • 敏感输出标记为 sensitive = true
  • 弃用的输出移至 deprecated_outputs.tf
Terraform 配置
  • terraform.tf 中包含版本约束(~> 格式)
  • 存在包含所有提供程序的 required_providers 块
  • 模块中不声明 provider(别名除外)
  • Locals 按字母顺序排列
测试与质量
  • 配置了必需的测试工具
  • 新资源具有功能开关
  • 已审查并记录破坏性变更

汇总统计

  • 功能性要求: 3
  • 非功能性要求: 34
  • 要求总数: 37
按严重性分类
  • MUST: 21 项要求
  • SHOULD: 14 项要求
  • MAY: 2 项要求

依据:Azure Verified Modules - Terraform Requirements

评论

支持 Markdown