☁️ 第四章 构建云服务的技术
📄 一句话概括

【不可变基础架构】是一条纪律:机器跑起来之后不再改它,要改就改镜像、重建一台——配套的做法叫【基础设施代码化】(IaC),把环境写成代码;这一套之所以要存在,是因为手改过的机器会慢慢变得各不相同,最后没人说得清线上到底是什么状态。

📝 本节和前面几节的关系

上一节(4-7)讲了声明式:你说想要什么,系统一直让它保持那样。这一节把同一个思路推到基础架构这一层:连机器本身也不再去【修】,而是【换】。

它是前面几节的自然结果——容器(4-6)本来就是一个【换掉比修好更便宜】的东西,而虚拟化(4-4)让【重建一台】只要几分钟。两件事凑齐,才让【不修只换】从一种理想变成一种可行的纪律。

一、要解决的问题:配置漂移

先看后果,再讲做法。

服务器跑起来之后,人总会去动它:打补丁、改配置、装个工具、临时调个参数排查故障。每一次动手,这台机器和【标准状态】就远了一点。 动了几十次、换过几拨人之后:

现象 后果
每台机器的配置都不一样 出问题的那台无法复现
说不清线上到底跑着什么版本 审计答不上来、合规过不了
大部分机器没打过某个补丁 漏洞长期存在,且没人知道范围
有机器已经没人用,还在计费 成本悄悄漏掉

这些现象有一个统一的名字:配置漂移。 它不来自任何一次错误的操作——每一次操作单独看都是合理的,漂移是它们叠加的结果。

二、两个做法,一个思路

教材把这两件事放在一起讲,因为它们是一套的:

做法 说的是什么 落地成什么
不可变基础架构 机器不做原地修改,要改就重建 一切都是镜像,改了镜像就重建
基础设施代码化(IaC) 环境的定义写成代码,而不是操作记录 机器、网络、权限都用文件描述

为什么必须两个一起:

所以这套纪律的完整表述是:环境的定义放在代码里(版本管理,可评审、可回滚),每次变更都通过【改代码 → 出新版本 → 整体重建】来完成,而不是登录上去改。

三、它带来的三个变化

变化 具体表现
故障处理变了 不再【登录上去修】,而是【先换掉,再离线查这台坏的】
环境变得可复制 测试环境可以从同一份代码重建,和生产完全一致
变更变得可回滚 回滚 = 用上一个版本的代码重建,不依赖人的记忆

第一条是最反直觉也最有效的一条:机器出问题时的第一反应从【救它】变成【换掉它】。这样服务恢复的时间和故障原因完全解耦——不需要先搞清为什么坏,就能先恢复。原因慢慢查,业务先回来。

四、动手 Demo:漂移查出来有多少台

看到什么算成功:

==================================================================================================
【Demo 8】不可变基础架构:不修机器,换机器
==================================================================================================
  可变做法:服务器跑起来之后,登录上去改配置、打补丁、装东西。
  不可变做法:配置写进代码,产出镜像;要改就重出一版镜像、重建机器。

  先看可变做法半年之后会发生什么(100 台服务器):

    情况                          台数      说明
    ----------------------------------------------------------------------------------------
    与基线完全一致                41 台     一次都没手工动过
    少打一个补丁                  27 台     当时节点在维护,跳过了
    配置文件被临时改过            18 台     为了排查故障改了没改回来
    多装了一个测试包              9 台      试完忘了卸
    已下线但仍在计费              5 台      没人记得它还在跑
    ----------------------------------------------------------------------------------------
    100 台里只有 41 台是【标准状态】,其余 59 台各不相同。
    这 59 台就是【配置漂移】,故障复现不了、审计答不上来的根源。

  不可变做法把这件事变成:改代码 → 出新镜像 → 整套重建。
  手工改机器这条路直接堵死(改了下一次重建就没了)。

  基础设施代码化(IaC)的时间账:
    手工建 50 台环境(含 IP、安全组、负载均衡):约 40 小时
    写成代码后首次执行:约 20 分钟
    以后每天重建一次(做测试用):每次 20 分钟,不需要人守着

  带来一个额外好处:环境本身进了版本管理,能回滚、能评审。

