一、前言
在K8s学习过程中,很多新手只会简单使用 kubectl apply、kubectl rollout undo,但完全不懂底层逻辑:
-
为什么Deployment更新后,旧ReplicaSet不会被删除?
-
回滚时Pod名称和旧版本一模一样,是Pod复活了吗?是巧合吗?
-
明明ReplicaSet可以管理Pod,生产为什么只用Deployment,不用ReplicaSet?
本文结合本人真实实操踩坑全过程,彻底讲透Deployment更新、滚动升级、版本回滚的底层原理,同时厘清生产环境的核心选型逻辑。
二、先搞懂基础:ReplicaSet与Deployment的基础关系
1. ReplicaSet(副本集)作用
核心功能:保证集群中始终维持指定数量的Pod副本,如果Pod挂了、被删了,会自动重建,保障Pod高可用。
但ReplicaSet有一个致命短板:不支持版本迭代、不支持更新回滚、无版本记录。
2. Deployment的定位
Deployment是ReplicaSet的超级封装,是K8s用于管理无状态应用的核心资源,所有的更新、升级、回滚操作,都是Deployment通过操控ReplicaSet实现的。
简单理解:Deployment是管理者,ReplicaSet是执行者。
三、实操完整踩坑流程(真实实验场景)
本次实验全程版本更迭、报错中断、手动回滚,完美复现新手所有疑惑点,完整时间线如下:
1. Revision 1:初始版本
创建Nginx Deployment,默认镜像正常启动,生成第一个ReplicaSet,维持3个正常运行的Pod。
-
ReplicaSet:
nginx-deployment-64598b8f46 -
副本数:3(正常运行)
2. Revision 2:正常版本更新(nginx:1.16.1)
修改镜像版本并更新,Deployment触发滚动更新机制:
-
新建第二个ReplicaSet:
nginx-deployment-8d94c585f -
新ReplicaSet拉起3个新Pod
-
旧ReplicaSet副本数被置为0,原有旧Pod被逐步删除
更新完成后:新版本Pod正常运行,旧ReplicaSet保留(副本数为0,用于回滚)。
3. Revision 3:错误更新+手动中断(核心踩坑点)
本次操作出现两个关键问题,也是新手最容易懵的场景:
-
手动输入错误镜像版本
nginx:1.161(镜像不存在) -
发现报错后,直接 CTRL+C 中断命令
很多人以为中断命令会撤销更新,这是最大误区!
真实结果:
-
Deployment已创建第三个全新ReplicaSet:
nginx-deployment-579478bf45 -
新镜像拉取失败,新Pod无法启动
-
滚动更新流程已触发,旧版本(revision2)的Pod被陆续删除
-
最终集群状态卡死:新Pod起不来、旧Pod被删,业务异常
重点结论:CTRL+C 只是终止本地命令行输出,不会停止K8s集群的更新流程!
4. 执行版本回滚(rollout undo --to-revision=2)
为恢复业务,执行回滚到上一个正常版本,集群触发回滚逻辑:
-
不再新建ReplicaSet,直接复用历史revision2的ReplicaSet(8d94c585f)
-
将异常版本ReplicaSet(579478bf45)副本数置0,异常Pod进入终止状态
-
旧ReplicaSet重新拉起3个全新Pod,恢复业务
-
再用kubectl rollout history查看历史命令时,回滚到的那条历史命令没有了,新加了一行刚刚执行的回滚命令,其内容和回滚到的那条原命令相同。因为回滚相当于执行了一遍对应的那条历史命令。
四、核心疑惑深度解答(彻底解惑)
1. 回滚后Pod名称和旧版本一模一样,是Pod复活了吗?
绝对不是!完全是全新Pod,无任何复活复用
很多同学看到同名Pod会疑惑,这里分清两个关键点:
-
前缀相同是必然 :Pod命名规则为
Deployment名-ReplicaSet哈希-随机串,回滚复用同一个ReplicaSet,前缀必然一致 -
全名一致是巧合:最后的随机字符串碰撞,纯粹概率问题
验证是否为新Pod的核心依据:查看Pod的AGE、IP、创建时间,回滚后的Pod是全新进程,和旧Pod无任何关联。
2. 为什么每次更新都会新建ReplicaSet,不直接修改旧的?
这是Deployment版本留存、支持回滚的核心设计:
-
每次更新镜像、配置,都会生成全新ReplicaSet,对应一个版本revision
-
所有历史ReplicaSet默认保留(副本数置0),作为版本快照
-
回滚时直接复用历史ReplicaSet快照,无需重新编写配置,秒级回滚
五、生产环境:为什么只用Deployment,不用原生ReplicaSet?
很多新手疑惑:ReplicaSet也能维持Pod数量,为什么生产环境100%只用Deployment,完全弃用原生ReplicaSet?
1. ReplicaSet的致命缺陷
-
仅能保证Pod数量,不支持滚动更新,更新只能删旧建新,业务中断
-
无版本记录、不支持回滚,更新出错无法快速恢复业务
-
无更新策略,无法控制更新节奏,容易导致集群Pod全部挂掉
-
不支持暂停、恢复发布,无法适配灰度、分批发布场景
2. Deployment的生产核心优势
-
滚动更新:先启新Pod、再删旧Pod,业务零停机更新
-
版本管理:自动留存所有版本ReplicaSet,支持一键回滚
-
策略可控:支持最大峰值、最大不可用Pod配置,保障更新稳定性
-
适配CI/CD:适配自动化发布、灰度发布,是生产标准无状态应用控制器
一句话总结 :ReplicaSet只是底层基础组件,只负责保活Pod;Deployment是上层生产级组件,负责安全更新、版本管理、故障回滚,是生产唯一选择。
六、最终核心知识点总结
-
Deployment更新不删除旧ReplicaSet,仅将其副本数置0,留存为版本快照
-
回滚不会复活旧Pod,是复用历史ReplicaSet,全新创建Pod
-
Pod名称一致是哈希前缀固定+随机串巧合,并非Pod复用
-
终端CTRL+C中断更新命令,无法停止集群更新流程,会导致业务卡死
-
ReplicaSet仅做Pod保活,无更新、回滚能力,生产环境一律使用Deployment
-
Deployment = 多版本ReplicaSet管理 + 滚动更新 + 一键回滚 + 生产高可用
七、学习感悟
本次通过手动改错镜像、中断更新、版本回滚的完整实操,彻底吃透了Deployment的底层运行逻辑。看似简单的更新和回滚命令,背后是K8s精心设计的版本快照和滚动更新机制。
同时也明白了K8s生产选型的核心逻辑:底层组件只做基础能力,上层组件提供生产级稳定性。ReplicaSet是基础,Deployment才是适配企业业务的标准方案,这也是生产环境几乎所有无状态应用都使用Deployment部署的根本原因。