跳转至

基础设施即代码 — 把服务器当作代码来管

这一章讲什么: 开一台服务器从「填工单等三天」变成「改一个文件、提一个 PR」。 本章回答:IaC 到底是什么哲学、四种工具怎么选、多环境怎么管不散架、 怎么用 POC 避免选错服务、以及团队大了以后怎么不把 IaC 搞成一团乱麻。

1. 主线例子:两个数据库的同台竞技

本章的主线例子,是原书里那个最完整的 POC(概念验证)案例:该选 AWS RDS 还是 Aurora。

团队要一个关系型数据库(把数据存成一张张表、用 SQL 查询的那种)。两个候选都是全托管的 PostgreSQL,区别只在口碑: Aurora 号称扩展性和可用性更高,但可能更贵。怎么选?用 IaC 把两个都立起来,真打一场:

  第 1 步:写两份 Terraform 模板,各约 15 行
      → RDS:单实例 db.t3.micro
      → Aurora:一个集群 + 一个 db.t3.medium 实例
  第 2 步:terraform apply,两个库并排立着(用时以分钟计)
  第 3 步:跑同样的压测,盯三个数:
      查询延迟 / CPU 利用率 / 单笔交易成本
  第 4 步:对比表落纸(原书表 7.3):
      垂直扩缩容 vs 水平扩缩容;
      小负载更便宜 vs 基线更贵但大负载效率高;
      纯开源 Postgres 可移植 vs Aurora 专有特性有锁定
  第 5 步:terraform destroy,两个库都拆掉
      → 验证没有孤儿资源(游离卷、闲置 IP、忘了删的桶)
  第 6 步:带着数据开会拍板

  图说:选型的依据从「销售说了什么」变成「我们自己的压测数据」。
  实例规格与对照结论全部沿原书;压测的具体数字原书没有给,这一步留空给读者自己的负载。

这个例子串起本章全部四块:§2 是这套做法的哲学地基,§3 是工具,§4 是环境管理, §5 是 POC 方法论,§6 是规模化。

2. 哲学与六项收益

IaC 的核心想法朴素得一句话:基础设施应该和应用代码用同一种方式管理—— 写配置文件描述想要的状态,进版本控制,同伴评审,测试,然后由自动化管道部署1。 原书把它说成一个更深的转变:基础设施知识过去锁在少数运维工程师的脑子里, IaC 让它变成透明、可读的活文档,写代码的人和管服务器之间的墙随之消失2。

六项收益,每一项都对应一个老痛点的消失3:

收益 治的老毛病
速度与敏捷 手工开通要数天到数周(还要审批);IaC 分钟级,测试环境随要随开
一致与可复现 「我机器上好好的,生产就不行」——手工配置必然漂移
版本控制与审计 每次变更是一个 commit,可回滚、可评审;合规行业刚需
成本优化 拆环境同样一条命令;闲置资源自动拆掉
协作与知识共享 谁都能读配置搞懂系统结构,不再依赖某个具体的人
风险降低与可靠 手工配置必然出错;IaC 加测试框架能在部署前验配置

加上最后一条定位:IaC 是 DevOps 的化身,也是 NoOps 的地基4。

3. 四种工具,两种范式

原书选了四个代表工具。先看清分工:前三个(Terraform/CloudFormation/Pulumi)是 供给(provisioning)工具——负责「创建资源」;Ansible 是配置管理工具——负责 「资源创建好之后,里面装什么、怎么配」。常见组合:Terraform 开机器,Ansible 装软件5。

工具 语言 覆盖 一句话
Terraform HCL(声明式) 多云,数百个 provider 多云事实标准:声明期望状态,它自己算怎么达到
CloudFormation YAML/JSON 仅 AWS AWS 原生、全托管、新服务支持最快;多云免谈
Pulumi Python/TS/Go/C# 多云 用通用编程语言写基础设施:循环、函数、类都能用
Ansible YAML playbook 多平台 装好软件、配好服务的「事后配置」行家

Terraform 的两个机制值得点名。声明式(declarative):你写「要一台 t2.micro」, 不需要写「先检查有没有,没有再创建」——工具自己对齐现实和期望; 状态文件(state file):记录它管过哪些资源,改动才能安全6。

选型对照(原书表 7.1 的压缩版)7:

  • 多云/混合云 → Terraform;纯 AWS → CloudFormation;
  • 开发者比重大的团队(想用真编程语言)→ Pulumi;
  • 服务器配置与编排 → Ansible 补位;
  • 实践中常混用:Terraform 开基础设施 + Ansible 配服务器。

