5自动化与平台工程

基础设施即代码

平台的声明式底座

IaCTerraformCrossplaneGitOps

🎯 AI 时代的学习建议:不要只读理论。理解这一章的设计动机(为什么需要这个概念?)和边界条件(什么情况下会失效?)。当 AI 生成的代码涉及这些概念时,你能判断它是否用对了场景。AI 能帮你总结内容,但无法替代你亲手阅读、思考、建立直觉的过程。

第5章 基础设施即代码

平台的声明式底座

章节导读

基础设施即代码(Infrastructure as Code,IaC)是平台工程的技术地基:没有 IaC,平台的自助服务就是无源之水——环境无法快速复制,资源无法程序化分配,策略无法自动执行,一切「点击即得」的承诺都无从谈起。本章从平台的视角重新审视 IaC:它不只是「用代码管理服务器」的运维技巧,而是平台能力的声明式底座、环境可复制性的保证、以及 GitOps 与策略即代码的技术前提。

IaC 的思想源头可以追溯到 2000 年代中期的配置管理革命。彼时,基础设施的变更靠人工登录服务器执行命令,「雪花服务器」(snowflake server)——每台机器都有独特的手工修改历史,无法复制、无法审计——是行业常态。2005-2010 年间,Puppet、Chef、CFEngine 等配置管理工具把「服务器的期望状态」表达为代码,开启了 IaC 的第一波浪潮(侧重操作系统与软件配置层)。2014 年 HashiCorp 发布 Terraform,把 IaC 推进到第二波浪潮:以声明式语言(HCL)描述云资源(网络、计算、数据库、DNS)的期望状态,由引擎负责计算差异并调和(reconcile),状态文件(state)记录现实与代码的映射。Terraform 的成功确立了现代 IaC 的三大支柱:声明式(说「要什么」而非「怎么做」)、版本化(代码进 Git,变更可追溯可回滚)、可重复(同一份代码在任何时候执行产生相同结果)。2018 年后,第三波浪潮出现:Pulumi 把 IaC 带入通用编程语言(TypeScript/Python/Go)时代;AWS CDK 提供高层抽象(constructs)编译为 CloudFormation;Crossplane 则提出了最激进的理念——用 Kubernetes 的 API 与控制器模式管理一切云资源,让 IaC 与 K8s 生态无缝融合。

在平台工程的语境下,IaC 的角色发生了质的转变:从「运维团队管理基础设施的工具」升级为「平台能力的实现机制」。这个转变有三个维度。第一,IaC 是自助服务的执行引擎:当开发者在门户点击「创建预览环境」,背后执行的是平台团队预先编写并测试过的 Terraform 模块或 Crossplane Composition——自助服务的每一个动作最终都落到某段 IaC 代码上;平台团队的核心工作之一就是把这些代码写得足够健壮、足够模块化、足够安全,让非专家的触发也能产生专家级的结果。第二,IaC 是环境一致性的保证:开发、测试、预发、生产环境的差异被压缩为「同一份代码 + 不同的变量文件」,「在我机器上能跑」与「在预发能跑但生产不行」这类环境漂移问题从根源上消除。第三,IaC 是策略即代码的作用对象:OPA/Conftest 校验 Terraform plan 的输出、Kyverno 校验 Crossplane 的资源清单——安全与合规检查在资源创建之前执行,「不合规的基础设施根本无法被创建」,这比事后审计强一个数量级。

IaC 与 GitOps 的关系是本章的另一个核心主题。GitOps 由 Weaveworks 在 2017 年提出,其四原则——声明式、版本化、自动拉取、持续调和——与 IaC 的理念天然契合,但 GitOps 增加了一个关键机制:以 Git 仓库为唯一事实源(single source of truth),由集群内的 agent(ArgoCD、Flux)持续对比 Git 声明与实际状态,自动修复漂移(drift)。传统 Terraform 工作流是「推模式」:CI 流水线执行 terraform apply 把变更推到基础设施;GitOps 是「拉模式」:变更合并进 Git,集群内 agent 拉取并调和。拉模式的优势在平台场景下尤为突出:不需要把云凭证交给 CI 系统(agent 使用集群内的工作负载身份)、漂移自动修复(有人手工改了控制台?agent 会改回来)、审计天然完整(Git 历史即变更历史)。Crossplane 的设计就是 GitOps 原生的:所有基础设施都是 K8s CR,ArgoCD/Flux 可以像管理 Deployment 一样管理数据库与网络。

模块化设计是 IaC 工程化的关键。原始的「一个 main.tf 管全部」模式在平台场景下不可持续:平台需要向数百个团队提供可复用的基础设施构件(一个标准的 VPC、一个生产级 RDS、一套监控栈),这些构件必须封装为带版本、带接口契约、带测试的模块。Terraform Module Registry、Crossplane Compositions、Terragrunt 的 DRY 分层都是模块化的不同实现。模块设计的核心权衡是「抽象层级」:模块暴露的参数越多越灵活,但使用者需要的知识也越多(抽象泄漏);参数越少越简单,但覆盖的场景越窄。平台模块的黄金法则是「策略参数化,实现封装化」——使用者可以选 size、选 tier、选 region,但不能改加密设置、不能改备份策略、不能改网络拓扑,因为这些是平台团队编码的组织策略。

本章还将覆盖 IaC 的测试与状态管理这两个工程深水区。IaC 测试的完整金字塔包括:静态分析(tflint、checkov 的规则扫描)、策略测试(Conftest/OPA 对 plan 输出的校验)、单元测试(模块接口的断言,如 terratest)、集成测试(在临时云账号中真实创建再销毁)、以及快照测试(plan 输出的 diff 审查)。状态管理则涉及远程后端(S3 + DynamoDB 锁)、状态隔离策略(按环境/按团队/按生命周期分 state)、以及最危险的操作——state 手术(手工修改状态文件)的规范。这些工程实践决定了 IaC 在平台规模下是「资产」还是「负债」。通过本章的学习,你将理解为什么 CNCF 平台白皮书把 IaC 列为平台的基础能力,以及平台团队应该如何设计 IaC 的分层架构:平台模块层(平台团队拥有)、组合层(把模块组装为可自助申请的能力)、应用层(业务团队的少量声明式配置)。

核心概念

  • IaC
  • Terraform
  • Crossplane
  • GitOps

要点精析