读结果:

30 秒实验

找一台你能登录的服务器(或者打开云控制台的某一台实例详情页),做三件事:

  1. 看它的【创建时间】——已经运行了多久。
  2. 看有没有【从模板创建】或【从快照重建】的入口。
  3. 想一个问题:如果这台机器现在坏了,你要多久才能让一台一模一样的新机器跑起来?

做完这个你会得到一个很实际的判断:如果答案超过半小时,说明这台机器的状态只存在于它自己身上——那它就是【不可替代】的,而不可替代的机器,是运维最大的负担来源。

常见误区

  1. 错误:不可变的意思是机器永远不会变。——纠正:它是【不做原地修改】,不是【永不更新】。 变化的路径是【改代码 → 出新镜像 → 换成新机器】——变化一直在发生,而且比以前更频繁(因为变更成本低了)。所以【不可变】这个词说的是修改方式,不是禁止变化。把它理解成【不准动】就完全反了。

  2. 错误:基础设施代码化只是把操作写成脚本,本质一样。——纠正:区别在【描述目标状态】还是【描述操作步骤】。脚本是我告诉你【先装这个、再改那个、然后重启】——执行到一半出错,状态就卡在中间。代码化描述的是【我要 3 台这样的机器】,由工具负责把实际状态调整到符合描述,并且可以重复执行而不出错。这个差别跟 4-7 讲的声明式是同一件事。

  3. 错误:这套做法只适合大公司,我们几十台机器用不上。——纠正:越是人少的地方越需要。因为漂移的根源是【靠人的记忆维持一致性】,而人少意味着记忆更少、交接口更少、出错后更没时间查。几十台机器、两三个人的团队,恰恰是最容易出【没人知道线上是什么版本】的队伍。规模小只是意味着可以选更简单的工具,不是可以不守这条纪律。

  4. 错误:既然机器可以随时重建,那数据也可以。——纠正:这是最危险的一条误解。不可变的是计算节点的状态,而数据必须放在外面(对象存储、数据库、共享存储)——因为重建机器会把本地盘一起丢掉。所以这套做法有一个必须成立的前提:有状态的东西全部外置。做不到这一点就贸然推行不可变,等于定期删数据。

自测三问(点开对答案) 1. 为什么【配置漂移】的每一次成因单独看都是合理的? —— 因为**它们都是应对具体问题的正常操作**:这个补丁先跳过是因为当时在维护、配置改动是为了排查故障、装测试包是为了验证——**每一步都有当时充分的理由**。漂移的可怕之处正在这里:**它不是由错误决策造成的,而是由无数个正确决策的叠加造成的**。所以指望【让大家更小心一点】来解决它是无效的——**只能靠机制,也就是不让人有机会手工改。** 2. 为什么【换掉它,离线再查】能显著缩短故障恢复时间? —— 因为**它把恢复和诊断解耦了**。修复一条传统路径是【先查清原因 → 再修 → 再验证】,其中【查清原因】占的时间往往最长且不可控;而【换掉】这条路**不需要任何诊断结论**就能执行,恢复时间只取决于【重建要多久】——而重建时间是已知的、可控的。**所以这不是【更聪明的修复】,而是【绕开诊断这道关卡】。** 3. 为什么推行这套做法的前提是【有状态的东西全部外置】? —— 因为**重建会丢掉本机的一切**,包括数据。而数据是不能靠重建恢复的——**重建只能恢复【程序该有的样子】,恢复不了【发生过的事实】**。所以这套纪律在架构上的强制要求是:计算节点要变成【用完即弃】的,凡是需要留下来的(用户数据、日志、文件)都必须存在机器之外。**做不到这条,不可变基础架构就是一场灾难**;做到了,它才成立。

相关笔记