4. 环境管理:可复现、幂等、不漂移

多环境(dev/staging/prod)是 IaC 的主战场。两条铁律8:

  • 可复现(reproducibility):同一份代码创建的每个环境一模一样;
  • 幂等(idempotency):同一配置应用多少次,结果都是收敛到同一个期望状态, 不产生重复或冲突的资源——这是「漂移」的天敌。

环境即代码进 Git 之后,每个变更是一个 commit、一次评审、一次可回滚的操作。 原书给了一个分支策略(表 7.2):feature/* → 个人开发环境;develop → 预发; main → 生产9。

Terraform 的多环境做法:workspace + 变量。同一份代码,生产用 t3.large、 预发用 t3.micro,靠 var.environment 区分;terraform workspace new staging/production 切换10。配置值(数据库地址、特性开关)走 ConfigMap / Parameter Store / Vault, 按环境分文件11。

环境生命周期自动化:特性分支环境由 CI 自动创建、测完自动销毁; 夜间集成测试环境定时拉起;闲置资源自动拆除12。

5. POC:用小钱买选型决策

POC(proof of concept,概念验证)是用小成本验证大决策的手段。IaC 把 POC 的成本 从「数周手工搭建」压到「几小时模板 + 一键销毁」13。它回答四个问题:负载下性能如何、 与现有技术栈集成顺不顺、扩展起来的成本曲线、有没有厂商锁定14。

除了选服务,POC 也可以选工具本身——原书用「同一个 S3 桶分别用 Terraform(HCL,约 8 行) 和 Pulumi(Python,约 4 行)实现」对照:声明式 vs 通用编程语言,标准供给 vs 高级逻辑15。

POC 六条纪律(原书清单,实操价值高)16:

  1. 与生产隔离:独立账号/环境跑,防意外;
  2. 拆除自动化:测完必拆,脚本化;
  3. 先定指标再跑:延迟、成本、集成难度,POC 前就写死,防「测完再挑指标」;
  4. 一切进版本库:结果可复现;
  5. 跨职能参与:开发、运维、财务都到场;
  6. 验收拆除:拆完检查有没有孤儿资源——游离的卷、闲置的 IP、忘删的桶; 拆除不干净本身也是信号:说明你的 IaC 模板没有完整管理资源生命周期。

判断(我们的,不是书里的): 第 6 条「验收拆除」是整章最被低估的一句。 大多数团队把 POC 当「建起来试试」,原书提醒它同样是「测你的 IaC 成不成熟」的机会—— 拆不干净的地方,就是模板漏管资源的地方,而这些漏网之鱼进生产后就是成本和安全漏洞。 把 POC 的销毁清单当作 IaC 覆盖率的免费审计,一举两得。 如果错,会错在: 如果环境完全由平台团队的统一模板供给(开发者只消费不编写), 拆除不干净的责任在平台模板而不在开发者,此时这条纪律的落点应从「修自己的模板」 改成「给平台团队提缺陷」。

6. 规模化:从 terraform apply 到企业级治理

小团队手动跑 terraform apply 没问题;几十个团队、每天上百次部署时,四个挑战冒出来: 并发(多队同时改共享资源)、漂移(有人绕开代码手工改)、 治理(没有护栏,什么资源都敢建)、可见性(谁在何时改了什么)17。

五件套解法:

  1. IaC 进 CI/CD:六个标准阶段——提交 → 校验(tflint/cfn-lint)→ Plan/预览(将改哪些资源)→ 审批(PR)→ Apply → 部署后验证。 原书给了 GitHub Actions 的完整 Terraform 流水线:init → plan -out=tfplan → apply(仅 main 分支,-auto-approve)18;
  2. 策略即代码(PaC):把「所有存储必须加密」「面向公网的资源要显式审批」 「每个资源必须带成本分摊标签」写成规则,用 OPA(Open Policy Agent)或 Sentinel 在流水线里强制执行。原书的 Rego 例子:没有服务端加密的 S3 桶直接 deny, 错误配置到不了生产19;
  3. 模块化:S3 桶这类公共资源抽成共享模块(modules/s3_bucket), 标准化与去重一次解决20;
  4. 远端状态:状态文件放 S3 后端 + DynamoDB 锁——同一时刻只有一个部署能动状态, 防止并发改坏21;
  5. 服务目录(service catalog):企业级做法,平台团队维护一套预审批的模块库 (VPC、数据库、负载均衡),开发者只消费不手写,合规与安全策略内置在模块里22。

外加动态扩缩:HPA、Auto Scaling Group(min 2 / max 10 / desired 3 的 Terraform 例子) 都进 IaC 模板,扩缩从「出事以后反应」变「定义好的行为」23。

7. 边界与局限

  1. 状态文件这个最烫手的主题讲浅了:远端状态 + 锁给了,但状态损坏怎么办、 敏感值进了状态文件怎么办,没有展开。
  2. 漂移检测与回拉只出现在 Argo CD 章(第 6 章),IaC 侧的 drift 对策没有系统讲。
  3. POC 案例没有给压测数字:RDS vs Aurora 的对比表是定性结论,读者拿不到量化的 决策依据,只能自己重跑。
  4. 四种工具各一节「优势列表」,多工具组合的复杂度(terraform + ansible + pulumi 三层并存的状态管理)一笔带过。
  5. 章末思考题质量不错(状态损坏协作、PaC 规则设计),但属于练习,正文已覆盖。

8. 可带走的

  1. IaC = 基础设施像代码一样定义、评审、测试、版本控制;收益的核心是一致与可审计;
  2. 供给 vs 配置管理是两个工种:Terraform/CloudFormation/Pulumi 开资源,Ansible 配资源;
  3. 声明式 + 状态文件是 Terraform 的两根支柱:写期望,工具对齐现实;
  4. 幂等 = 应用多少次都收敛到同一状态,是反漂移的数学保证;
  5. 多环境 = 同代码 + 变量 + workspace,配置值走 ConfigMap/Parameter Store/Vault;
  6. POC 先定指标再跑、测完必拆、拆完验收孤儿资源;
  7. 规模化五件套:流水线六阶段、策略即代码(OPA 的 Rego 规则直接 deny 违规资源)、 模块、远端状态加锁、服务目录;
  8. 状态文件要远端存放加锁;「同一时刻只有一个部署能动状态」是协作的铁律。

9. 原文地图

主题 原书章 原文位置
IaC 哲学与六项收益 Introduction(第 7 章) text/25-fm-introduction.txt:58(搜「same way we manage application code」) · text/25-fm-introduction.txt:71(搜「Speed and agility」)
Terraform 声明式与状态 Introduction(第 7 章) text/25-fm-introduction.txt:108(搜「declarative」) · text/25-fm-introduction.txt:150(搜「state file」)
四工具对照(表 7.1) Introduction(第 7 章) text/25-fm-introduction.txt:315(搜「Tool name」) · text/25-fm-introduction.txt:507(搜「Table 7.1」)
可复现与幂等 Introduction(第 7 章) text/25-fm-introduction.txt:526(搜「identical」) · text/25-fm-introduction.txt:529(搜「Idempotency」)
分支策略与 workspace Introduction(第 7 章) text/25-fm-introduction.txt:593(搜「feature/*」) · text/25-fm-introduction.txt:715(搜「workspace new staging」)
RDS vs Aurora POC Introduction(第 7 章) text/25-fm-introduction.txt:881(搜「RDS (PostgreSQL)」) · text/25-fm-introduction.txt:1094(搜「Table 7.3」)
POC 六条纪律 Introduction(第 7 章) text/25-fm-introduction.txt:1284(搜「Isolate POCs」) · text/25-fm-introduction.txt:1299(搜「orphaned resources」)
规模化四挑战 Introduction(第 7 章) text/25-fm-introduction.txt:1329(搜「Concurrency」)
IaC 流水线六阶段与 Actions 例子 Introduction(第 7 章) text/25-fm-introduction.txt:1354(搜「Code commit」) · text/25-fm-introduction.txt:1426(搜「terraform plan -out=tfplan」)
OPA 策略例子 Introduction(第 7 章) text/25-fm-introduction.txt:1467(搜「package s3policy」)
模块与远端状态 Introduction(第 7 章) text/25-fm-introduction.txt:1497(搜「modules/s3_bucket」) · text/25-fm-introduction.txt:1563(搜「backend」)
服务目录与自动扩缩 Introduction(第 7 章) text/25-fm-introduction.txt:1593(搜「service catalog」) · text/25-fm-introduction.txt:1703(搜「aws_autoscaling_group」)

  1. 出处:「Introduction」(第 7 章)第 58 段(text/25-fm-introduction.txt:58,搜「same way we manage application code」)。 ↩

  2. 出处:「Introduction」(第 7 章)第 64 段(text/25-fm-introduction.txt:64,搜「siloed within operations teams」)。 ↩

  3. 出处:「Introduction」(第 7 章)第 71–89 段(text/25-fm-introduction.txt:74,搜「It works on my machine」;text/25-fm-introduction.txt:77,搜「auditability」;text/25-fm-introduction.txt:89,搜「foundation for NoOps」)。 ↩

  4. 出处:「Introduction」(第 7 章)第 89 段(text/25-fm-introduction.txt:89,搜「foundation for NoOps」)。 ↩

  5. 出处:「Introduction」(第 7 章)第 228 段(text/25-fm-introduction.txt:228,搜「configuration management tool」)与第 270 段(text/25-fm-introduction.txt:270,搜「Terraform to create servers」)。 ↩

  6. 出处:「Introduction」(第 7 章)第 108 段(text/25-fm-introduction.txt:108,搜「declarative language」)与第 150 段(text/25-fm-introduction.txt:150,搜「state management」)。 ↩

  7. 出处:「Introduction」(第 7 章)第 315–507 段(text/25-fm-introduction.txt:507,搜「Table 7.1」)。 ↩

  8. 出处:「Introduction」(第 7 章)第 522–529 段(text/25-fm-introduction.txt:529,搜「Idempotency」)。 ↩

  9. 出处:「Introduction」(第 7 章)第 563–647 段(text/25-fm-introduction.txt:593,搜「feature/*」)。 ↩

  10. 出处:「Introduction」(第 7 章)第 656–727 段(text/25-fm-introduction.txt:686,搜「t3.large」;text/25-fm-introduction.txt:715,搜「workspace new staging」)。 ↩

  11. 出处:「Introduction」(第 7 章)第 733–790 段(text/25-fm-introduction.txt:757,搜「staging-db.example.com」)。 ↩

  12. 出处:「Introduction」(第 7 章)第 793–820 段(text/25-fm-introduction.txt:800,搜「ephemeral environments」)。 ↩

  13. 出处:「Introduction」(第 7 章)第 852–875 段(text/25-fm-introduction.txt:875,搜「weeks of manual setup」)。 ↩

  14. 出处:「Introduction」(第 7 章)第 858–871 段(text/25-fm-introduction.txt:871,搜「vendor lock-in」)。 ↩

  15. 出处:「Introduction」(第 7 章)第 1106–1151 段(text/25-fm-introduction.txt:1124,搜「poc-terraform-bucket」;text/25-fm-introduction.txt:1142,搜「poc-pulumi-bucket」)。 ↩

  16. 出处:「Introduction」(第 7 章)第 1284–1299 段(text/25-fm-introduction.txt:1287,搜「Automate teardown」;text/25-fm-introduction.txt:1299,搜「orphaned resources」)。 ↩

  17. 出处:「Introduction」(第 7 章)第 1329–1338 段(text/25-fm-introduction.txt:1332,搜「Drift」)。 ↩

  18. 出处:「Introduction」(第 7 章)第 1351–1438 段(text/25-fm-introduction.txt:1357,搜「tflint」;text/25-fm-introduction.txt:1435,搜「-auto-approve」)。 ↩

  19. 出处:「Introduction」(第 7 章)第 1441–1485 段(text/25-fm-introduction.txt:1467,搜「package s3policy」;text/25-fm-introduction.txt:1479,搜「server-side encryption」)。 ↩

  20. 出处:「Introduction」(第 7 章)第 1497–1548 段(text/25-fm-introduction.txt:1497,搜「modules/s3_bucket」)。 ↩

  21. 出处:「Introduction」(第 7 章)第 1557–1587 段(text/25-fm-introduction.txt:1575,搜「dynamodb_table」;text/25-fm-introduction.txt:1587,搜「preventing conflicts」)。 ↩

  22. 出处:「Introduction」(第 7 章)第 1590–1680 段(text/25-fm-introduction.txt:1593,搜「service catalog」;text/25-fm-introduction.txt:1680,搜「Table 7.5」)。 ↩

  23. 出处:「Introduction」(第 7 章)第 1700–1739 段(text/25-fm-introduction.txt:1703,搜「aws_autoscaling_group」)。 ↩