【IaC 的核心思想:声明式、版本化、可重复的深层含义】IaC 的三大支柱常被当作口号引用,但每根支柱都有深刻的工程含义。声明式(Declarative)的本质是「期望状态与调和循环」:用户描述目标(一个 3 节点的 K8s 集群、一个加密的 PostgreSQL),引擎负责计算当前状态与目标的差异并执行调和。这与命令式(Imperative)脚本的根本区别在于幂等性:命令式脚本执行两次可能创建两个资源或报错,声明式定义应用一百次结果相同——幂等性是自动化重试、故障恢复与持续调和的前提,也是 GitOps 的技术基础。声明式还带来「差异即变更」的审查模式:terraform plan 输出的 diff 精确展示了本次变更将修改什么,评审者审查的是「状态的变化」而非「操作的序列」,认知负荷显著降低。版本化(Versioned)的本质是「基础设施变更获得软件级的工程纪律」:每次变更是一个 commit,有作者、时间、消息、评审记录;出问题可以 git bisect 定位引入变更的 commit,可以 git revert 回滚;分支模型支持「基础设施变更的 CI 验证后再合并」。版本化还使基础设施成为「可分发的知识」:新团队不需要问老员工「生产数据库怎么配的」,读代码即可。可重复(Repeatable)的本质是「消灭雪花」:同一份代码 + 同一组变量,在任何时间、由任何人执行,产生相同的基础设施——这要求代码中不能有时间戳、随机数等不确定性来源(需要时用受控的 random provider 并把结果存入 state),不能依赖执行者的本地环境(所有工具版本用 .terraform-version 锁定)。三根支柱相互支撑:没有版本化,声明式定义的历史不可追溯;没有可重复性,版本化的代码也无法保证环境一致。平台视角的推论:IDP 的每个自助动作背后都应该是声明式、版本化、可重复的 IaC 执行——任何依赖「平台工程师手工操作控制台」的环节都是自助化的断点。

