Kubernetes 系统设计者之路 · 序与问题地图
这不是一本”kubectl 怎么用”的手册,也不是一份把概念搬到中文的说明书。 这是一本把 Kubernetes 当成一部活着的系统设计史来拆的书。 每一章只回答一个问题:它当初到底在解决什么麻烦?后来的人又用什么新办法把麻烦解决得更漂亮?
一、先别急着学,先问一句:你为什么需要 K8s?
老哥,咱们先停一下。
你写了五年 Go,CRUD 和中间件都摸过,你肯定部署过服务——编译、打镜像、scp 上去、跑起来、挂个 systemd。这套动作你闭着眼都能做。那我问你一个问题,你先别急着翻书,先在脑子里过一遍:
如果你的服务只有 1 个,你需不需要 Kubernetes?
想三秒。
……
答案很清楚:不需要。 一个服务,一台机器,systemd 管着,挂了自动拉起,够了。K8s 在这个场景下纯属脱裤子放屁——你引入了 etcd、API Server、调度器、kubelet、CNI、容器运行时……一堆进程,就为了跑一个进程。这账怎么算都是亏的。
那 K8s 是给谁设计的?
你心里已经有了答案的雏形:给”很多”设计的。 给几百个服务、几千个实例、几十台甚至几百台机器设计的。给”人肉已经管不过来”的那个临界点设计的。
好,记住这个感觉。我们整本书的第一性原理就这一句话:
Kubernetes 不是一个”功能集合”,它是一堆”规模带来的麻烦”的答案合集。
你记不住它的所有概念,没关系。但你只要能回答”这个设计是在还哪一笔债”,你就真懂了。这也是为什么这本书的副标题是”系统设计者之路”——我们不是来背名词的,我们是来学”遇到麻烦怎么设计”的。
二、大多数人学 K8s 是怎么废掉的
我见过太多人,包括当年的我自己,学 K8s 的路线是这样的:
- 照着文档
kubectl run起个 nginx; - 被 Pod、Deployment、Service、Ingress 一堆名词砸晕;
- 硬背:“Pod 是最小调度单位,Deployment 管副本,Service 做负载均衡”;
- 面试能答,一上线就懵:为什么我的 Pod 起不来?为什么 Service 不通?为什么节点压力大了我的 Pod 被杀了?
- 最后变成”遇事不决重启大法”,或者”遇事不决问群里”。
问题出在哪?
出在他们学的是”名词”,不是”问题”。 他们脑子里是一张扁平的概念表,而不是一张有因果的地图。概念之间没有”因为所以”,只有”并列”。
比如说”Service”。大多数人背的定义:“Service 是稳定的访问入口,背后挂着一堆 Pod。” 这是对的,但这句定义没用——因为它没告诉你:
- 为什么 Pod IP 不能当稳定入口?(因为 Pod 会死,IP 会变)
- 那 IP 变了,调用方怎么知道?(这就逼出了 Service 这个”虚拟 IP + 自动维护后端列表”的东西)
- 这个”虚拟 IP”在机器上到底长啥样?是个进程吗?是个网卡吗?(其实是 iptables/ipvs 里的一堆规则)
- 规则谁写的?什么时候写的?(kube-proxy 看着 Endpoints 变,就改写规则)
- Endpoints 这玩意后来为啥被嫌弃了?(后端一多,一个对象几 MB,watch 风暴,于是有了 EndpointSlice)
你看,当你顺着”问题”往下剥,Service 自己就从答案变成了下一个问题的起因。 这才是真懂。背书的人停在第三层,设计者看到第十层。
所以这本书的读法,跟你以往看教程不一样。每一章我会先把你按在”麻烦现场”,让你先自己琢磨一两步,然后再层层剥开。有的地方我会故意留白,让你先想。书里所有”思考题”都配了参考答案——但老哥你记着,答案不是用来抄的,是用来对答案的。你自己想过的,跟看答案对上了,那才叫长在自己身上。
三、这本书的方法论:问题 → 设计 → 演化
每一章都按同一个骨架走:
1. 问题(Problem)。 先把你拉到 K8s 诞生之前,或者某个子系统设计之前。没有这个东西的时候,人是怎么痛苦的?是运维凌晨三点被叫醒?是扩容要填工单等三天?还是一台机器挂了,上面的服务全灭?
2. 设计(Design)。 它怎么解的?核心机制是什么?为什么这个机制能解(而不只是”它做了什么”)?我会尽量用生活化的类比把抽象机制钉死——邮局、餐厅、快递柜、合同、红绿灯,哪种能讲清楚用哪种。
3. 演化(Evolution)。 这一点是这本书跟别的 K8s 书最大的不同。我会专门花篇幅讲:后来的版本、后来的社区,发现当初的设计有什么不够好的地方,又用了什么新办法。 比如 Endpoints 变 EndpointSlice,iptables 变 ipvs,PodSecurityPolicy 变 Pod Security Admission,cgroups v1 变 v2。看演化,你才看得到”设计没有终点,只有权衡”——这才是系统设计者的真正内功。
为什么非要讲演化?因为只讲”现在是什么”,你是模仿;讲”为什么从那样变成这样”,你才学的会是判断。 等你哪天自己要设计一个分布式系统,没人给你答案,你靠的就是这种”在几个都不完美的方案里,根据约束做选择”的肌肉。
四、一张地图:K8s 全系统的”核心矛盾”一览
下面这张表,是整本书的目录,也是一张”问题地图”。每一行都是一个矛盾——一个”我想要 X,但现实 Y 挡路”的死结。你后面每章都会回到这行来。先扫一眼,不用记,知道有这张图就行。
| 章节 | 子系统 | 它要还的”债”(核心矛盾) |
|---|---|---|
| 2 | 编排的必然性 | 应用越来越多,机器越来越多,人肉部署/扩缩容/故障转移已经崩溃 |
| 3 | 声明式 API / 控制循环 | 命令式脚本”做一次”不可恢复;系统任何瞬间都可能偏离期望,需要”永远朝目标收敛” |
| 4 | API Server | 一堆组件都要读写状态,得有个唯一、可控、可追溯的”真理入口” |
| 5 | etcd | 状态要存在哪?要一致、要持久、要能 watch,又不能慢死 |
| 6 | 调度器 | 一堆 Pod 要落地,落哪台?要装得下、要亲和、要省资源、要公平 |
| 7 | 控制器模式 | 副本、升级、有状态、一次性任务……每种工作负载的”麻烦”都不一样,不能一套通吃 |
| 8 | Pod / CRI | 容器太”小”:一组进程要共享网络/存储/生命周期,得有个”同生共死”的包裹 |
| 9 | 网络 | Pod 要互通、要稳定寻址、要对外暴露;但每个 Pod 都有 IP,网络怎么不乱套 |
| 10 | 存储 | 有状态应用重启不能丢数据;但 Pod 会漂,盘怎么跟着走 |
| 11 | 服务发现演进 | Endpoints 对象在大规模下爆炸;需要更细粒度、更省带宽的发现机制 |
| 12 | 配置 / 密钥 | 配置写死镜像里,改个开关要重新打包;密钥更不能明文躺平 |
| 13 | 安全 | 谁能动什么、Pod 能碰什么、网络能通到哪——默认全开就是灾难 |
| 14 | 可扩展机制 | 内置能力永远不够;怎么让用户在”不改 K8s 源码”的前提下塞进自己的逻辑 |
| 15 | 资源 / QoS | 节点资源有限,谁该被优先保证?谁该在压力下先死? |
| 16 | 高可用 | 控制面自己挂了,整个集群就瞎了;它得先能自愈 |
| 17 | 可观测性 | 分布式之后,一个问题散在几十个组件里;怎么在迷宫里定位一根坏线 |
| 18 | 版本演进 | 回头看:哪些老问题被新方法解决了,哪些权衡一直没变 |
你发现没有?这张表里没有一行在说”K8s 有什么功能”。每一行都是”没有 K8s 会死在哪”。 这就是设计者视角的入口。
五、一个示范:咱们现场剥一层”为什么需要编排”
怕你还是觉得抽象,我拿第一章要讲的大问题,在这儿先剥一层给你看,让你尝尝这个”从问题入手”的滋味。
场景: 你有 3 个服务——网关、订单、库存。部署在 3 台机器上。某天订单服务流量暴涨,你手动在订单机器上 systemctl 起了第 2 个实例。一切安好。
麻烦来了: 半夜订单机器磁盘满了,订单服务挂了。你被叫醒,迷迷糊糊在另一台机器上起了一个实例,但忘了改网关的 upstream 配置——网关还往死掉的 IP 发请求,一半请求 502。你修了半小时。
麻烦升级: 公司发展了,30 个服务,每台机器上跑五六个。你发现:
- 哪台机器上跑了什么,你靠脑子记不住了(得有个”台账”);
- 某个服务要加实例,你不知道哪台机器还有空(得有人算资源);
- 一台机器挂了,上面五六个服务要逐个挪,挪到哪、IP 怎么更新、依赖怎么连,全是手工(得自动搬);
- 发版要滚动,不能全停,手动滚 30 个服务你当天别下班了(得自动编排发布)。
你看,每一个”麻烦”,都是后来 K8s 一个子系统的 Seed(种子):
- “得有个台账” → etcd + API Server(集群的真实状态);
- “得有人算资源往哪放” → 调度器;
- “得自动把挂的搬走、自动扩缩” → 控制器 + 控制循环;
- “得自动滚动发布” → Deployment 控制器;
- “IP 老变,调用方怎么找” → Service + 服务发现。
所以 K8s 不是从天而降的。它是被人肉运维的痛点,一砖一瓦逼出来的。 你记住这个因果关系,后面 18 章都是它的展开。
六、这本书的”对话”约定
为了对标你想要的”讨论式”,书里我会用几种标记,你认一下:
- 「墨:」 是我(墨叔)抛的问题或追问,相当于咱俩面对面聊时我拍你肩膀那一下。
- 「你:」 是替你预设的回答或反驳——很多时候是我替你说出心里话,再一起推。
- 🔧 思考题 是留给你自己想的,下面紧跟 【参考答案】。老哥你答应过我,思考题必须配答案——你把这答案当第二遍讲解看,不是当考试。
- 📦 案例 是真实或高度拟真的工程场景,用来把机制钉在生活里。
- ⚠️ 坑 是生产环境真会咬人的地方,提前给你画警戒线。
七、关于”硬核”和”30 万字”
你点名要硬核,要 30 万字。我得跟你交个底,免得你读到后面觉得我在水:
硬核不等于堆术语。硬核是——我把一个机制拆到”如果你来设计,你会卡在哪一步”,然后看 K8s 怎么过的坎。比如讲 etcd,我不只说”它用 Raft”,我会问你:三个节点,一个崩溃,剩下的两个怎么决定”谁的日志算数”?如果网络分区,两边各写各的,恢复后以谁为准? 这种问题答上来了,Raft 你才真懂,否则就是个名词。
30 万字不等于凑页数。每一章我都按”问题→设计→演化”走满,该深的章节(网络、调度、etcd)会很长。你嫌长的时候,记住:你怕的是水,不是长。我尽量让每句话都在搬砖,不在和泥。
八、给五年 Go 老兵的特别提示
因为你是从 Go 后台过来的,这本书里我会多处用 Go 的视角勾连:
- 控制循环其实就是
for { desired := get(); actual := observe(); if desired != actual { act() } }——你写过 reconcile 吗? - etcd 的 watch 本质是个长连接的事件流,跟你写的消息推送是不是一个东西?
- 调度器的”过滤+打分”就是给你一个 Pod 任务,让你从节点列表里挑一个——像不像你写的任务分发?
- CRD + Operator 就是”用 Go 写一个控制器,盯着自定义资源做调和”——你完全可以自己写一个。
所以你读的时候,脑子里随时可以翻译成 Go:*“哦,这玩意我也能写一个。”** 对的,很多你真能写。K8s 没用什么你写不出的黑魔法,它用的是你一个人写不过来的规模和取舍。
九、本章思考题
🔧 思考题 1
你说”一个服务不需要 K8s”。那反过来问:如果一个公司只有 2 个服务、2 台机器,上 K8s 划算吗?什么量级(服务数 × 机器数)你认为是”该上”的临界点?这个临界点背后真正的成本是什么(不只是机器钱)?
【参考答案】 临界点上没有标准答案,但”该上”的信号不是服务数量,是运维动作的人肉成本开始非线性上升——也就是”一个变化要手工动 N 个地方,且 N 随规模平方增长”的时候。2 服务 2 机器,故障域小、人肉能 cover,kubeadm 搭一套的维护成本反而比它解决的问题贵。真正的成本有三块:(1) 认知成本——团队要懂一整套新概念才能排障;(2) 运维成本——控制面本身要保活、升级、备份 etcd;(3) 隐性风险成本——一个 YAML 写错,可能比手工操作影响面更大更快。所以临界点往往在”人肉部署/故障转移已经让你开始填工单、开始半夜被叫、开始靠某个人脑子里的拓扑图”的时候。这是个组织问题,不是纯技术问题。
🔧 思考题 2
书里说”K8s 是麻烦的答案合集”。请你从你自己的工作经历里,举一个你觉得如果当年有 K8s 会轻松很多的麻烦,并猜猜它对应 K8s 哪个子系统。
【参考答案】 (这是开放题,没有标准答案,但我给你个范例。)比如你当年做过”大促前手动加 10 台机器、每台 ansible 批量下发服务、配好 nginx upstream、大促后手动缩”。这对应的就是:调度器(往哪放)+ 控制器(按副本数维持)+ Service/kube-proxy(自动维护 upstream)+ HPA(按指标自动扩)。痛点在于”加机器”和”加实例”是两件事、要人串联,而 K8s 把”副本数=5”一个声明,就把调度、起实例、注册到发现、缩容全串起来了。意识到”扩容的本质是改一个数字”,就是设计者视角的起点。
🔧 思考题 3
“背书的人停在第三层,设计者看到第十层。” 你回忆一下自己学过的某个技术(不一定是 K8s),你曾经停在”名词层”,后来因为某个契机突然看到”因果层”的?那个契机是什么?
【参考答案】 开放题。常见的契机是排障——只有当你亲手踩过一个坑,被迫顺着调用链一路追问”为什么会这样”,名词才连成因果。比如很多人学 TCP 三次握手是背的,直到遇到”TIME_WAIT 爆了导致连不上”,才真正理解为什么要有它、为什么等 2MSL。给你的提醒:本书里所有”⚠️ 坑”,都是别人用线上事故换来的”因果层门票”,别跳过。
十、本章小节
- K8s 是”规模带来的麻烦”的答案合集,不是功能集合;
- 学它要沿”问题 → 设计 → 演化”,别停在名词层;
- 整本书挂在一张”核心矛盾地图”上,每个子系统都在还一笔债;
- 看”演化”比看”现状”更重要,因为它教你怎么判断;
- 你写的 Go,很多 K8s 机制都能翻译成你写过的东西——别把它供起来。
下一章,我们从最根上的问题开始:人类到底为什么要”编排”?从裸机到容器的每一步,是被什么逼出来的?
(目录与阅读顺序见本书末尾《全本索引》,或随包附带的 README。)