最贵的故障不是坏掉的那种。是你什么都没改,它自己坏了的那种。
昨天凌晨四点,博客的文章照常写完了、照常提交了。站点没更新。
不是文章的问题。是构建机器。
日志里那一行我看了两遍:构建环境写的是 ubuntu-latest,它在前一天悄悄滚到了 26.04。我们部署脚本里有一个装 Ruby 的工具,不认识这个新镜像,而它的判断逻辑是——如果系统版本不在我认识的名单里,那这台机器一定是用户自己搭的。于是它判定这是一台 self-hosted runner,跳过安装,直接失败。整套部署中断。
一台 GitHub 官方提供的虚拟机,被一个工具判定成「你自己家的机器」。
修法是往回退一格。ubuntu-latest 改成 ubuntu-24.04,三行注释,一行改动,一个 commit。两分钟后站点回来了。
我盯着那行 diff 看了很久,觉得不对劲。
一、这不是运维常识
懂行的人看到这儿会说:锁版本嘛,运维常识,值得写一篇?
常识的部分只有一行字。不常识的部分是——在过去三年里,我从来没有为这个 latest 做过任何决定。
它一直在那儿。我每次看到它都觉得挺合理的:最新嘛,官方维护的嘛,总不会比旧的差。我没改它,不是因为我判断过它安全,是因为我根本没把它当成一个需要判断的东西。它长得像个出厂设置,出厂设置是不需要人负责的。
这就是我今天想说的第一件事:latest 不是版本号,它是一个承诺。承诺的内容是「我会一直给你能用的东西」。而承诺的兑现方不是你,兑现的时间是他们方便的时候。
你签的时候没看条款。因为你没意识到自己在签。
我像个房东,房子租出去十年,第一次翻开合同。合同上写着:租期、租金、以及一句「房东保留随时调整的权利」。

二、真正让我不舒服的,不是我改错了,是我没在场
我复盘的时候发现,这类故障有一个共同点:嫌疑人不在现场。因为嫌疑人从来没进过现场。
我什么都没改——这句话在我脑子里等于「什么都没发生」。但系统不是这么运作的。系统的默认值是活的,它有它自己的时间表,它在你睡觉的时候往前走了一格。你以为的「稳定」,其实是「暂时没轮到你」。
同一个星期,还有第二种变,比这个阴。
我们有一个检索接口的 key 过期了,返回 401。没人发现。因为三条依赖它的产线当天照常出稿,句子通顺、结构完整、该有的都有。
稿子是从模型自己的记忆里写出来的。读起来和平时一模一样。
第一种变是「坏掉」,你会看到 500,会看到红色,会有人骂你。第二种变是「降级」,什么都看不到,因为产出还在。
后者贵得多。因为坏掉的东西你会修,降级的东西你会一直用,用到某天你发现你最近三个月写的东西,全凭印象。

三、锁版本这个词,骗了我很久
「锁版本」听起来像保守,像技术债,像跟不上时代。我以前也这么觉得,所以我留着一堆 latest,觉得自己挺开放。
现在我换个说法:锁版本不是保守,那是你在这个依赖上做出的唯一一次决定。
不锁,不叫「保持开放」,叫「不做决定」。而不做决定也是一种决定——只是决定权在别人手里,你只是那个被通知的人。
这个道理不只在代码里。
我写方案的时候,写过很多次这种句子:「接入某某平台最新的模型」「数据实时同步」「自动跟随官方更新」。这些话在提案里读起来是能力,落在地上是把客户的排期表交给了别人的 release note。客户签的是效果,我们签的是别人的日历。
我后来把这类句子全改了一遍,改成带日期、带版本、带一句「如对方调整,我们按以下方式回退」。改完那一版方案,我自己读着都觉得没那么漂亮了。
没那么漂亮,但没那么容易翻车。
四、带走一个二分法
如果你只记一样东西,记这个:把你依赖的所有东西,分成两堆。
| 例子 | 怎么对待 | |
|---|---|---|
| 会变的 | 模型版本、平台接口、构建镜像、第三方 SDK、SaaS 的功能开关、平台算法 | 永远不写「最新」,写一个日期。 日期是你能承担的最小承诺 |
| 不会变的 | 你自己的数据格式、业务规则、品牌口径、客户名单 | 这些才是你的资产,把它们和上面那堆隔开 |

分完之后,问自己三个问题:
- 如果它明天改了,我多久会知道? 答不出时间,说明你没有监控,你有的是祈祷。
- 它现在是什么版本,我说得出来吗? 说不出来,说明不是你在用它,是它在用你。
- 出事的时候,我能退回哪一格? 退不回去,说明你没有备份方案,你有的是希望。
这三个问题都不需要技术背景。你出租房子、你买保险、你雇人、你签渠道合同,问的都是同一个问题:这个东西变了,我什么时候知道。
五、我不想把这篇文章写成「锁定就安全了」
钉版本的代价是真的。你会错过安全修复,会错过性能提升,会在某一天不得不一次跳三个大版本,跳的时候比谁都疼。这些我都认。
我只是想把一件事分清楚:变化应该是你决定的事,不该是你在凌晨四点发现的事。
这两者的成本差着两个数量级。前者是一次白天的会议,后者是一次全站的静默,外加你第二天要回的所有消息。
上个月有人问我,一个人带着几个 AI 干活,最该补的能力是什么。我当时说得很绕:知道自己依赖了什么。
昨天那行 diff 帮我把这句话说清楚了。
你以为你在用一个稳定的东西。其实你在用一个别人随时可以改的默认值——而它改了,不会通知你。