【IaC 工具生态:Terraform、Pulumi、Crossplane、CloudFormation 的定位与选型】四大主流工具各有清晰的定位。Terraform:HCL 声明式语言,provider 生态覆盖 3000+ 平台(所有主流云、K8s、SaaS 服务),模块系统成熟,社区最大;2023 年许可证从 MPL 转为 BUSL 引发社区分叉,OpenTofu 作为 Linux 基金会旗下的开源分支获得广泛关注——选型时需评估许可证风险与生态迁移成本。优势是心智模型简单、生态无敌;劣势是 HCL 表达力有限(复杂逻辑写起来别扭)、状态文件管理是运维负担。Pulumi:用通用语言(TypeScript、Python、Go、Java、C#)编写 IaC,完整的编程能力(循环、抽象、类型系统、包管理),状态管理兼容 Terraform 后端;适合工程能力强、需要复杂抽象的平台团队;劣势是「基础设施代码」与「应用代码」的边界模糊化可能带来过度工程,且不同语言项目的代码风格差异影响跨团队协作。CloudFormation:AWS 原生,无需额外状态管理(状态在 AWS 侧),新服务支持最快;但锁定 AWS、模板语法冗长(YAML/JSON)、变更集机制笨重,多云组织通常不用。Crossplane:把云资源建模为 K8s CRD,用 K8s 的控制器模式持续调和,天然 GitOps(ArgoCD 直接管理)、天然多租户(RBAC + namespace)、天然与平台其他能力集成(同一套 API 机制);Composition 机制让平台团队定义复合资源;劣势是生态较新、调试复杂(多层抽象:CR → Composition → Provider → 云 API)、非 K8s 中心的基础设施(如纯网络配置)用 Crossplane 表达别扭。平台选型经验法则:以 K8s 为中心的 IDP 优先考虑 Crossplane(统一 API 平面)+ Terraform/OpenTofu(Crossplane 覆盖不到的领域)组合;工程能力强的团队可评估 Pulumi 构建高层抽象;单 AWS 且规模小的组织 CloudFormation + CDK 是低摩擦选择。

【IaC 在平台中的角色:三层分工架构】平台语境下的 IaC 应按「谁拥有、谁使用」分为三层。第一层:平台基础层(Platform Foundation)——平台团队用 IaC 构建平台自身的底座:K8s 集群、网络拓扑、IAM 体系、监控栈、CI/CD 系统、密钥管理系统。这层代码的特点是变更频率低、爆炸半径大(改错了全平台瘫痪),因此需要最严格的评审与测试流程(强制双人评审、完整的集成测试环境、变更窗口管理)。第二层:平台能力层(Platform Capabilities)——平台团队把常见基础设施需求封装为可自助消费的「产品」:Terraform 模块(标准 VPC、生产级 RDS、Kafka 集群)或 Crossplane Compositions(XPostgreSQL、XRedis、XS3Bucket)。这层是平台价值的核心载体:模块的接口设计(暴露哪些参数)、默认值(编码哪些策略)、版本管理(如何演进)决定了自助服务的体验。业务团队消费这层的接口而不接触实现——正如消费者用电不需要懂电网。第三层:应用基础设施层(Application Infrastructure)——业务团队声明自己服务所需的基础设施:用哪些模块、什么规格、什么环境。这层的代码量应该很小(一个服务的 infra 目录通常只有几十行——引用模块 + 填参数),如果业务团队的基础设施代码动辄上千行,说明平台能力层的封装不足(业务团队在重复实现本应平台化的构件)。三层之间的接口契约至关重要:能力层对基础层的依赖(模块假设的网络布局、IAM 权限)要显式文档化;应用层对能力层的消费要通过稳定的模块版本接口(语义化版本 + 变更日志),平台团队承诺 N-1 版本的支持窗口。这种分层让 IaC 的复杂性各归其位:平台团队消化云 API 的复杂性,业务团队只面对领域化的简单接口——这正是「降低认知负担」在基础设施维度的实现。

【模块化设计:可复用基础设施模块的工程标准】平台级 IaC 模块的质量标准远高于个人脚本,需要满足六个工程要求。第一,接口最小化与语义化:模块的 input variables 控制在必要范围(一个数据库模块通常 8-15 个参数),参数命名用业务语义(size: small/medium/large)而非技术细节(instance_class: db.r6g.large),技术映射在模块内部完成——参数每多一个,使用者的认知负担与测试矩阵都指数增长。第二,策略内嵌:安全与合规要求硬编码在模块中而非暴露为参数——加密默认开启且不可关闭、备份保留期有最小值、公网访问默认禁止;需要例外的场景通过独立模块变体(如 module "public_alb")而非布尔开关实现,让例外显式且可审计。第三,版本化与变更日志:模块发布到内部 Registry,遵循 semver,每个版本附变更日志(新增参数、默认值变化、breaking change 与迁移说明);消费方锁定版本(version = "~> 3.2"),升级是显式决策。第四,输出契约:模块的 outputs 定义清晰的消费接口(数据库模块输出 endpoint、port、secret 引用——注意输出 secret 的引用而非明文),下游模块与监控注册依赖这些输出。第五,可测试性:模块附带完整的测试套件——变量校验测试(无效输入被拒绝)、plan 断言测试(给定输入产生期望的资源属性,用 terratest 或 terraform plan + jq 断言)、集成测试(在临时账号真实创建-验证-销毁)。第六,文档即代码:README 由 terraform-docs 从代码注释自动生成(避免文档与代码漂移),包含参数表、使用示例、架构说明与故障排查指南。模块的目录组织推荐「一个模块一个仓库」或 monorepo 下的独立目录 + CODEOWNERS,评审权限归平台团队,业务团队通过 issue/PR 提需求——模块是产品,产品需要产品经理式的维护。

【IaC 与 GitOps:拉模式的基础设施管理】GitOps 与 IaC 的结合有两种主要形态。形态一:ArgoCD/Flux 管理 Crossplane CR——所有基础设施声明为 K8s CR 存放在 Git,GitOps 控制器同步到集群,Crossplane 控制器调和到云。这是「全 K8s API 平面」的纯粹形态:基础设施与应用共用同一套声明、同步、调和、审计机制,平台团队的心智模型统一。形态二:GitOps 化的 Terraform——Git 仓库存放 Terraform 代码,专用控制器(如 Atlantis、TF-Controller/Galley、env0 的 agent)监听变更,自动执行 plan 并把结果评论到 PR(供人审查),合并后自动 apply。这种形态保留了 Terraform 生态,同时获得 GitOps 的「Git 为唯一事实源」特性。GitOps 拉模式对平台的三大价值。第一,凭证安全:推模式下 CI 系统需要持有云凭证(CI 被攻破 = 云账号被攻破);拉模式下调和 agent 运行在集群内,使用 IRSA/Workload Identity 绑定的最小权限角色,凭证不出云边界。第二,漂移检测与自愈:有人绕过流程在控制台手工创建/修改了资源?调和循环在下一个周期发现实际状态与 Git 声明不符,自动修复(或告警,取决于策略)——「控制台是只读的」从纪律要求变成技术现实。第三,审计与合规的自动化:Git 历史就是完整的变更审计日志(谁、何时、改了什么、谁批准的——PR 评审记录),合规审计从「翻工单系统 + 访谈」变成「导出 Git 日志」。实施 GitOps 的关键设计决策:仓库结构(按环境分目录还是按环境分仓库——推荐单仓库多环境目录,跨环境变更的原子性更好);同步策略(自动同步 vs 手动批准同步——生产环境推荐「PR 合并即批准,同步自动执行」,把审批前置到代码评审);健康判定(资源 Synced 不等于 Healthy,ArgoCD 的健康检查需要定制——一个 RDS 创建中是 Progressing,创建失败是 Degraded);灾难恢复(Git 仓库 + 状态后端的备份策略,以及「从 Git 完整重建一个环境」的演练——这是 GitOps 承诺的终极验证)。

【策略即代码:OPA、Kyverno、Sentinel 在 IaC 中的应用】策略即代码(Policy as Code)把安全、合规、成本、架构治理规则从文档变为可执行的校验,在 IaC 流水线中的位置决定了其效力。校验时机有三个层次,效力递增。层次一:IDE 实时反馈——开发者编写 Terraform 时,IDE 插件(如 checkov 的 VSCode 扩展)实时标注违规(「此安全组对 0.0.0.0/0 开放 22 端口」),修复成本最低(秒级)。层次二:PR 门禁——CI 流水线对 terraform plan 的 JSON 输出运行 Conftest/OPA 策略,违规则 PR 检查失败并评论具体违规项与修复指南;这是策略执行的主战场,覆盖所有变更。层次三:运行时准入——Kyverno/OPA Gatekeeper 在 K8s API Server 侧拦截不合规的 Crossplane CR 或资源清单,即使前两层被绕过(如直接 kubectl apply),违规资源也无法进入集群;这是最后防线。策略的组织方式推荐「策略库集中管理」:一个独立 Git 仓库存放全部 Rego 策略(按域分目录:security/、cost/、architecture/、compliance/),版本化发布,各业务仓库的 CI 通过 conftest --policy 拉取指定版本的策略库——策略更新一处生效全局,与黄金路径的模板升级机制同构。策略的分级执行同样重要:deny(阻断,用于安全底线与合规红线)、warn(警告不阻断,用于成本建议与架构偏好,输出到 PR 评论引导改进)——全 deny 的策略库会把开发者逼向绕过,全 warn 的策略库没有牙齿;成熟组织的比例大约是 30% deny / 70% warn,且 warn 策略在误报率稳定后逐步升级为 deny。策略本身也需要测试:每条 Rego 策略附带单元测试(opa test,覆盖通过/拒绝/边界用例),策略变更走 PR 评审——策略是代码,代码需要工程质量。Sentinel(HashiCorp 商业产品)与 CDK Aspects(AWS)是同类理念的其他实现,选型取决于工具链生态。

【IaC 的测试金字塔:从静态分析到混沌验证】IaC 测试的完整金字塔自底向上有五层。第一层,静态分析与 Lint:tflint(HCL 语法与 provider 规则)、terraform fmt(格式统一)、checkov/tfsec(内置数百条安全规则的扫描,如「S3 桶未加密」「RDS 公网可达」)——秒级反馈,拦截低级错误与已知安全反模式。第二层,策略测试:Conftest 对 plan 输出运行组织自定义策略(上一要点详述)——组织特有规则的校验。第三层,模块单元测试:terratest(Go 库)或 terraform plan + jq 断言——验证模块的接口行为:给定输入变量,plan 输出包含期望的资源与属性(「size=large 时实例类型为 db.r6g.2xlarge」「未指定 backup_window 时使用默认值」);这层测试让模块重构有安全网。第四层,集成测试:在临时云账号/订阅中真实执行 apply,验证资源真的能创建成功、属性符合预期、模块间依赖正确,测试完成后 destroy——成本高(真实云资源费用 + 20-40 分钟时长)但对模块发布必不可少;推荐用「每晚定时 + 发布前强制」的节奏运行,用临时账号与自动清理标签控制成本。第五层,端到端与混沌验证:通过 IDP 的自助接口(而非直接 terraform apply)触发完整流程(门户申请 → 工作流 → 模块执行 → 资源可用 → 目录登记),验证平台链路的完整性;进阶组织还会做「环境重建演练」——定期从零重建一套 staging 环境,验证 IaC 的完备性(没有藏在控制台里的手工配置),这是「可重复」支柱的终极检验。测试的分层执行策略:第一、二层跑在每个 PR(分钟级),第三层跑在模块仓库的 PR 与每日构建,第四层跑在模块发布流水线与每晚定时,第五层跑在平台的每周/每月演练——把慢测试放在低频高价值的节点,避免拖垮反馈速度。

【状态管理:IaC 最危险的资产】Terraform 类工具的状态文件(state)记录了「代码声明的资源」与「真实世界资源」的映射,是 IaC 体系中最敏感、最危险的组件。危险性的三个来源:其一,state 包含敏感信息——数据库连接串、密钥引用、资源 ID 都以明文或半明文存储,state 泄漏约等于基础设施蓝图泄漏;其二,state 损坏或丢失意味着「失明」——工具不再知道哪些资源是自己管理的,盲目 apply 可能重建资源(数据丢失)或产生孤儿资源(成本泄漏);其三,并发写冲突——两个流水线同时 apply 同一 state 会导致数据竞争与损坏。工程对策成套出现。远程后端 + 锁定:state 存储在 S3(开启版本控制与 SSE-KMS 加密)+ DynamoDB 锁(或 S3 原生锁),杜绝本地 state 与并发冲突;后端配置本身用 partial configuration 或 -backend-config 注入,避免凭证进代码库。状态隔离策略:按「爆炸半径 + 变更频率 + 团队边界」切分 state——推荐模式是「平台基础层一个大 state(低频高危,严格变更管理)+ 每个平台能力模块的实例独立 state(如每个团队的每个环境一个 state,用 terraform workspace 或目录结构隔离)」;单 state 资源数控制在几百以内(state 过大导致 plan 缓慢与锁竞争)。禁止 state 手术:手工 terraform state mv/rm/import 是高危操作,必须走「双人复核 + 操作前 state 快照 + 操作记录审计」的流程;平台化场景下应把 state 操作封装为受控的自助工具(带校验与审计),而非给工程师裸 CLI 权限。Crossplane 的状态模型不同:资源状态存在于 K8s etcd 中(CR 的 status 字段),由控制器持续维护,没有独立 state 文件——这消除了 state 管理负担,但把 etcd 的备份与恢复提升为同等重要的基础设施课题。无论哪种模型,「从备份完整恢复基础设施管理平面」的演练都应每半年执行一次——没演练过的备份等于没有备份。

【案例深析:Crossplane 用 K8s API 管理云资源】Crossplane 的架构与工作机制值得深入剖析,因为它代表了 IaC 与平台工程融合的最前沿。核心组件:Provider(如 provider-aws)是运行在集群中的控制器,封装了对特定云 API 的调用,把云资源暴露为 K8s CRD(如 rds.aws.crossplane.io/DBInstance);Composition 定义「复合资源(XR)到具体资源组合」的映射规则;XRD(CompositeResourceDefinition)定义平台自己的抽象 API(如 platform.acme.com/XPostgreSQL)。工作流程:开发者提交 XPostgreSQL CR → Crossplane 根据标签与 XRD 定义选择匹配的 Composition → Composition 的 patches 把 XR 的参数(size: medium)翻译为底层资源的属性(db.r6g.xlarge)→ 生成 RDS 实例、子网组、监控配置等具体 CR → provider-aws 控制器调用 AWS API 创建真实资源 → 状态持续写回 CR 的 status 字段。这个机制的平台价值:(1)统一的 API 平面——应用(Deployment)与基础设施(数据库、队列)用同一套 K8s 语义管理,ArgoCD 一个工具同步一切,RBAC 一套体系授权一切,开发者学习成本减半;(2)持续调和——云资源被手工修改后控制器自动改回(GitOps 漂移自愈延伸到云资源);(3)多租户原生——namespace + RBAC 天然隔离各团队的基础设施申请权限,配合 ResourceQuota 可以实现「基础设施配额」(每团队最多 3 个生产数据库);(4)组合即产品——Composition 是平台团队的产品工件,一个「生产级 PostgreSQL」Composition 编码了多可用区、加密、备份、监控、网络隔离的全部最佳实践,开发者消费 12 行 YAML。局限与对策:调试链条长(XR → Composition → MR → 云 API,任何一环失败都需要逐层排查)——对策是完善的事件与 condition 传播(Crossplane 1.15+ 大幅改进了错误信息)与平台侧的「申请状态」聚合视图;非 K8s 语义的资源(IAM 策略的复杂合并、账户级配置)表达别扭——对策是保留 Terraform 处理这些领域,Crossplane 与 Terraform 通过 Function(Crossplane 1.14+ 的扩展机制,可以在 Composition 中调用 Terraform)混合使用。CNCF 毕业项目的成熟度与 Upbound 的商业支持使其成为 2024 年后新建平台的主流选择之一。

【IaC 的组织实践:谁写、谁评审、谁负责】IaC 的技术实践必须配套组织实践才能规模化。角色分工遵循三层架构:平台基础层与能力层的代码由平台团队编写与评审(业务团队可以提 PR,平台团队把关合并);应用基础设施层由业务团队编写,但受双重约束——只能引用平台发布的模块(策略强制:CI 检查 module source 必须来自内部 Registry)与模块参数(策略校验参数合规)。评审机制的设计要点:基础设施 PR 的评审清单与应用代码不同,需要额外关注——plan 输出的 diff 审查(本次变更将修改/销毁哪些资源,销毁操作需要特别警惕)、状态影响(是否涉及 state 迁移)、爆炸半径(影响单服务还是共享基础设施)、回滚方案(变更失败如何恢复)。高危变更(生产网络、IAM、数据库引擎版本)实行「双人评审 + 变更窗口 + 值班 SRE 知情」的升级流程。责任模型:平台模块的质量责任归平台团队(模块 bug 导致的基础设施故障由平台团队主导修复与复盘),业务团队对自己填写的参数与组合方式负责(选了 small 规格导致容量不足是业务决策的后果)——责任边界的清晰是避免「平台背锅文化」或「业务甩锅文化」的关键。知识管理:每个平台模块的仓库包含 docs/ 目录(架构图、决策记录、故障案例),模块的重大变更在平台频道公告并附迁移说明;平台团队每月举办「基础设施办公时间」(office hours),业务团队可以咨询模块使用与特殊需求——特殊需求的累积是模块演进的输入(同一需求出现三次以上就应进入模块路线图)。这套组织实践的本质是把 IaC 从「个人技能」转化为「组织资产」:代码有主、变更有据、知识有传、责任有界。

代码示例

/* 示例 1:平台级 Terraform 模块——生产级 RDS PostgreSQL 的封装 */
/* 文件结构: modules/postgres/{main.tf,variables.tf,outputs.tf,README.md} */
/* variables.tf —— 接口最小化与语义化 */
variable "service_name" {
  description = "消费此数据库的服务名(用于命名与标签)"
  type        = string
  validation {
    condition     = can(regex("^[a-z][a-z0-9-]{2,40}$", var.service_name))
    error_message = "service_name 必须为小写字母数字连字符,3-41 位。"
  }
}
variable "size" {
  description = "容量档位: small(<100GB/低QPS) medium(<500GB) large(>500GB)"
  type        = string
  default     = "small"
  validation {
    condition     = contains(["small", "medium", "large"], var.size)
    error_message = "size 仅支持 small/medium/large 三档。"
  }
}
variable "environment" {
  description = "环境: dev/staging/prod,驱动备份与多可用区策略"
  type        = string
}
variable "team" {
  description = "owning 团队(成本分摊与告警路由)"
  type        = string
}
/* main.tf —— 策略内嵌:加密、备份、私有网络不可配置 */
locals {
  size_map = {
    small  = { instance = "db.r6g.large",  storage = 100 }
    medium = { instance = "db.r6g.xlarge", storage = 500 }
    large  = { instance = "db.r6g.2xlarge", storage = 2000 }
  }
  spec          = local.size_map[var.size]
  is_prod       = var.environment == "prod"
  backup_days   = local.is_prod ? 30 : 7
}
resource "aws_db_instance" "this" {
  identifier     = "${var.service_name}-${var.environment}"
  engine         = "postgres"
  engine_version = "15.4"
  instance_class = local.spec.instance
  allocated_storage = local.spec.storage
  /* 以下为平台策略,不暴露为参数 */
  storage_encrypted      = true
  multi_az               = local.is_prod
  backup_retention_period = local.backup_days
  publicly_accessible    = false
  deletion_protection    = local.is_prod
  skip_final_snapshot    = !local.is_prod
  db_subnet_group_name   = data.aws_db_subnet_group.platform_private.name
  vpc_security_group_ids = [aws_security_group.db.id]
  tags = {
    team        = var.team
    environment = var.environment
    managed-by  = "terraform"
    module      = "postgres@3.2.0"
  }
}
/* outputs.tf —— 输出引用而非明文 */
output "endpoint" {
  value = aws_db_instance.this.endpoint
}
output "secret_ref" {
  description = "凭据存放于 Secrets Manager,应用通过 IRSA 读取"
  value       = aws_secretsmanager_secret.db_creds.arn
}
解释:这个模块展示了平台级 IaC 的全部工程标准。接口设计:4 个必填/可选参数全部是业务语义(service_name、size、environment、team),validation 块在 plan 阶段就拒绝无效输入并给出中文错误说明——错误信息的质量决定自助体验(对比裸 AWS provider 的报错:晦涩的 API 错误码)。size 的 description 直接内嵌决策辅助信息(small 适合 <100GB/低 QPS),使用者无需查阅外部文档即可做出知情选择。策略内嵌是模块的灵魂:storage_encrypted、publicly_accessible=false、deletion_protection(生产强制)等安全属性硬编码,不暴露为变量——业务团队想创建不加密的数据库?接口上就不存在这个选项。环境驱动的策略分叉(is_prod 控制多可用区、备份期、删除保护、快照策略)把「生产与测试的差异化标准」编码为逻辑而非文档约定。size_map 的翻译层把业务档位映射为具体规格——未来实例族换代(r6g → r7g)只改模块一处,所有消费方在模块升级后自动获得新规格,这是「默认值集中管理」原则在 IaC 的体现。标签体系(team/environment/managed-by/module@version)支撑成本分摊、漂移检测与版本审计——module 标签记录消费时锁定的模块版本,安全事件时可以快速定位「哪些数据库用了带漏洞的模块版本」。输出契约只暴露 endpoint 与 secret 的 ARN 引用,凭据本体走 Secrets Manager + IRSA——应用拿密码的唯一途径是通过平台的密钥体系,明文密码在 IaC 层就不存在。
/* 示例 2:Conftest 策略——PR 门禁校验 terraform plan 输出 */
/* 文件: platform-policies/terraform/deny.rego */
package terraform.deny

import future.keywords.in

/* 规则 1: 禁止对公网开放 SSH/RDP */
deny[msg] {
  resource := input.resource_changes[_]
  resource.type == "aws_security_group"
  ingress := resource.change.after.ingress[_]
  ingress.from_port <= 22
  ingress.to_port >= 22
  cidr := ingress.cidr_blocks[_]
  cidr == "0.0.0.0/0"
  msg := sprintf("安全组 %s 对 0.0.0.0/0 开放 SSH(22)。请使用堡垒机或 SSM Session Manager。修复指南: https://platform.acme.internal/docs/network-access", [resource.address])
}

/* 规则 2: 生产环境数据库必须启用删除保护 */
deny[msg] {
  resource := input.resource_changes[_]
  resource.type == "aws_db_instance"
  resource.change.after.tags.environment == "prod"
  not resource.change.after.deletion_protection
  msg := sprintf("生产数据库 %s 未启用 deletion_protection。这是合规红线(SOC2 CC6.1)。", [resource.address])
}

/* 规则 3(warn 级): 资源销毁提醒 */
warn[msg] {
  resource := input.resource_changes[_]
  resource.change.actions[_] == "delete"
  msg := sprintf("警告: 本次变更将销毁 %s (%s)。请确认数据已备份且无下游依赖。", [resource.address, resource.type])
}

/* CI 中的调用方式: */
/* terraform plan -out=tfplan && terraform show -json tfplan > plan.json */
/* conftest test plan.json --policy platform-policies/terraform/ */
/* deny 规则命中 -> exit 1 -> PR 检查失败; warn 规则 -> PR 评论 */
解释:这份 Rego 策略是「策略即代码」在 IaC 流水线 PR 门禁层的标准实现。工作机制:terraform show -json 把二进制的 plan 文件转为结构化 JSON(resource_changes 数组包含每个资源的变更前后状态与动作类型),conftest 用 Rego 规则查询这个 JSON——策略校验的是「将要发生的状态变化」而非代码文本,因此无论资源用什么方式声明(原生 resource、模块、for_each 循环生成),策略都能覆盖,这是 plan 级校验优于文本级 grep 的根本原因。三条规则展示了策略的分级设计:规则 1(公网 SSH)是安全 deny——注意 msg 不只说违规,还给出替代方案(堡垒机/SSM)与文档链接,可操作的拒绝信息把开发者引向自助修复;规则 2(生产删除保护)是合规 deny,msg 中引用具体合规条款(SOC2 CC6.1)——把「为什么」写进拒绝信息能显著降低对抗情绪(开发者理解这是审计要求而非平台团队刁难);规则 3(资源销毁)是 warn 级——销毁操作可能是合法的(环境下线、资源替换),一刀切 deny 会阻碍正常工作,warn + PR 评论的方式保留人的判断,同时确保销毁动作被显式注意到。策略库的运营要点:规则按域组织(security/compliance/cost),每条规则附单元测试(tests/deny_test.rego,用 mock plan JSON 验证规则命中与不命中的场景);新规则上线先以 warn 模式运行两周评估存量违规与误报,稳定后升级 deny;策略库版本化发布,业务仓库 CI 锁定策略版本(conftest --policy 指向特定 tag),策略升级通过 PR 机器人推送——与黄金路径模板的升级机制完全同构,一套运营心智模型管理所有「平台知识工件」。
/* 示例 3:Crossplane Composition——平台复合资源的完整定义 */
/* XRD 定义平台抽象 API,Composition 定义其到 AWS 资源的实现 */
apiVersion: apiextensions.crossplane.io/v1
kind: CompositeResourceDefinition
metadata:
  name: xpostgresqls.platform.acme.com
spec:
  group: platform.acme.com
  names:
    kind: XPostgreSQL
    plural: xpostgresqls
  claimNames:
    kind: PostgreSQLClaim
    plural: postgresqlclaims
  versions:
    - name: v1alpha1
      served: true
      referenceable: true
      schema:
        openAPIV3Schema:
          type: object
          properties:
            spec:
              type: object
              properties:
                parameters:
                  type: object
                  properties:
                    size:
                      type: string
                      enum: [small, medium, large]
                      default: small
                    environment:
                      type: string
                      enum: [dev, staging, prod]
                  required: [environment]
              required: [parameters]
---
apiVersion: apiextensions.crossplane.io/v1
kind: Composition
metadata:
  name: xpostgresql-aws
  labels:
    provider: aws
spec:
  compositeTypeRef:
    apiVersion: platform.acme.com/v1alpha1
    kind: XPostgreSQL
  resources:
    - name: db-instance
      base:
        apiVersion: rds.aws.upbound.io/v1beta1
        kind: Instance
        spec:
          forProvider:
            engine: postgres
            engineVersion: "15.4"
            storageEncrypted: true
            publiclyAccessible: false
            region: ap-southeast-1
            dbSubnetGroupNameSelector:
              matchLabels:
                platform.acme.com/subnet-group: private
      patches:
        - fromFieldPath: spec.parameters.size
          toFieldPath: spec.forProvider.instanceClass
          transforms:
            - type: map
              map:
                small: db.r6g.large
                medium: db.r6g.xlarge
                large: db.r6g.2xlarge
        - fromFieldPath: spec.parameters.environment
          toFieldPath: spec.forProvider.tags[0].value
          policy:
            fromFieldPath: Required
        - fromFieldPath: metadata.labels[platform.acme.com/team]
          toFieldPath: spec.forProvider.tags[1].value
        - type: CombineFromEnvironment
          toFieldPath: spec.forProvider.identifier
          combine:
            variables:
              - fromFieldPath: metadata.labels[platform.acme.com/service]
              - fromFieldPath: spec.parameters.environment
            strategy: string
            string:
              fmt: "%s-%s"
    - name: backup-policy
      base:
        apiVersion: rds.aws.upbound.io/v1beta1
        kind: Instance
        spec:
          forProvider:
            backupRetentionPeriod: 7
      patches:
        - fromFieldPath: spec.parameters.environment
          toFieldPath: spec.forProvider.backupRetentionPeriod
          transforms:
            - type: map
              map:
                dev: 7
                staging: 14
                prod: 30
解释:这个 XRD + Composition 组合是 Crossplane 平台化 IaC 的完整形态,与示例 1 的 Terraform 模块实现同等能力但机制不同。XRD(CompositeResourceDefinition)定义平台自己的 API:group/names 声明了 XPostgreSQL 这个集群级复合资源与 PostgreSQLClaim 这个 namespace 级申请资源(claim 机制是多租户的关键——业务团队在自己 namespace 里提交 Claim,无权也无需接触集群级资源);openAPIV3Schema 定义参数接口(size 枚举 + environment 必填),K8s API Server 在提交时即完成校验——参数校验免费获得了 K8s 的全部机制(kubectl explain、OpenAPI 文档、准入校验)。Composition 的 patches 是「翻译层」的核心:map transform 实现档位到规格的翻译(与 Terraform 模块的 size_map 同构);CombineFromEnvironment 策略把多个来源字段(服务名标签 + 环境参数)组合为数据库标识符——注意标签来自 Claim 提交时平台 webhook 自动注入的 team/service 标签,开发者无需手填;backup-policy 资源展示「环境驱动策略」:dev 7 天、staging 14 天、prod 30 天的备份策略由 environment 参数自动决定。与 Terraform 模块的关键差异:(1)无 state 文件——资源状态持续存在于 CR 的 status 中,由控制器调和,消除了 state 管理的全部负担与风险;(2)持续调和而非一次性 apply——有人在 AWS 控制台改了备份策略?控制器下个周期改回来,GitOps 漂移自愈延伸到云资源;(3)申请即 K8s 对象——PostgreSQLClaim 天然获得 RBAC(哪个团队能在哪个 namespace 申请)、ResourceQuota(每团队最多几个生产库)、审计(K8s audit log)的全部多租户机制。调试建议:kubectl describe postgresqlclaim 查看 conditions(Claim 是否 Bound)、kubectl get xpostgresql -o yaml 查看 XR 状态、再看具体 MR(managed resource)的 conditions 定位云 API 错误——三层逐层下钻是 Crossplane 排障的标准路径。
/* 示例 4:GitOps 化的基础设施仓库结构与 ArgoCD ApplicationSet */
/* 仓库结构: */
/* infra-gitops/ */
/*   platform/            平台基础层(集群、网络、IAM)*/
/*     clusters/ */
/*       prod-ap-southeast-1/ */
/*       staging-ap-southeast-1/ */
/*     shared-services/   监控栈、Vault、CI runners */
/*   capabilities/        能力层发布的复合资源定义 */
/*     compositions/ */
/*   teams/               应用基础设施层(按团队分目录)*/
/*     payments/ */
/*       claims/ */
/*         orders-db.yaml       (PostgreSQLClaim) */
/*         events-topic.yaml    (KafkaTopicClaim) */
/*     growth/ */
/* ApplicationSet: 自动为每个团队目录生成 ArgoCD Application */
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
  name: team-infrastructure
  namespace: argocd
spec:
  generators:
    - git:
        repoURL: https://github.com/acme/infra-gitops
        revision: main
        directories:
          - path: teams/*
  template:
    metadata:
      name: "infra-{{path.basename}}"
    spec:
      project: team-infra
      source:
        repoURL: https://github.com/acme/infra-gitops
        targetRevision: main
        path: "{{path}}"
      destination:
        server: https://kubernetes.default.svc
        namespace: "team-{{path.basename}}"
      syncPolicy:
        automated:
          prune: true
          selfHeal: true
        syncOptions:
          - CreateNamespace=true
          - ApplyOutOfSyncOnly=true
        retry:
          limit: 5
          backoff:
            duration: 30s
            factor: 2
解释:这个示例展示基础设施 GitOps 仓库的组织方式与自动化同步机制,两者共同构成「拉模式 IaC」的运行时。仓库结构的三层目录直接映射 IaC 的三层分工架构:platform/ 是平台基础层(变更低频高危,单独的 ArgoCD project 施加更严格的同步策略——生产集群目录可配置为「手动同步 + 变更窗口」);capabilities/ 存放 Composition 与 XRD 定义(平台团队发布的能力目录);teams/ 是应用基础设施层,按团队分目录——目录即边界,CODEOWNERS 文件把 teams/payments/ 的评审权分配给 payments 团队(业务团队自己的基础设施自己评审,平台团队只评审 capabilities/ 与 platform/),权限模型与目录结构同构。ApplicationSet 的 git directory generator 自动发现 teams/* 下的每个目录并生成对应的 ArgoCD Application——新团队入驻平台时,平台脚手架自动创建 teams/<team>/ 目录,ApplicationSet 在下一个同步周期自动开始管理它,零人工配置。syncPolicy 的三个设置各有深意:automated + prune 保证 Git 删除的资源在集群中同步删除(Git 是唯一事实源的完整语义);selfHeal: true 开启漂移自愈——有人 kubectl edit 了某个 Claim?30 秒内被改回 Git 声明的状态;ApplyOutOfSyncOnly 只对有差异的资源执行 apply,大仓库下显著降低 API Server 压力。retry 与指数退避处理云 API 的瞬时故障(RDS 创建中的 throttling)。这个架构下的完整变更流:开发者修改 teams/payments/claims/orders-db.yaml(如 size: small → medium)→ PR 触发 CI(Conftest 策略校验 + plan 预览评论)→ 评审合并 → ArgoCD 检测到差异 → 自动同步 → Crossplane 调和 → RDS 实例规格变更 → status 回写 → 门户显示完成。全程无人工登录任何系统,Git 历史即完整审计日志。
/* 示例 5:terratest 模块单元测试——平台模块的质量安全网 */
/* 文件: modules/postgres/test/postgres_test.go */
package test

import (
    "testing"
    "github.com/gruntwork-io/terratest/modules/terraform"
    "github.com/stretchr/testify/assert"
)

/* 测试 1: plan 级断言——size 参数正确翻译为实例规格 */
func TestSizeMapping(t *testing.T) {
    cases := map[string]string{
        "small":  "db.r6g.large",
        "medium": "db.r6g.xlarge",
        "large":  "db.r6g.2xlarge",
    }
    for size, expectedClass := range cases {
        t.Run(size, func(t *testing.T) {
            opts := &terraform.Options{
                TerraformDir: "../",
                Vars: map[string]interface{}{
                    "service_name": "test-svc",
                    "size":         size,
                    "environment":  "dev",
                    "team":         "platform",
                },
                /* plan-only: 不创建真实资源,秒级完成 */
                NoColor: true,
            }
            plan := terraform.InitAndPlan(t, opts)
            json := terraform.PlanOutputJson(t, opts, plan)
            assert.Contains(t, json, expectedClass)
        })
    }
}

/* 测试 2: 策略内嵌验证——加密与私有访问不可绕过 */
func TestSecurityDefaultsAreImmutable(t *testing.T) {
    opts := &terraform.Options{
        TerraformDir: "../",
        Vars: map[string]interface{}{
            "service_name": "test-svc", "size": "small",
            "environment": "prod", "team": "platform",
        },
    }
    planJson := terraform.InitAndPlanAndShow(t, opts)
    /* 断言 plan 中 storage_encrypted=true, publicly_accessible=false, */
    /* deletion_protection=true(prod 环境)——这些值没有对应变量,  */
    /* 测试保证未来重构不会意外把它们暴露为可配置项 */
    assert.Contains(t, planJson, "\"storage_encrypted\": true")
    assert.Contains(t, planJson, "\"publicly_accessible\": false")
    assert.Contains(t, planJson, "\"deletion_protection\": true")
}

/* 测试 3: 输入校验——非法 service_name 被拒绝 */
func TestInvalidNameRejected(t *testing.T) {
    opts := &terraform.Options{
        TerraformDir: "../",
        Vars: map[string]interface{}{
            "service_name": "INVALID_NAME!", "size": "small",
            "environment": "dev", "team": "platform",
        },
    }
    _, err := terraform.InitAndPlanE(t, opts)
    assert.Error(t, err)
    assert.Contains(t, err.Error(), "小写字母数字连字符")
}
解释:terratest 单元测试是平台模块重构与演进的安全网,三个测试分别守护模块的三类契约。TestSizeMapping 守护「接口契约」:size 参数到实例规格的翻译表是模块对使用者的公开承诺,表驱动测试遍历全部档位,任何翻译错误(如升级实例族时漏改一档)在 CI 即被捕获;使用 plan-only 模式(不 apply)使测试秒级完成,可以跑在每个 PR 上。TestSecurityDefaultsAreImmutable 是最有价值的测试——它守护「策略内嵌」这一设计决策本身:断言 plan 输出中加密、私有访问、删除保护的值为期望状态,且注释点明了深层意图:这些属性没有对应的 input variable,测试保证未来的维护者在重构时不会「顺手」把它们参数化(平台模块最常见的腐化路径就是「应业务团队要求」把安全属性开放为参数,然后某个团队把它关掉了)。把架构决策固化为测试断言,是「决策即代码」的高级实践。TestInvalidNameRejected 守护「输入校验契约」:非法输入必须被拒绝且错误信息可读——注意断言检查的是中文错误消息的内容,这意味着错误信息本身也是被测试保护的接口(随意修改提示文案会让测试失败,提醒维护者错误信息是用户体验的一部分)。这三个测试都不需要真实云资源(全部基于 plan),成本近零;配套的集成测试(真实 apply-verify-destroy)则跑在每晚定时任务与模块发布流水线上,用临时账号与 AutoTag 清理策略控制成本。模块的 CI 完整序列:fmt check → tflint → checkov 安全扫描 → terratest 单元测试 → conftest 策略测试 → (发布时)集成测试——五层门禁保证进入内部 Registry 的每个模块版本都经过完整质量验证。

实验笔记

【实验目标】本实验构建一个「微型平台 IaC 栈」:用 Terraform/OpenTofu 编写一个平台级模块,用 Conftest 实施策略门禁,用完整的 CI 序列验证质量,最后(可选)用 Crossplane 实现同等能力并对比两种机制。通过实验你将亲身体验「平台团队如何把云资源封装为可自助消费的产品」。预计耗时 5-7 小时。

【环境准备】本地安装:Terraform 或 OpenTofu(brew/apt 安装)、conftest、tflint、checkov(pip install)、Go 1.21+(运行 terratest,可选)、Docker。云环境三选一:(A)真实云账号的免费层(AWS Free Tier / GCP 试用——注意实验结束务必 destroy 并检查残留资源);(B)LocalStack(Docker 运行 localstack/localstack,模拟 AWS API,零成本零风险,推荐首选);(C)仅 plan 模式(不 apply,只验证 plan 输出与策略——最低配置)。进阶部分需要 kind 集群 + Crossplane helm chart + provider-kubernetes(用 K8s 资源模拟云资源,无需真实云账号)。

【步骤一:编写平台模块(120 分钟)】实现一个「标准 Web 应用环境」模块(modules/webapp-env/),封装:一个「数据库」(LocalStack 模式下用 aws_db_instance,纯 plan 模式亦然)、一个 S3 存储桶(强制加密 + 版本控制 + 公共访问阻断)、必要的 IAM 角色(最小权限:应用只能读写自己的桶)。要求:(1)接口参数不超过 6 个(service_name、size、environment、team 等),全部带 validation 与中文 description;(2)策略内嵌——加密、公共访问阻断、生产删除保护硬编码,不暴露为参数;(3)size 三档翻译表;(4)标准标签集(team/environment/managed-by/module@version);(5)outputs 输出 endpoint 与桶名,不输出任何凭据明文;(6)用 terraform-docs 生成 README。完成后运行 terraform fmt、tflint、checkov 三件套,修复全部告警。

【步骤二:策略门禁(90 分钟)】编写 conftest 策略库(policies/terraform/):至少 4 条规则——deny:S3 桶未启用版本控制;deny:生产环境资源缺少 team 标签(成本分摊依赖);deny:安全组对公网开放高危端口;warn:任何资源销毁操作。每条规则附 opa test 单元测试(构造命中与不命中的 mock plan JSON 各一)。验证流程:terraform plan -out=tfplan && terraform show -json tfplan > plan.json && conftest test plan.json --policy policies/terraform/;先故意在模块中制造违规(注释掉 versioning 配置)确认 deny 生效且错误信息包含修复指引,再恢复确认通过。

【步骤三:测试与 CI 序列(90 分钟)】(Go 环境可用时)为模块编写 3 个 terratest 测试:size 翻译表断言、安全默认值不可绕过断言、非法输入拒绝断言(参考本章代码示例 5 的结构);无 Go 环境时用 shell + jq 实现等价断言(terraform show -json | jq 查询资源属性)。然后编写一个 GitHub Actions 工作流(或本地 Makefile)串联完整 CI 序列:fmt → tflint → checkov → plan → conftest → 单元测试,任何一步失败即终止。在 LocalStack 模式下补充集成测试:apply → 用 aws cli 验证资源真实属性(桶加密确实开启)→ destroy → 验证清理完整。

【步骤四(进阶):Crossplane 对照实现(120 分钟)】在 kind 集群安装 Crossplane 与 provider-kubernetes,定义 XWebappEnv 的 XRD(参数与 Terraform 模块一致)与 Composition(用 Kubernetes 资源模拟:ConfigMap 代表数据库配置、Secret 代表凭据、PVC 代表存储)。提交一个 Claim,观察:kubectl get claim 的状态流转(Pending → Bound)、kubectl describe 的 conditions、修改 Claim 参数后控制器的自动调和、直接 kubectl edit 底层资源后 selfHeal 的漂移修复(若配置了 ArgoCD)。撰写一页对比笔记:state 管理差异、漂移处理差异、多租户机制差异、调试体验差异、各自最适合的场景。

【检查清单】(1)模块通过 fmt/tflint/checkov 零告警;(2)参数 ≤6 个且全部有 validation 与决策辅助 description;(3)4 条 conftest 规则全部有单元测试且 deny/warn 分级正确;(4)CI 序列完整可重复运行,故意制造的违规被正确拦截;(5)(LocalStack 模式)集成测试完成 apply-verify-destroy 全循环且无资源残留;(6)(进阶)Crossplane Claim 状态流转正常且漂移自愈演示成功;(7)对比笔记覆盖四个差异维度。

【进阶挑战】(1)把模块发布到「内部 Registry」:用 Git tag 打版本(v1.0.0),另一个消费仓库通过 source = "git::https://...//modules/webapp-env?ref=v1.0.0" 引用,演示版本锁定与升级流程;(2)实现「模块升级机器人」:脚本对比消费方锁定版本与最新版本,自动生成升级 PR(附 CHANGELOG 摘要);(3)为策略库增加成本规则:warn 级检查 large 档资源是否有对应的成本中心标签,体验 FinOps 策略化;(4)用 Terragrunt 重构消费侧:把 environment/team 等公共变量提取到层级配置,体会 DRY 分层与「每环境独立 state」的隔离策略。

延伸阅读

  • 《Terraform: Up & Running》(Yevgeniy Brikman,O'Reilly 第 3 版):Terraform 工程实践的最系统教材,覆盖状态管理、模块设计、测试(terratest 作者的书)与团队协作模式。第 4-6 章关于状态隔离与模块化的论述直接对应本章的平台三层架构;书中「Terraform 反模式」清单是评审基础设施 PR 的实用参考。
  • Crossplane 官方文档(docs.crossplane.io):重点精读 Concepts 部分的 XRD、Compositions、Claims 三篇与 Functions 扩展机制文档。Quickstart 提供 provider-kubernetes 的零云账号动手路径(本章实验步骤四的官方版本);Troubleshooting 指南总结了 CR 状态排查的标准路径,是平台团队支持文档的范本。
  • OpenTofu 项目文档与发布公告(opentofu.org):了解 Terraform 许可证变更(MPL → BUSL)后的社区分叉现状。OpenTofu 由 Linux 基金会托管,兼容 Terraform 语法与 provider 生态,并率先实现了 state 加密等特性——平台选型时应跟踪两者的特性差异与生态兼容性演进。
  • 《Infrastructure as Code》(Kief Morris,O'Reilly 第 2 版):IaC 方法论的奠基之作,超越具体工具阐述原则——不可变基础设施、声明式与命令式的取舍、持续交付基础设施的流水线设计。第 2 版的「云原生基础设施」章节讨论了 K8s 时代 IaC 的形态演变,是理解 Crossplane 类工具的思想背景。
  • ArgoCD 官方文档的 ApplicationSet 与 Sync Policy 章节:GitOps 运行时的权威参考。ApplicationSet 的六种 generator(git directory、list、cluster 等)覆盖了基础设施仓库自动化的全部常见模式;Sync Waves 与 Hooks 文档解释了复杂依赖(先网络后集群再服务)的编排方法。
  • OPA/Conftest 官方文档与《Policy as Code》相关 CNCF 白皮书:Conftest 的 Rego 入门教程 + 对 plan/manifest 等多种输入的测试方法;CNCF 的策略即代码实践文档汇总了 Kyverno、Gatekeeper、Conftest 的选型对比。配合本章代码示例 2 动手编写策略是掌握 Rego 的最快路径。
  • Atlantis 与 TF-Controller(Galley)文档:GitOps 化 Terraform 的两种主流实现。Atlantis 的 PR 工作流(plan 评论 → approve → apply)是团队协作模式的经典设计;TF-Controller 则把 Terraform 作为 K8s CR 管理,与 Crossplane 共存于同一 GitOps 体系——两者的架构差异反映了「推模式改良」与「拉模式原生」的路线分野。
5/12基础设施
0%