☰
K8S旧书仍可当校准器:对象模型、三本账与API迁移
2026/10/28 23:37:12 网站建设 项目流程

简介:《Kubernetes in Action中文版》是面向云原生开发、运维与架构人员的Kubernetes系统学习读物,适合希望从容器编排入门并深入理解集群部署实践的读者。压缩包内共1个PDF文件,大小约15.62MB,为电子工业出版社2019年简体中文版,由七牛容器云团队翻译,内容完整便于离线阅读与检索。全书从Docker与Kubernetes的由来和发展切入,围绕在Kubernetes中部署分布式容器应用逐步展开,通过不断增加功能帮助读者理解架构与操作方式,并进一步覆盖监控、调试、伸缩等进阶主题;同时涉及容器编排系统在计算力调度、负载均衡、部署升级、服务发现及日志监控等方面的组织思路,对理解容器与数据中心操作系统的关系也有帮助。已有1212人学习,既可作为按章节系统阅读的教材,也便于在实际项目中查阅部署结构、线上流量组织与容器服务管理等相关内容。

1. 一本中文版 PDF 被反复找,说明 K8S 的知识折旧没有想象中快

一份 2019 年初出版的《Kubernetes in Action 中文版》PDF,原书基于 1.8 版本写成并用本地单节点集群跑完全部示例,到今天仍然有人隔三差五在技术群里问一遍有没有干净的版本。这件事本身就有点反直觉:容器编排这一层,API 版本换了好几轮,当年能直接 apply 的清单现在连解析都过不去,一本“过期”的书按说早该进资料库的旧资料区。可它没有,找它的人也没断过。

原因不在年份,在它选择讲什么。它没有把 K8S 当成一组命令来教,而是把 Pod、Service、Deployment、StatefulSet 这些对象为什么长成这个样子,从调度器、控制器、kube-proxy 的账本层面拆开讲了一遍。命令会变,对象模型在这六七年里几乎没有变。对想真正搞懂 K8S 而不是背命令的人来说,这类书的半衰期比文档长得多。

2. 十八章的骨架:从跑通一个 Pod 到控制面的账本

2.1 三部分结构,对应的是三个不同层级的提问

这本书的目录不是按“功能清单”排的,而是按“你在什么阶段会问什么问题”排的。第一部分只有两章,先把容器从哪来、怎么构建镜像、怎么在集群里跑起来讲完;第二部分八章,围绕单集群内的对象模型展开;第三部分八章,往控制面内部走,讲网络、认证、资源、调度和扩展。

部分章节解决的问题读完之后能回答的问题
第一部分1–2容器从哪来、怎么跑起来一个应用为什么需要编排层,本地集群和托管集群差别在哪
第二部分3–10单集群内的对象模型Pod、Service、卷、配置、发布之间怎么咬合
第三部分11–18控制面、安全、资源、调度与扩展副本为什么没起来、Pod 为什么被驱逐、流量为什么打到空端点

这个结构有个明显的取舍:它不教你怎么搭一个高可用集群,也不讲 etcd 怎么调优。作者在开篇就说清楚了,重点在应用侧。所以指望拿它做集群运维手册的人会失望,但拿它做“对象模型字典”的人会觉得很值。

第二部分的主线特别值得说。第 3 章先讲 Pod 和标签,第 4 章讲健康检查与副本管理,第 5 章讲 Service 怎么把 Pod 暴露出去,第 6 章讲卷,第 7 章讲配置和敏感信息注入,第 8 章讲应用怎么反过来访问 API,第 9 章讲 Deployment 的滚动更新,第 10 章讲有状态负载。这条线是一层一层加上去的:先能跑,再能活,再能被访问,再能持久化,再能配置,再能自我感知,最后才是发布和状态。

这种“每次只加一个维度”的写法,学起来慢,但理解得牢。很多后来出的速成材料是把所有对象一次性铺开,读者能背下来但串不起来,一遇到“Service 有端点但访问不通”就卡住。

