本节摘要:API Server 暴露的是一组 REST 风格的资源接口,集群里的一切——Pod、Deployment、Service——都是台账上的资源对象。客户端通过"增删改查加 watch"与之交互,watch 机制让各组件能在状态变化时立即得知,是声明式制度的信号系统。本节走通一次 kubectl apply 的完整旅程,并理解资源、版本、幂等三个关键词。
上一章你交过一份"三株网页"的单子,柜台验完就归档了。档案长什么样?在集群上看一眼:
# 列出这家"机构"受理的所有单据类型 kubectl api-resources # NAME SHORTNAM NAMESPACED KIND # pods po true Pod # deployments deploy true Deployment # services svc true Service # namespaces ns false Namespace # nodes no false Node # ...(完整列表有几十行,还能通过自定义资源扩展)
# 看一份已归档单据的全貌(YAML 视角,节选) kubectl get deployment greenlib-web -o yaml # apiVersion: apps/v1 # kind: Deployment # metadata: # name: greenlib-web # generation: 2 # 单子被改过几次,一目了然 # uid: 5f3a... # 全集群唯一身份号 # spec: # 你声明的期望 # replicas: 3 # status: # 园丁汇报的实际(此刻已达标) # readyReplicas: 3
这两条输出透露了台账的本质:一切都是资源对象。每份对象有 apiVersion(单据模板版本)、kind(单据类型)、metadata(身份信息)、spec(期望状态)与 status(实际状态)。你写 YAML 时只写 spec 之前的四样,status 由园丁们填写。spec 与 status 的分离,就是"期望"与"实际"这对矛盾在数据结构上的投影,整套系统的运转都围绕把 status 扳向 spec。
命令式世界的经典恐惧是"脚本跑了两遍"。声明式世界没有这个问题:apply 的语义不是"执行这些操作",而是"让台账与我的单子对齐"。同一份单子交一遍与交十遍,台账内容相同,园丁看到的期望不变,就不会有多余动作。这性质有个学名,幂等。它带来的工程红利很实际:交付流水线重试无顾虑、网络抖动重发无副作用、灾备重建就是"把单子再交一遍"。

台账有了、园丁有了,还有最后一个工程问题:园丁怎么知道账变了?最笨的办法是每秒全量拉一次台账,几十万个对象这么玩,柜台直接累垮。Kubernetes 的答案是 watch:客户端对某类资源"订阅"变化,台账一有增改,柜台立刻把增量推给订阅者。调度器 watch 未分配的 Pod、kubelet watch 派给本节点的 Pod、控制器 watch 自己负责的对象——整个集群像一片听到雨声就动的田,而雨声的传播靠的是 watch 这套信号系统。
kubectl 里也有它的影子:kubectl get pods -w 末尾那个小写的 w,就是让柜台把后续变化推给你看,而不是打印一遍就退出。第七章观察滚动更新时它会大放异彩。
零件齐了,把 2.1 那个"排练剧情"扩成正式时序,这也是全册最重要的一张流程图:
对这张图我常做一个测验:把图里任何一条线掐断,问"田里会发生什么"。掐掉调度器,Pod 永远停在 Pending(第三章你会亲眼见到);掐掉 kubelet 与柜台的连线,苗还活着但无人补种;掐掉园丁,期望与实际的差距再没人扳。理解故障画像,比背组件名词更能检验你是否真懂这台机器。
单据模板会演进,所以每份单子都有 apiVersion(如 apps/v1)。偶尔还能见到 v1beta1 字样的旧模板,读旧清单时留意即可。更妙的在于:单据类型本身可扩展。机构允许你注册自定义资源(CRD),凭空发明新的单据类型——比如注册一种 Greenhouse(温室)类型,再配一个专属园丁盯着它。这个扩展机制是 Operator 生态的地基,超出入门范围,但你现在知道了它并不神秘:不过是"新单据加新园丁"而已。
⚠️ 常见坑:把 kubectl 当成"客户端里装了个数据库"。kubectl 只是个翻译官,它把你的 YAML 翻译成对 API Server 的 HTTP 请求。理解这一点,kubectl 的所有子命令(get、describe、apply、delete)对你来说就只是不同花式的"读写台账"。
apply 带整份单子,柜台对齐台账;patch 只带差异片段,动一个字段。日常交付用 apply(口径统一、可入库评审),脚本里的小改动可用 patch(第七章会看到它一条命令改配额的用法)。两者殊途同归:最终都是改台账,再由各方 watch 之后自行行动。顺带说一句,kubectl 里没有"重启服务"这个动词——想滚动重启,改一个会触发模板变化的字段(比如给模板加个无害的注解)即可。这是声明式的又一次顺手胜利。