在Kubernetes(K8S)里面摸爬滚打,如果你只会 kubectl run 和 kubectl apply,那离“会用”还差着十万八千里。我见过不少刚接触K8S的朋友,上来就写Pod清单,kubectl apply 一下,业务跑了,就觉得自己会了。结果一问“如果这个Pod挂了怎么办”,对方一脸茫然——重新apply一次呗。这就是典型的还没理解Pod控制器(Controller)的价值。
可以这么说:Pod是K8S里调度的最小单元,但直管Pod不挂代理的用法几乎只存在于测试环境。真正扛线上流量的,永远是Pod控制器。它帮你管副本数、管滚动更新、管故障自愈、管网络标识的稳定性。这篇文章我会把这套东西掰开揉碎讲清楚,包括控制器到底在解决什么问题、Deployment和StatefulSet这类主流控制器怎么选怎么用、滚动更新和回滚背后的细节逻辑,以及我踩过的那些真金白银的坑。适合刚学完K8S基础、准备上手搭建集群跑业务的人,也适合准备面试时被问到“Deployment和StatefulSet区别”这类问题的人。
1. 先搞清楚:Pod控制器到底解决了什么问题
1.1 没有控制器时我们是怎么跑业务的
先把场景拉回到最原始的K8S用法。你写好一个Pod的YAML,里面定义了一个nginx容器,kubectl apply -f nginx.yaml,Pod跑起来了,IP也分配到了,一切看似美好。
但线上哪有这么理想。有一次我在测试环境模拟节点故障,直接把Pod所在的那台worker节点关机。结果呢?这个Pod就永远卡在Terminating状态,业务彻底断掉。因为裸Pod没有“保活”机制,它的生命周期和节点强绑定,节点挂了它就没了,而且没有谁会去重新拉起一个新Pod。这就是为什么K8S官方文档里反复强调:不要直接创建Pod,哪怕只有一个副本,也应该交给控制器去管。
裸Pod的另一个问题是没有“声明式”的恢复能力。比如你想跑3个副本,手动创建3个Pod当然可以,但其中一个Pod被误删了,系统并不会替你补回来。你再apply一次YAML,K8S只会告诉你“Pod已经存在”,然后什么都不做。这其实反映了K8S一个非常重要的底层哲学:它只负责“维持你声明的期望状态”,而不是“帮你执行一次性的操作”。而控制器,正是把这种哲学落到实处的核心机制。
1.2 控制器的核心思路:期望状态与控制回路
K8S里控制器的设计灵感来自我们熟悉的恒温器。你设定了26度,这是期望状态;温度传感器读到当前房间是23度,这是实际状态;空调就会开始制热,直到实际状态达到期望状态。控制器在K8S里干的也是一模一样的事。
每个控制器都盯着两类对象:一类是它自己管理的那份期望状态(比如Deployment里写的replicas: 3),另一类是集群里的实际资源状态(通过API Server实时watch到的Pod数量)。两者一旦不一致,控制器就调用API去创建或删除Pod,直到实际数量与期望数量完全对齐。这个“监听-对比-动作-再监听”的循环,在源码里叫Reconcile(调谐),也是面试时特别爱问的一个点。
这里有个细节值得注意:控制器并不是“实时监控Pod进程挂了没有”,而是监听API Server上对象的变化。如果你用 kubectl get pod 看到一个Pod的状态是Error或者Completed,但这依然是一个“存在于etcd里的Pod对象”,控制器并不会因为容器退出就立刻删掉它。它真正关心的是Pod对象的数量是否等于期望值,以及Pod有没有处于Running状态。理解了这一点,后面排查很多问题都会顺不少。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 五种主流Pod控制器,每个都要会用
2.1 Deployment:日常业务的无状态主力
Deployment可以说是K8S里出场率最高的控制器,没有之一。我自己的项目、包括帮朋友搭的集群里,90%的无状态Web服务都是用Deployment跑的。
Deployment最核心的价值是管理无状态应用。什么叫无状态?就是每个实例之间不共享本地数据、不依赖固定的网络身份,任何一个实例挂了,新建一个顶上来就行。比如Nginx、后端API、前端静态页面,这些都是典型的无状态服务。Deployment会帮你自动创建一个ReplicaSet,再由ReplicaSet去管理Pod副本数。
Deployment还有一个隐藏技能是滚动更新。老版本K8S里Deployment直接管Pod,后来演进成Deployment——ReplicaSet——Pod三层结构,其实就是为了把“更新版本”这件事拆出来。每次你修改镜像tag再apply,Deployment就会创建一个新的ReplicaSet,然后逐渐缩容旧的ReplicaSet里的Pod、扩容新ReplicaSet里的Pod,整个过程业务不中断。这也是Deployment最吸引人的地方——我后来给生产环境升级版本,基本都是跑一遍滚动更新再加一句kubectl rollout status确认结果,很少出现过因为升级导致的服务中断。
Deployment的局限也在于“无状态”三个字。数据库、消息队列这类需要稳定存储和稳定网络标识的应用,用Deploymen