2.2 全部示例用 YAML 清单,这个选择决定了书的寿命

书里的示例几乎不用任何语言的客户端 SDK,全部是 YAML 清单加 kubectl 命令。这个决定在当时看有点“土”,现在看是非常聪明的。

SDK 的接口迭代速度远快于 API 对象本身。一份用 Java 客户端写的示例,三年后可能连编译都过不去;而一份 YAML 清单,只要把 apiVersion 和少数必填字段改掉,逻辑还是那套逻辑。声明式清单还有一个副产品:它天然可以进版本库、可以做 diff、可以走审查流程,这恰好是后来基础设施即代码那套工作方式的雏形。

下面这份清单是书里 Deployment 示例的等价写法,只是换成了当前集群能直接接受的版本:

# 与书中示例等价、但可在当前集群直接 apply 的 Deployment apiVersion: apps/v1 # 书中写作 extensions/v1beta1 kind: Deployment metadata: name: demo-app spec: replicas: 3 selector: # apps/v1 起必填,且创建后不可变更 matchLabels: app: demo-app strategy: rollingUpdate: maxSurge: 1 # 滚动时最多超出期望副本数 1 个 maxUnavailable: 0 # 滚动过程中不允许有副本不可用 template: metadata: labels: app: demo-app spec: containers: - name: app image: demo/app:1.0 # 换成自己的镜像地址 ports: - containerPort: 8080 readinessProbe: # 就绪探针,决定是否进入 Service 端点 httpGet: path: /healthz port: 8080 initialDelaySeconds: 3 periodSeconds: 5 resources: requests: {cpu: 100m, memory: 128Mi} limits: {cpu: 500m, memory: 512Mi}

几个参数值得单独说明。selector.matchLabels在apps/v1里是必填项,因为控制器要靠它认领 Pod,而extensions/v1beta1时代可以省略、由模板标签自动推导——这是照着老书敲最容易撞上的第一个报错。maxUnavailable: 0配合maxSurge: 1意味着滚动期间先起新 Pod 再停旧 Pod,副本数永远不会低于期望值,代价是需要额外一份资源余量;如果集群资源紧张,反过来设成maxSurge: 0, maxUnavailable: 1更稳。readinessProbe和livenessProbe的区别也常被搞混:前者失败只是把 Pod 从 Service 端点里摘掉,后者失败会触发容器重启。

书里对这两个探针的区分讲得很细,甚至给了“探针本身配置错误导致无限重启”的反例。这类反例在文档里往往只有一句话,在书里是一整节,这就是纸质资料相对在线文档的差异。

2.3 时间锚点:1.8 版本意味着什么

所有示例在 1.8 版本加本地单节点集群上跑过,部分在托管集群上验证。1.8 这个时间点很关键:Deployment 还挂在extensions/v1beta1下,apps/v1要到 1.9 才出现;自定义资源那套机制刚刚把更早的第三方资源模型替下去;Pod 安全策略还叫 PSP,是集群管理员配的准入控制;HPA 只有autoscaling/v1,只能看 CPU。

照着书敲,最常见的翻车点就在 apiVersion 上。做一张对照表放在手边,比每次去搜报错快得多:

资源书里常见写法当前可用写法分界说明
Deployment / ReplicaSetextensions/v1beta1apps/v1旧版在 1.16 移除
Ingressextensions/v1beta1networking.k8s.io/v1旧版在 1.22 移除,pathType 变必填
自定义资源定义apiextensions.k8s.io/v1beta1apiextensions.k8s.io/v1旧版在 1.22 移除
水平自动伸缩autoscaling/v1autoscaling/v2v2 在 1.23 转正,支持内存与自定义指标
Pod 安全策略policy/v1beta1已移除1.25 移除,改用 Pod Security Admission

