凌晨两点四十,手机在枕头边震。
生产环境一台跑了三年的服务器重启之后起不来了。登上去看,配置文件里有个去年手改过的路径,谁改的、为什么改,问了一圈没人记得。日志翻到三点半,最后靠猜把服务拉起来了。
那一刻我特别清楚地意识到一件事——我们不是在运维,我们是在当一个记性不太好的保姆。
那台机器就是经典意义上的雪花服务器。独一无二,没法复制,谁碰谁心慌。

基础设施即代码治的是记忆和信任
很多人第一次听到基础设施即代码,脑子里浮现的是 Terraform、Ansible 这些名字。工具当然重要,但工具不是重点。
重点是什么?
是把“这台机器现在长什么样”这件事,从某个人的脑子里,挪到一份可以被 review、被 diff、被回滚的文件里。就这么朴素。
以前你要加一台机器,流程大概是:找运维大哥,大哥凭经验开一台,装环境,改配置,跑起来。下次再来一台,大哥可能记得,也可能记岔了。人一多,机器一多,差异就像雪球一样滚起来。
IaC 的思路反过来:先写清楚“我要什么样的机器”,再让工具去把它变出来。声明式,而不是命令式。这个区别很关键。
命令式:你先装 nginx,再改这个文件,再重启服务,再……一步错,步步错。
声明式:我只说我要 nginx 1.24 开着,剩下的工具自己算。它算出来的差异,就是它要执行的动作。
说实话,第一次看到 terraform plan 那行输出的时候,我是有点震撼的。它会告诉你,这次变更会新增 3 个资源、改 1 个、删 0 个。删 0 个。这三个字比任何文档都让人安心。
顺带说一句,Terraform 管的是资源的生命周期,创建、修改、销毁;Ansible 更偏向进去之后干了什么,装包、发文件、跑命令。两者不冲突,经常一起用。先把这条界线搞清楚,能省掉很多无谓的争论。

真上手之后才发现坑在别处

工具本身学起来不难,三天能写出能跑的东西。难的是后面那些。
第一个坑是状态漂移。有人半夜着急,直接在控制台上手改了一条安全组规则,没走代码。代码里没这条,真实环境里有。下次 apply,工具一看——这玩意儿不是我创建的,删了。恭喜,事故。
所以很多团队会立个规矩:控制台的写权限收紧,人只能读不能改。痛苦,但是有效。
第二个坑是密钥。早期我见过有人把数据库密码直接写在 .tf 文件里,然后推到了 Git。仓库还是 public 的。那次之后我大概有半个月,做梦都梦见告警。
现在比较正常的做法是代码里只放引用,真实值走密钥管理或者环境变量注入。CI 里做扫描,提交时先拦一道。
第三个坑说起来有点反直觉——模块化做过头。有人一上来就抽了七八层 module,变量传进去传出来,最后没人能看懂一台机器到底是怎么被创建出来的。这种抽象不是工程,是自嗨。
我自己的判断标准很简单:如果一个模块三个月内只被用过一次,那它就不该叫模块。
如果要开始 我会这样排顺序
不吹牛,落地这事儿跟团队规模关系很大。五个人的团队和五十个人的团队,节奏完全不一样。但有几件事我觉得是通用的。
先把最痛的那一块码化,别贪全。通常是网络或者一台标准应用机。跑通了再往外扩。
代码仓库和基础设施仓库分开。别混在业务代码里,两边的发布节奏根本对不上。
PR 流程必须走起来。基础设施的改动比业务代码的改动危险得多。业务代码崩了顶多回滚,基础设施改错了,可能连回滚的入口都没了。
还有一条,plan 的输出贴在 PR 里。让人肉眼看一遍到底要动什么。这个动作看着笨,但它拦下来的事故,比任何自动化检查都多。
再就是,别指望一步到位。我见过太多团队写了半年的 IaC,最后因为没人维护,代码比实际环境还旧,反而长成了新的技术债。
小步走。先让它有用,再让它好看。
毕竟工具是给人用的,对吧。