K8s Deployment 滚动更新与回滚深度详解(含踩坑实录+生产选型原理)

一、前言

在K8s学习过程中,很多新手只会简单使用 kubectl applykubectl 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:错误更新+手动中断(核心踩坑点)

本次操作出现两个关键问题,也是新手最容易懵的场景:

  1. 手动输入错误镜像版本 nginx:1.161(镜像不存在)

  2. 发现报错后,直接 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是上层生产级组件,负责安全更新、版本管理、故障回滚,是生产唯一选择。

六、最终核心知识点总结

  1. Deployment更新不删除旧ReplicaSet,仅将其副本数置0,留存为版本快照

  2. 回滚不会复活旧Pod,是复用历史ReplicaSet,全新创建Pod

  3. Pod名称一致是哈希前缀固定+随机串巧合,并非Pod复用

  4. 终端CTRL+C中断更新命令,无法停止集群更新流程,会导致业务卡死

  5. ReplicaSet仅做Pod保活,无更新、回滚能力,生产环境一律使用Deployment

  6. Deployment = 多版本ReplicaSet管理 + 滚动更新 + 一键回滚 + 生产高可用

七、学习感悟

本次通过手动改错镜像、中断更新、版本回滚的完整实操,彻底吃透了Deployment的底层运行逻辑。看似简单的更新和回滚命令,背后是K8s精心设计的版本快照和滚动更新机制。

同时也明白了K8s生产选型的核心逻辑:底层组件只做基础能力,上层组件提供生产级稳定性。ReplicaSet是基础,Deployment才是适配企业业务的标准方案,这也是生产环境几乎所有无状态应用都使用Deployment部署的根本原因。

相关推荐
顾默@2 小时前
双系统Ubuntu18.04升级22.04,安装docker进行openclaw安装
运维·docker·容器
蜀道山老天师3 小时前
Docker Compose 多容器编排实战:LNMP、Tomcat 集群、云桌面、Portainer、Zabbix 一键部署
运维·docker·容器·tomcat·zabbix
见牛羊4 小时前
docker理解
java·docker·容器
ん贤5 小时前
Higress 详细笔记
笔记·云原生·higress
IT策士7 小时前
Docker 从 0 到 1 再到 Kubernetes 实战:第18篇 从 Docker Compose 到 Kubernetes 的思考
docker·容器·kubernetes
linmengmeng_13147 小时前
【总结】Docker 容器重建后 Nginx 502 问题排查与解决
nginx·docker·容器
qq_356408667 小时前
Kubernetes Rook-Ceph 高可用存储部署文档
ceph·容器·kubernetes
Plastic garden7 小时前
Docker(3)Docker 镜像 & Dockerfile
运维·docker·容器
m0_740859627 小时前
Docker安装常见数据库命令汇总(2026)
数据库·docker·容器