除了 apiVersion,还有几处命令层面的变动,属于“血泪经验”级别的坑:kubectl rolling-update早就删了,对应的能力合并进了kubectl rollout;kubectl run的--generator参数也没了,现在它默认只创建一个 Pod,不再顺手创建 Deployment;kubectl get --export同样被移除,想导出干净清单得靠kubectl get -o yaml再手工剔除 status 和 metadata 里的运行时字段。

注意:--dry-run在较早版本里是个布尔开关,后来才拆成client、server、none三个取值。脚本里如果还写着裸的--dry-run,在新版本上会直接报参数错误,这个报错信息很不直观,容易误判成集群问题。

这些差异不影响概念理解,但会极大影响动手体验。明智的做法是:读的时候把 YAML 当伪代码看,理解它想表达的对象关系;敲的时候先跑一遍服务端校验,让集群告诉你哪里不对。

3. 谁还在读:三类人的收益点并不相同

3.1 应用开发者:把“部署成功”和“部署正确”分开

对写业务代码的人来说,这本书最大的价值是让人分清两件事:容器起来了不等于服务可用,服务可用了不等于发布安全。

第 4 章讲副本管理和健康检查时,给了一个很典型的场景:Pod 处于 Running 状态,但里面的进程还在初始化,这时候如果直接接流量,用户会看到一批 502。就绪探针就是为这个场景存在的。很多团队早期的做法是在启动脚本里sleep 30,后来发现机器慢的时候 30 秒不够、机器快的时候白等 25 秒,最后还是回到探针上。

第 5 章讲 Service 的时候,把四种类型的适用边界讲清楚了:集群内互通走 ClusterIP,对外暴露走 NodePort 或 LoadBalancer,把集群外的服务映射进集群走 ExternalName。这一章还花了不少篇幅讲端点对象——Service 本身只是个虚拟 IP 的规则集合,真正干活的是背后那组 Endpoint。理解了这一层,“Service 存在但访问超时”这类问题就有了排查方向:先看端点列表是不是空的,再看选择器是不是写错了,最后才怀疑网络插件。

第 9 章的滚动更新和第 10 章的有状态负载,是把开发和运维拉到同一张桌子上的两章。前者解释了为什么发布过程中副本数会短暂超出期望值,后者解释了为什么数据库这类负载需要稳定标识和有序启停。这两章读完,再看现在的托管发布平台,会明白那些“灰度”“分批”“回滚”按钮背后到底在操作什么对象。

第 7 章和第 8 章相对冷门,但实际项目里用得很多。配置和敏感信息怎么注入、注入之后怎么热更新、应用怎么通过 Downward API 拿到自己的 Pod 名和命名空间——这些都是写 Operator 或者做多环境适配时的基础。尤其是“环境变量注入不会热更新、挂载卷会”这个细节,踩过坑的人印象都很深。

3.2 平台与运维侧:三本账决定了集群稳不稳

第三部分那八章,对做平台的人来说是核心。它把集群拆成三本账:资源账、调度账、网络账。

资源账在第 14 章。核心是 requests 和 limits 这两个字段怎么影响调度和运行时。requests 参与调度决策,调度器只保证节点上所有 Pod 的 requests 之和不超过可分配资源;limits 由内核的 cgroup 执行,超出内存限制会被杀掉,超出 CPU 限制会被限流但不会被杀。这两个字段的组合方式,直接决定了 Pod 的 QoS 等级:

QoS 等级触发条件驱逐顺序典型场景
Guaranteed每个容器都设了 request 且等于 limit最后被驱逐核心网关、数据库代理
Burstable至少一个容器设了 request,但不满足上一档居中,按实际用量超出 request 的比例排序大多数在线服务
BestEffort所有容器都没设 request 和 limit最先被驱逐批处理、临时任务

