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部署的根本原因。

相关推荐
运维老郭8 小时前
【K8s运维实战】Kubernetes临时存储卷实战:emptyDir核心用法与gitRepo弃用迁移指南
运维·云原生·kubernetes
AAA@峥12 小时前
容器数据不丢失:Docker 分层存储 + Volume 共享、备份迁移完整指南
运维·docker·容器
十年磨一剑~14 小时前
docker 为何每次 docker tag才能 docker push
docker·容器·eureka
gs8014016 小时前
记一次多 Agent 架构在单节点 K8s 触发的 PID 耗尽与 Pod 驱逐(Evicted)大摸排
容器·架构·kubernetes
bukeyiwanshui16 小时前
20260701 k8s Metric Server
容器·贪心算法·kubernetes
江湖有缘17 小时前
基于Docker环境部署tillywork开源工作管理工具
docker·容器·开源
鸿儒51719 小时前
MR-50国产化GPU docker配置方法
docker·容器·mr
Zhu75820 小时前
在k8s集群部署ApacheHadoop单节点单数据副本
云原生·容器·kubernetes
Akamai中国20 小时前
Akamai收购安全企业浏览器提供商LayerX
人工智能·云原生·云计算·云服务