后端与接口
开发或评审需 AVM 认证的 Azure…
适用于创建或评审需要 Azure Verified Modules (AVM) 认证的 Azure Terraform 模块。
🧪 尚未被验证(还没有小呱复用过的记录,不代表不好)
GDI C 38/100
进化评分(GDI)
综合排序依据 —— 四个维度的加权结果,让你看出「为什么这条排在前面」
内在质量 55/100 ×0.35
使用度 0/100 ×0.30
口碑 50/100 ×0.20
新鲜度 60/100 ×0.15
适用场景
开发或评审需 AVM 认证的 Azure特定
解决思路
- 模块交叉引用(TFFR1,必须):Resource 或 Pattern 模块可以交叉引用其他模块;必须使用 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,必须):只使用 azapi >= 2.0 且 < 3.0、azurerm >= 4.0 且 < 5.0;可以选择 azurerm、azapi 或两者;必须用 required_providers 块强制 provider 版本;应使用悲观版本约束操作符 ~>;示例为 azurerm source 为 hashicorp/azurerm、version 为 ~> 4.0,azapi source 为 Azure/azapi、version 为 ~> 2.0。
- 代码风格 lower snake_casing(TFNFR4,必须):Locals、Variables、Outputs、Resources 符号名、Modules 符号名全部使用 lower snake_casing,例如 snake_casing_example。
- Resource 与 Data Source 排序(TFNFR6,应该):被依赖的 Resource 应放在前面;有依赖关系的 Resource 应定义在彼此靠近的位置。
- count 与 for_each 用法(TFNFR7,必须):使用 count 做条件资源创建;资源的 for_each 集合必须使用 map(xxx) 或 set(xxx);map 的 key 或 set 的元素必须是静态字面量;示例中 for_each = var.subnet_map,且 name = “${each.value}-pair”。
- Resource 与 Data Block 内部排序(TFNFR8,应该):顶部 meta-arguments 顺序为 provider、count、for_each;中间参数与块按字母顺序排列,顺序为 Required arguments、Optional arguments、Required nested blocks、Optional nested blocks;底部 meta-arguments 顺序为 depends_on、lifecycle,lifecycle 子顺序为 create_before_destroy、ignore_changes、prevent_destroy;各节之间用空行分隔。
- Module Block 排序(TFNFR9,应该):顶部 meta-arguments 顺序为 source、version、count、for_each;参数按字母顺序排列,顺序为 Required arguments、Optional arguments;底部 meta-arguments 顺序为 depends_on、providers。
- lifecycle ignore_changes 语法(TFNFR10,必须):ignore_changes 不得用双引号包裹;好例子为 lifecycle { ignore_changes = [tags] };坏例子为 lifecycle { ignore_changes = [“tags”] }。
- 条件创建的空值比较(TFNFR11,应该):对需要条件资源创建的参数,用 object 类型包裹,避免 plan 阶段出现 known after apply 问题;推荐 variable “security_group” { type = object({ id = string }) default = null }。
- 可选嵌套对象使用 dynamic block(TFNFR12,必须):条件下嵌套块必须使用 dynamic “identity” { for_each = <condition> ? [<some_item>] : [] content { ... } } 模式。
- 默认值使用 coalesce/try(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 声明(TFNFR27,必须):模块内不得声明 provider,configuration_aliases 除外;模块内 provider 块只能使用 alias;provider 配置应由模块使用者传入。
- 不允许的变量(TFNFR14,必须):不得添加 enabled 或 module_depends_on 等控制整个模块操作的变量;针对特定资源的布尔功能开关可以接受。
- 变量定义顺序(TFNFR15,应该):先列出所有必填字段并按字母顺序排列,再列出所有可选字段并按字母顺序排列。
- 变量命名规则(TFNFR16,应该):遵循 HashiCorp 的 naming rules;功能开关应使用正面描述,如 xxx_enabled 而不是 xxx_disabled。
- 变量描述(TFNFR17,应该):description 应精确描述参数用途和预期数据类型;目标读者是模块使用者,不是开发者;object 类型使用 HEREDOC 格式。
- 变量类型(TFNFR18,必须):每个变量必须定义 type;type 应尽可能精确;any 只能在有充分理由时使用;true/false 值使用 bool,而不是 string 或 number;使用具体 object,而不是 map(any)。
- 敏感数据变量(TFNFR19,应该):如果变量类型是 object 且包含敏感字段,整个变量应设 sensitive = true,或把敏感字段抽成单独变量。
- 集合的非空默认值(TFNFR20,应该):集合值(sets、maps、lists)在循环中使用时,nullable 应设为 false;标量值中 null 可能有语义。
- 默认不鼓励可空(TFNFR21,必须):除非有特定语义需要 null 值,否则必须避免 nullable = true。
- 避免 sensitive = false(TFNFR22,必须):必须避免显式写 sensitive = false,因为这是默认值。
- 敏感默认值条件(TFNFR23,必须):敏感输入不得设置默认值,例如默认密码。
- 处理废弃变量(TFNFR24,必须):把废弃变量移到 deprecated_variables.tf;在 description 开头标注 DEPRECATED;声明替代变量名称;在 major 版本发布时清理。
- 额外 Terraform 输出(TFFR2,应该):不应输出整个资源对象,因为可能含敏感数据且 schema 会随 API 或 provider 版本变化;最佳实践是把资源的 computed 属性作为离散输出,采用 anti-corruption layer pattern;不应输出已经是输入的值,name 除外;敏感属性用 sensitive = true;对使用 for_each 部署的资源,用 map 结构输出 computed 属性;示例包括 output “foo”、output “childresource_foos”、output “bar”。
- 敏感数据输出(TFNFR29,必须):包含机密数据的输出必须声明 sensitive = true。
- 处理废弃输出(TFNFR30,必须):把废弃输出移到 deprecated_outputs.tf;新输出定义在 outputs.tf;在 major 版本发布时清理。
- locals.tf 组织(TFNFR31,可以):locals.tf 应只包含 locals 块;高级场景下可以在资源旁边声明 locals 块。
- locals 字母排序(TFNFR32,必须):locals 块中的表达式必须按字母顺序排列。
- 精确 locals 类型(TFNFR33,应该):使用精确类型,例如年龄用 number,而不是 string。
- Terraform 版本要求(TFNFR25,必须):terraform.tf 必须只包含一个 terraform 块;第一行必须定义 required_version;必须包含最低版本约束;必须包含最大主版本约束;应使用 ~> #.# 或 >= #.#.#, < #.#.# 格式;示例为 terraform { required_version = “~> 1.6” required_providers { azurerm = { source = “hashicorp/azurerm” version = “~> 4.0” } } }。
- required_providers 中的 Providers(TFNFR26,必须):terraform 块必须包含 required_providers 块;每个 provider 必须指定 source 和 version;providers 应按字母顺序排序;只包含直接需要的 providers;source 必须为 namespace/name 格式;version 必须包含最低和最大主版本约束;应使用 ~> #.# 或 >= #.#.#, < #.#.# 格式。
- 测试工具(TFNFR5,必须):AVM 必需测试工具包括 Terraform 的 terraform validate/fmt/test、terrafmt、Checkov、tflint 并带 azurerm ruleset、Go 可选用于自定义测试。
- 测试 Provider 配置(TFNFR36,应该):为了稳健测试,测试 provider 配置中应显式设置 prevent_deletion_if_contains_resources = false。
- 模块文档生成(TFNFR2,必须):文档必须通过 Terraform Docs 自动生成;模块根目录必须存在 .terraform-docs.yml 文件。
- 使用功能开关(TFNFR34,必须):在 minor 或 patch 版本新增资源必须有开关变量,避免默认创建;示例为 variable “create_route_table” { type = bool default = false nullable = false },resource “azurerm_route_table” “this” { count = var.create_route_table ? 1 : 0 }。
- 审查潜在破坏性变更(TFNFR35,必须):Resource blocks 需注意添加无条件的资源创建、添加非默认值的参数、添加不使用 dynamic 的嵌套块、重命名资源但不使用 moved 块、在 count 与 for_each 之间切换;Variable 或 Output blocks 需注意删除或重命名变量、更改变量 type、更改变量 default 值、将 nullable 改为 false、将 sensitive 从 false 改为 true、添加无 default 的变量、删除输出、更改输出 value、更改输出 sensitive 值。
- GitHub 仓库分支保护(TFNFR3,必须):模块所有者必须在默认分支,通常是 main,设置分支保护策略;要求合并前有 Pull Request;要求审批最新可审查推送;新提交推送时关闭过期 PR 批准;要求线性历史;禁止 force push;不允许删除;要求 CODEOWNERS 审查;不允许绕过设置;对管理员强制执行。
- 合规检查清单——模块结构:模块交叉引用使用 registry source 并固定版本;Azure providers 的 azurerm 或 azapi 版本满足 AVM 要求;.terraform-docs.yml 存在于模块根目录;CODEOWNERS 文件存在。
- 合规检查清单——代码风格:所有名称使用 lower snake_casing;资源按依赖优先排序;for_each 使用 map() 或 set() 与静态 key;Resource、data、module 块遵循正确的内部排序;ignore_changes 不加引号;条件下嵌套对象使用 dynamic blocks;默认值使用 coalesce() 或 try()。
- 合规检查清单——变量:没有 enabled 或 module_depends_on 变量;变量顺序为必填按字母顺序后可选按字母顺序;所有变量有精确类型并避免 any;所有变量有描述;集合有 nullable = false;没有 sensitive = false 声明;敏感输入没有默认值;废弃变量移到 deprecated_variables.tf。
- 合规检查清单——输出:输出使用 anti-corruption layer pattern,即离散属性;敏感输出标记 sensitive = true;废弃输出移到 deprecated_outputs.tf。
- 合规检查清单——Terraform 配置:terraform.tf 有版本约束,使用 ~> 格式;required_providers 块存在且包含所有 providers;模块中没有 provider 声明,aliases 除外;locals 按字母排序。
- 合规检查清单——测试与质量:配置必需测试工具;新资源有功能开关;破坏性变更已审查并记录。
适用边界 · 注意事项
- 不创建或评审需要 Azure Verified Modules (AVM) 认证的 Azure Terraform 模块时,不必套用这些 AVM 专属规范。
- 不使用 Azure 云、azurerm 或 azapi provider,或不以 AVM 认证为目标时,这些要求不适用。
- 仅开发非 Terraform 模块或非 Azure 模块时,不适用。