节点内存吃紧时,kubelet 按这个顺序驱逐 Pod。很多团队抱怨“生产 Pod 半夜被无故杀掉”,翻回去看清单,基本都是三类资源都没设,落在了 BestEffort 档位。把 requests 补上,问题往往就消失了,这个改动成本极低但收益极高。

调度账在第 16 章。节点亲和、Pod 亲和与反亲和、污点和容忍,这四组机制的组合能表达很复杂的放置策略。书里给的例子是“把同一服务的副本打散到不同节点”,用 Pod 反亲和加拓扑键实现。这一套在多可用区部署时尤其重要,但配置错了会导致 Pod 一直 Pending,而 Pending 的原因在事件里只写一句“不满足亲和规则”,排查起来相当费劲。

网络账在第 11 章。这一章讲清楚了 Service 的虚拟 IP 是怎么落到 iptables 规则上的,以及 Pod 之间跨节点通信依赖什么。理解了这一层,再看后来出现的各种网络方案,会知道它们改变的只是数据面实现,控制面的对象模型没动。

3.3 术语一致性带来的协作红利

这个中文版由一家云服务厂商的容器团队组织译者完成,多人分章翻译再统一审校。多人协作翻译的通病是术语打架,但这一版在术语上做了统一:核心对象名保留英文不译,容易混淆的概念在首次出现时给出中英对照。

这件事听起来是编辑层面的细节,实际影响不小。团队内部讨论时,如果一个人说“服务”、另一个人说 Service、第三个人说 svc,沟通成本会悄悄上升。有一套共同词汇表,写文档、做评审、查资料都能对得上。我在几个团队里见过的情况是:新人上手慢,往往不是技术难,是每个人嘴里的词指的不是同一个东西。

对非英语母语的读者来说,还有一个隐性收益:读中文版建立概念框架,再回头读英文文档补细节,比一上来硬啃英文原文效率高。概念框架建立起来之后,英文文档里的生词基本只剩名词,理解障碍会小很多。

4. 五个常见误读:版本之外,还有边界和用途

4.1 逐条拆开看

误读一:这是一本入门书,读完就能上手生产。

为什么会有这个印象:书名带“in Action”,章节从最基础的容器讲起,确实很像入门读物。但它的定位是“在 K8S 中开发和运行应用”,不是“搭建和运维 K8S 集群”。高可用控制面、etcd 备份恢复、证书轮换、集群升级,这些生产必备的内容它明确说了不在范围内。

怎么看:把它当“应用侧全景图”,集群侧的内容另找资料。两者不冲突,但别指望一本通吃。

误读二:API 版本都过期了,这书没用了。

为什么会有这个印象:照着敲第一份清单就报错,体验极差,很容易得出“过时”的结论。

怎么看:分清“语法”和“语义”。apiVersion 是语法,会变;Pod 为什么是最小调度单元、Deployment 的滚动更新凭什么能做到零中断、StatefulSet 为什么要配无头服务,这些是语义,没变。语法花半天就能翻译过来,语义花半年也未必能自己悟出来。

误读三:讲的是单集群,跟现在的多集群和服务网格没关系。

为什么会有这个印象:书里确实没有多集群联邦、没有服务网格,这些概念在当时还没成型。

怎么看:服务网格解决的问题,本质上是把“服务发现 + 流量治理”从应用代码里抽出来下沉到基础设施。它操作的对象仍然是 Service 和 Endpoint,只是把 iptables 那层换成了边车代理。不懂 Service 和 Endpoint 的关系,看服务网格的流量规则只会更糊涂。旧模型是新抽象的地基,这个顺序不能反。

误读四:书里的 kubectl 命令现在还能原样用。

为什么会有这个印象:命令看起来都是通用的,没有版本号提示。

怎么看:命令的子命令和参数是变动最频繁的部分。kubectl rolling-update、--generator、--export都已经移除,kubectl run的语义也变了。遇到报错先查当前版本的命令帮助,别怀疑集群。

误读五:翻译版就是直译,术语会乱,不如看原版。

