awesome-copilot 实战:为 Azure 编写现代 Terraform 代码的 Copilot 指令指南
【免费下载链接】awesome-copilotCommunity-contributed instructions, agents, skills, and configurations to help you make the most of GitHub Copilot.项目地址: https://gitcode.com/GitHub_Trending/aw/awesome-copilot
GitHub Copilot 的指令(Instructions)文件是约束代码生成行为的核心机制。在 awesome-copilot 仓库中,instructions/generate-modern-terraform-code-for-azure.instructions.md 就是一份专门面向 Azure Terraform 代码生成的指令文件:它通过 frontmatter 声明适用范围,并在正文中给出 10 条可执行的质量守则,从版本锁定、代码组织、模块封装,到 Provider 选型、幂等性、状态管理与验证测试一应俱全。读完本文,你将理解这份指令的完整脉络,掌握在 Copilot 中落地现代 Azure Terraform 代码的整套实操标准,并知晓它与仓库内 terraform.instructions.md、terraform-azure.instructions.md、azure-verified-modules-terraform.instructions.md 三份配套指令的分工关系。
一、先读懂这份指令文件本身
1.1 文件的定位与生效机制
与仓库内所有 instructions 文件一致,这份文件通过 YAML frontmatter 声明元数据:
--- description: 'Guidelines for generating modern Terraform code for Azure' applyTo: '**/*.tf' ---description:向模型描述该指令的用途,帮助 Copilot 在合适场景自动加载;applyTo:声明生效的文件范围,**/*.tf意味着当用户打开或编辑任意层级的.tf文件时,该指令都会作为生成代码的上下文约束。
换言之,这是一份"文件类型级"的规则注入:只要 Copilot 在处理 Terraform 配置文件,这 10 条准则就会被激活。仓库中另有 docs/README.instructions.md 系统介绍 instructions 的编写与使用方式,可作为机制层面的延伸阅读。
1.2 它与仓库内其他 Terraform 指令的关系
awesome-copilot 围绕 Terraform 提供了多份指令,分工各不相同,阅读时可互为参照:
| 指令文件 | 侧重点 |
|---|---|
| generate-modern-terraform-code-for-azure.instructions.md(本文主体) | 生成现代、高质量 Azure Terraform 代码的 10 条直接准则 |
| terraform.instructions.md | 通用 Terraform 约定:安全、模块化、可维护性、风格格式化、文档、测试 |
| terraform-azure.instructions.md | Azure 场景最佳实践:AVM 应用、反模式规避、secrets、文件夹结构、成本管理 |
| azure-verified-modules-terraform.instructions.md | Azure Verified Modules(AVM)的发现、使用、版本管理与贡献规范 |
下文各节将首先完整继承主体文件中的每一条准则,再用上述配套指令与仓库内可核验的约定进行纵深扩充,使每一条都具备可直接落地的操作性。
二、使用最新的 Terraform 与 Azure Providers
原准则:始终瞄准最新稳定版 Terraform 与 Azure providers;在代码中显式声明所需版本以强制执行;保持 provider 版本更新以获取新功能与修复。
这条准则在实际代码中的落点是required_providers块与required_version。以 azurerm provider 为例,标准写法如下:
terraform { required_version = ">= 1.9" required_providers { azurerm = { source = "hashicorp/azurerm" version = "~> 4.0" } } }required_version:声明 HCL 所需的最低 Terraform 版本,防止旧版二进制执行新语法(如ephemeral资源、改进后的for_each语义);- provider 的
version:使用悲观约束(pessimistic constraint,~> 4.0)锁定大版本,同时允许向后兼容的小版本升级。
在 terraform-azure.instructions.md 的"Follow recommended Terraform practices"一节中,这一条被量化为 AVM 规范TFFR3:始终以最新稳定版 Terraform 与 Azure provider 为目标,在代码中指定版本并保持更新。与之配套的 azure-verified-modules-terraform.instructions.md 在"Version Management"一节进一步给出了版本检查与固定策略:
- 悲观约束用于日常开发:
version = "~> 1.0"; - 生产环境建议固定精确版本:
version = "1.2.3"; - 任何升级前都应先阅读 changelog。
实操建议:在.tf文件中把版本声明视为"合同"——不仅约束本地 CLI,也约束 CI 流水线中的 Terraform 版本,从源头消除"本地能跑、CI 报错"的环境漂移。
三、清晰组织代码:文件分工与格式化
原准则:用逻辑清晰的文件切分 Terraform 配置——main.tf放资源、variables.tf放输入、outputs.tf放输出;遵循一致的命名与格式化(terraform fmt)。
这是 Terraform 项目最基础的工程化骨架,terraform-azure.instructions.md 在此基础上做了两处重要扩充:
- 文件分工更细:增加
terraform.tf(provider 配置)与locals.tf(本地值/复杂表达式); - 文件拆分规则:当
main.tf或variables.tf过大时,按资源类型或职能拆分,如main.networking.tf、main.storage.tf,并把对应变量同步拆到variables.networking.tf、variables.storage.tf。
一个符合规范的根模块文件布局为:
my-azure-app/ ├── main.tf # 核心资源 ├── variables.tf # 输入变量 ├── outputs.tf # 输出 ├── terraform.tf # provider 配置与版本约束 ├── locals.tf # 本地值 └── environments/ # 环境差异配置 ├── dev.tfvars ├── test.tfvars └── prod.tfvars格式与命名层面有两点共识:变量与模块名统一使用snake_casing(snake_case);每次修改后执行terraform fmt统一缩进(Terraform 风格指南约定每级 2 空格)。terraform.instructions.md 还补充了更细的风格规则:depends_on置于资源定义块最前、for_each/count紧随其后、lifecycle块置于资源定义末尾、同文件内对 providers/variables/data sources/resources/outputs 按字母序排列,以提升导航效率。
四、封装成模块:复用而非复制
原准则:任何会在多个场景复用的资源组都应封装为模块——为模块定义自己的变量与输出,通过引用模块而非复制代码,促进复用与一致性。
模块化的核心判断标准是"复用价值":单资源不建模块(过度抽象),真正相关的资源组才封装。这与 terraform.instructions.md 的模块化约定完全一致:模块用于封装相关资源、避免配置重复、保持层级浅、避免模块间循环依赖。
在 Azure 场景下,更现代的模块化路线是优先使用 Azure Verified Modules(AVM)。terraform-azure.instructions.md 明确要求:任何重要资源只要存在对应 AVM 就应使用之,因为 AVM 对齐 Well-Architected Framework、由微软维护、能显著减少自维护代码量;若无对应 AVM,则建议按 AVM 风格自建模块,以便未来向社区上游贡献。
AVM 模块的命名遵循Azure/avm-res-{service}-{resource}/azurerm(资源模块)、Azure/avm-ptn-{pattern}/azurerm(模式模块)、Azure/avm-utl-{utility}/azurerm(工具模块)三种形态,使用方式见 azure-verified-modules-terraform.instructions.md:
module "resource_group" { source = "Azure/avm-res-resources-resourcegroup/azurerm" version = "~> 0.1" enable_telemetry = true location = var.location name = var.resource_group_name } module "virtual_network" { source = "Azure/avm-res-network-virtualnetwork/azurerm" version = "~> 0.1" enable_telemetry = true location = module.resource_group.location name = var.vnet_name resource_group_name = module.resource_group.name address_space = ["10.0.0.0/16"] }注意这里模块间通过module.resource_group.location、module.resource_group.name引用输出,形成隐式依赖——这正是"模块拥有独立变量/输出接口"的落地示范,同时避免依赖 module 输出之外的隐式耦合。
五、善用变量与输出:参数化一切
原准则:用带类型与描述的变量参数化所有可配置值;为可选变量提供默认值;用输出暴露关键资源属性;对敏感值做标记以保护机密。
terraform-azure.instructions.md 将这一条展开为 AVM 对齐的编码标准(对应 TFNFR17/18/20/22 等规范),可归纳为五条硬性要求:
- 变量命名:全部使用 snake_case,描述性且与命名约定一致(TFNFR4、TFNFR16);
- 类型与描述:所有变量必须有显式
type声明(TFNFR18)与完整description(TFNFR17);集合类型尽量避免可空的默认值(TFNFR20); - 敏感变量:正确标记
sensitive,避免显式写sensitive = false(TFNFR22),敏感默认值的处理要遵循正确姿势(TFNFR23); - 动态块与默认值:可选嵌套对象用
dynamic块(TFNFR12),默认值善用coalesce、try函数(TFNFR13); - 本地值:
locals.tf专用于本地值(TFNFR31),并为 locals 保持精确类型(TFNFR33)。
一个参数化的变量声明范例:
variable "environment" { type = string description = "Deployment environment (dev, test, prod)" default = "dev" validation { condition = contains(["dev", "test", "prod"], var.environment) error_message = "Environment must be one of: dev, test, prod." } } variable "owner" { type = string description = "Team or individual owning the resources" }输出同样要"按需而为":只暴露其他配置真正需要的信息,所有输出提供清晰描述,包含机密的输出必须sensitive = true(terraform-azure.instructions.md 给出了资源组与虚拟网络 ID 输出的标准范例)。关于机密,该指令还有一条更彻底的思路:最好的机密是不需要存储的机密——优先用 Managed Identity 而非密码/密钥;Terraform v1.11+ 支持ephemeral(write-only)参数时,可避免把机密写入状态文件。
六、Provider 选型:azurerm 优先,azapi 兜底
原准则:
- 大多数场景使用
azurermprovider——稳定性高、覆盖大多数 Azure 服务; - 仅在需要最新 Azure 功能或
azurerm尚未支持的资源时使用azapiprovider; - 在代码注释中记录选型理由;
- 两者可混用,但拿不准时优先
azurerm。
这条准则的实质是"成熟优先"的工程判断:azurerm是多年打磨的稳定实现,覆盖绝大多数生产需求;azapi面向 ARM API 的通用 CRUD,能第一时间吃到新服务/新特性,但代价是需要手动维护资源 schema。两者混用的典型形态是:主体资源用azurerm,个别"尝鲜"资源用azapi,并用注释说明每个azapi资源为何不能迁移回azurerm。
在 terraform-azure.instructions.md 中,这一选择被进一步与 AVM 结合:绝大多数 Azure 服务都有对应的azurerm资源实现,也通常存在官方 AVM 模块;只有当服务过新、连 AVM 都未覆盖时才需要考虑azapi路线。实操建议:每次引入azapi资源时,务必在同一resource块上方写注释,记录引入时间、对应 Azure 服务的 GA 状态、以及"一旦 azurerm 支持即迁移"的 TODO,防止技术债沉淀。
七、最小依赖:保持技术栈精简
原准则:不引入项目范围之外的多余 providers 或模块;若确需特殊 provider(如random、tls)或外部模块,必须加注释说明并征得用户同意;保持基础设施栈精简。
这条准则在 terraform-azure.instructions.md 中被同样强调:不得在未经用户确认的情况下引入额外 provider(如random、tls)或外部模块;确需引入时用注释解释原因并保持栈精简。
最小依赖的价值在于三重收敛:
- 风险面收敛:每个 provider 都是一段需要更新、审计、可能有 CVE 的第三方代码;
- 计划面收敛:额外 provider 会显著拉长
terraform plan的 provider 加载与 schema 解析时间(terraform.instructions.md 也提示无必要的数据源会拖慢 plan/apply); - 认知成本收敛:队友阅读代码时只需掌握少数 provider 的语义。
一个典型取舍是randomprovider:生成资源后缀、密码等场景确实常用,但若能用timestamp()、uuid()或 AVM 内部已封装的随机逻辑替代,就不必新增 provider。原则:任何 provider 或模块的引入都要"先解释、再批准、后引入"。
八、确保幂等性:重复执行结果一致
原准则:配置可被反复 apply 且结果相同;避免非幂等动作(每次 apply 都运行的脚本、重复创建会冲突的资源);通过多次terraform apply验证第二次运行为零变更;用 lifecycle 设置或条件表达式优雅处理漂移与外部变更。
幂等性是 IaC 的根基。需要警惕的高危模式包括:
- 使用
local-exec/remote-execprovisioner 在每次 apply 时执行副作用脚本——除非绝对必要,否则应避免(terraform-azure.instructions.md 将其列为反模式); - 依赖无确定性语义的随机生成值,导致每次 plan 都提议变更;
- 资源参数依赖 API 返回的运行时值(如默认生成的密码)未捕获到状态。
处理漂移的典型lifecycle设置:
resource "azurerm_resource_group" "example" { name = var.resource_group_name location = var.location lifecycle { # 允许外部(如 Azure 门户手动操作)修改 tags 时不被强制回滚 ignore_changes = [tags] } }验证方法遵循 terraform-azure.instructions.md 的约定:先测试再上生产——在非生产环境执行多次 apply,第二次 plan 应显示 "No changes"。这与 terraform.instructions.md 的测试要求一脉相承:用.tftest.hcl编写覆盖正反场景的测试,且测试本身必须幂等、可重复执行。
九、状态管理:远程后端 + 锁 + 永不入库
原准则:使用远程后端(如带状态锁的 Azure Storage)安全存储状态;启用团队协作;绝不把状态文件提交到版本控制。
落地形态是 Azure Storage 后端 + blob 租约锁:
terraform { backend "azurerm" { resource_group_name = "tfstate-rg" storage_account_name = "tfstateaccount" container_name = "tfstate" key = "my-azure-app.terraform.tfstate" } }terraform-azure.instructions.md 在此基础上有更严格的纪律:
- 状态文件(
**/*.tfstate)只允许只读操作,一切变更必须通过 Terraform CLI 或 HCL 完成; **/.terraform/**(拉取的模块与 provider)同样只读,禁止手工改动;- 启用静态加密与传输加密;
- 状态中可能包含明文属性,必须配合"敏感值不入状态"(ephemeral、
sensitive、Managed Identity)策略。
团队协作层面,状态锁可以防止多人并发 apply 造成的状态竞争;而"永不提交状态文件"则通过.gitignore中的*.tfstate、*.tfstate.*规则落实。terraform.instructions.md 也强调用环境变量引用密钥服务的值(如ARM_SUBSCRIPTION_ID),使敏感值始终不落盘于状态文件——这与 Azure 场景下ARM_SUBSCRIPTION_ID由环境变量注入、而非硬编码进 provider 块的要求完全一致。
十、文档与图表:让基础设施可读
原准则:维护最新文档;代码变更后同步更新 README.md(新变量、新输出、使用说明);考虑用terraform-docs自动化;每次重大更新后同步架构图;良好的文档与图表让全团队理解基础设施。
文档维护有两个层次:
- 自动生成:
terraform-docs可从 HCL 生成变量/输出/资源清单,terraform-docs markdown table . > README.md即可产出结构化参考文档,避免手工同步遗漏; - 手工补充:README 中保留使用说明、环境准备、后端配置、常见问题等叙述性内容,与自动生成部分互补。
terraform-azure.instructions.md 还强调"代码变更即文档变更"的节奏:新增变量/输出时同步更新 README;每次重大基础设施变更后更新架构图。这与 terraform.instructions.md 对注释的要求(说明复杂配置与决策原因、避免冗余注释)共同构成"文档即代码"文化。
十一、验证与测试:把质量门槛前置
原准则:apply 前先跑terraform validate并审查terraform plan输出,尽早发现错误与意外变更;考虑落地自动化检查:CI 流水线、pre-commit hooks,强制执行格式化、lint 与基础验证。
推荐的本地工作流为:
# 1. 格式化 terraform fmt -recursive # 2. 语法与配置校验 terraform validate # 3. 静态风格检查(可选但推荐) tflint # 4. 审查变更 terraform plan # 5. 确认后应用 terraform applyterraform-azure.instructions.md 对 plan 的使用有一条重要纪律:运行terraform plan前必须先征求用户同意,且订阅 ID 应从ARM_SUBSCRIPTION_ID环境变量读取,绝不能硬编码进 provider 块。这一条也呼应了前文"用户指令优先级最高、变更需确认"的协作模式。
在 AVM 参与的场景,azure-verified-modules-terraform.instructions.md 给出了更完整的 CI 门槛,任何 PR 提交前都必须执行:
# 格式化(递归) terraform fmt -recursive # 语法校验 terraform validate # AVM 专属强制校验 ./avm pre-commit ./avm tflint ./avm pr-check这套组合拳将"格式化 → 语法 → 风格 → AVM 规范"四层门槛全部前置到本地与 CI,避免 PR 校验阶段才发现问题导致返工。对普通(非 AVM 贡献)项目,最小可行方案是 pre-commit 钩子中串联terraform fmt -check与terraform validate,再在 CI 中加入tflint与安全扫描(如 checkov/tfsec,见 terraform.instructions.md 的安全审计建议)。
十二、组合使用:从指令到生产级工作流
将以上 10 条准则串联起来,一份"现代 Azure Terraform 代码"的生成与交付闭环如下:
- 版本锁定:
required_version+required_providers固定 Terraform 与 azurerm 版本(准则 1); - 结构先行:按 main/variables/outputs/terraform/locals 分文件,超过规模即按资源类型拆分(准则 2);
- 模块化:优先引 AVM 官方模块,无 AVM 时按 AVM 风格自建并设计好变量/输出接口(准则 3);
- 参数化:全部输入走带类型+描述+默认值的变量,输出按需暴露,机密标记
sensitive(准则 4); - Provider 取舍:默认 azurerm,仅新特性场景用 azapi 并注释理由(准则 5);
- 依赖审查:不新增无关 provider/模块,确需引入先注释再确认(准则 6);
- 幂等验证:非生产环境连续 apply 两次,第二次必须零变更(准则 7);
- 状态治理:Azure Storage 远程后端 + 状态锁 + 状态文件永不入库(准则 8);
- 文档同步:terraform-docs 自动生成 + README 手工更新 + 架构图随变更维护(准则 9);
- 质量门槛:validate/plan 先于 apply,CI 与 pre-commit 强制 fmt、lint 与校验(准则 10)。
这 10 条准则并非孤立清单,而是与仓库内 terraform.instructions.md(通用约定)、terraform-azure.instructions.md(Azure 最佳实践)以及 azure-verified-modules-terraform.instructions.md(AVM 规范)形成互补的完整体系。理解它们的分工,就能在 Copilot 中按需组合出既现代、又可维护、且具备生产级质量保障的 Azure Terraform 代码。
【免费下载链接】awesome-copilotCommunity-contributed instructions, agents, skills, and configurations to help you make the most of GitHub Copilot.项目地址: https://gitcode.com/GitHub_Trending/aw/awesome-copilot
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考