为什么会有这个印象:技术书翻译质量参差不齐是事实,很多译本确实读起来别扭。

怎么看:这一版在术语表和审校上投入了人力,关键概念在首次出现时给了中英对照。真正拿不准的地方,对照英文原版核对一遍即可,不需要全程双开。对刚建立概念框架的阶段,中文的阅读速度优势是实打实的。

4.2 误读的共同来源:把“书的时间”当成“技术的时间”

这五条误读有个共同的根:把资料出版的年份和技术本身的生命周期混为一谈。

技术书有两个时间轴。一个是出版时间,决定里面的命令、版本号、示例能不能直接跑。另一个是它描述的那层抽象的生命周期,决定里面的判断还成不成立。前者以季度为单位折旧,后者以年为单位折旧。翻任何一本有年头的技术书,第一件事应该是判断它落在哪条轴上。

K8S 这层抽象的特殊之处在于,它的核心对象模型在 1.0 之前就基本定型了。Pod、标签选择器、控制器循环、声明式 API,这几个设计决策在 2015 年前后就定了,之后所有的演进都是在这个骨架上长肉。所以描述骨架的资料,折旧速度远慢于描述肉的资料。

反过来也有陷阱:不能因为骨架没变,就认为所有旧资料都值得读。有些书讲的是当年的生态格局、某几个方案的优劣对比,那部分是真的过期了,读完反而会形成错误认知。判断标准很简单:看它讲的是“对象为什么这样设计”,还是“当时哪个工具更流行”。前者读,后者跳过。

5. 抽象越来越厚,账本没变:K8S 能力分层的分水岭

5.1 上层抽象不断加厚,底层三本账原封不动

这几年 K8S 生态最明显的变化是抽象层在不断加厚。最早是直接写 Pod,后来写 Deployment,再后来是 Helm 包管理、Operator 控制器、平台工程内部门户,现在很多团队的业务方连 YAML 都看不到了,点个按钮就发布。

抽象加厚带来的是使用门槛下降,但也带来一个副作用:出问题时排查路径变长了。一个请求超时,可能出在业务代码、可能出在边车代理、可能出在 Service 端点为空、可能出在节点资源不足被驱逐、可能出在网络插件。上层抽象越好用,下层账本越陌生。

这就是为什么讲底层账本的资料仍然有价值。资源账、调度账、网络账这三本,无论上面套了多少层,最终都要落到这几个字段和这几个对象上。平台工程做得再好,也只是把这三本账包装得更友好,账本身没有消失。

一个具体的观察:现在招聘里写“熟悉 K8S”的岗位,面试时问得最多的还是那几件事——Pod 一直 Pending 怎么查、Service 访问不通怎么排查、滚动发布卡住怎么定位。这些问题全都是书里第 4、5、9、16 章覆盖的内容。上层工具换了一茬又一茬,面试题没怎么变,说明考查的就是那层不变的东西。

5.2 两条被低估的长线:有状态负载与自定义资源

书里第 10 章和第 18 章,当年看是进阶内容,现在看是两条主干。

第 10 章讲有状态负载。核心难点不在“怎么起一个数据库 Pod”,而在“怎么让它在重启、迁移、扩容之后还是同一个它”。解决方案是稳定网络标识加稳定存储:无头服务给每个副本一个固定的 DNS 名,持久卷声明保证数据跟着副本走,有序的启停顺序保证集群状态一致。这一套机制现在是各种数据库上云方案、消息队列上云方案的基础。近几年火起来的训练任务调度,很多也在复用同一套“稳定标识 + 有序启停”的思路。

第 18 章讲自定义资源。当时的写法还是用自定义资源定义加一个小控制器,现在这套模式有了统一的名字叫 Operator,成了把运维知识编码进系统的标准做法。它的思想其实很朴素:把“人类运维专家的判断”翻译成“控制器里的期望状态”,剩下的交给控制器循环去收敛。

这两条线的共同点是,它们都不是“多加一个字段”能解决的,需要理解控制器怎么工作、状态怎么收敛、失败怎么重试。书里对这些机制的描述,比大多数后来的教程要细。

5.3 一份旧资料的正确用法

不按章节顺序读。第 1 章和第 2 章可以快速过,建立“容器到编排”的直觉就够了。真正该反复翻的是第二部分的对象章节和第三部分的账本章节,而且是以“查”为主:遇到哪个对象拿不准,翻到对应章节看设计意图,比顺着读效率高得多。

清单要先翻译再运行。把书里的 YAML 抄下来之后,先做三件事:改 apiVersion、补必填字段、过一遍服务端校验。这三步用一个脚本就能批量完成:

#!/usr/bin/env bash # 批量校验从书里抄下来的清单能否被当前集群接受 set -euo pipefail # 任一命令失败即退出,避免错误被吞掉 DIR="${1:-./manifests}" # 第一个参数是清单目录,默认 ./manifests fail=0 while IFS= read -r f; do # --dry-run=server 会走准入控制和默认值填充,比客户端校验更接近真实结果 if ! out=$(kubectl apply --dry-run=server -f "$f" 2>&1); then echo "[FAIL] $f" echo "$out" | tail -n 3 # 只打最后三行,通常是关键报错 fail=1 fi done < <(find "$DIR" \( -name '*.yaml' -o -name '*.yml' \) -type f) exit $fail

脚本里几个地方值得说明。--dry-run=server需要较新版本的 kubectl,老版本只有布尔的--dry-run,行为接近客户端校验,检查不出准入控制层面的问题。set -euo pipefail里pipefail的作用是让管道中任一环节失败都算失败,否则kubectl ... | tail这种情况下错误会被 tail 的退出码掩盖。find里的括号必须转义,否则-type f只作用于后半个条件。

概念要挂到新东西上。读到服务网格的流量规则,回头对照第 5 章的 Service 和 Endpoint;读到 Operator,回头对照第 18 章的控制器循环;读到集群自动扩缩容,回头对照第 15 章的副本数调整逻辑。旧资料的价值不在于它给了新答案,而在于它给了理解新答案的坐标系。

6. 我的用法:把它当校准器,不当教程

我最早照着这本书敲示例的时候,第一份 Deployment 就卡了整整一个下午。extensions/v1beta1报错,我以为是集群装坏了,重装了两次本地集群,最后才在报错信息的最后一行看到“no matches for kind”。那次之后我养成一个习惯:任何从资料上抄下来的清单,在 apply 之前强制走一遍--dry-run=server,让集群先告诉我能不能过,再决定要不要花时间排查。

后来这个习惯延伸出了别的用法。团队里有人问“为什么这个 Pod 一直 Pending”,我不再凭记忆答,而是翻回讲调度那章,把节点亲和、资源请求、污点容忍这几条逐个对一遍,通常五分钟内能定位。有人问“滚动发布为什么卡住不结束”,就翻回讲 Deployment 的那章,对着maxSurge和maxUnavailable的组合看当前配置是不是把自己锁死了。这本书在书架上的位置,从“要读完的书”变成了“要翻的书”。

对刚接触 K8S 的人,我的建议是别把它当教程从头啃。先跑通一个最小应用,建立“清单声明期望状态、控制器负责收敛”这个直觉,然后遇到问题按对象去查对应章节,看设计意图而不是抄命令。对已经用了几年的人,值得回头重读的是第三部分那几章——当年觉得枯燥的资源配额和调度规则,恰恰是现在排查大部分线上问题的入口。

手边留一份能检索的 PDF,比放在收藏夹里吃灰强。真正会用的人,都是把它当校准器用的:念头拿不准的时候翻一页,确认一下自己的理解没有跑偏,然后继续干活。希望帮到你。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询