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

相关推荐
小猿姐1 天前
MySQL Top 10 热点问题 AI 运维实战:从内核诊断到云原生运维
mysql·云原生·aiops
阿里云云原生2 天前
深入内核:拆解 OpenTelemetry eBPF 探针如何优雅地“透视”多语言微服务?
云原生
2601_961875242 天前
决战申论100题2026|最新|范文
linux·容器·centos·debian·ssh·fabric·vagrant
java_cj2 天前
深入kube-apiserver认证机制:从Bearer Token到mTLS的完整认证链解析
linux·运维·服务器·云原生·容器·kubernetes
程序员老赵2 天前
服务器没有桌面?Docker 跑个 Chrome,浏览器就能远程用
docker·容器·devops
正经教主2 天前
【docker基础】 第八周:容器监控与应用更新策略
运维·docker·容器
kiros_wang2 天前
Docker 使用完整指南
运维·docker·容器
正经教主2 天前
【docker基础】第九周:Docker安全与镜像优化
运维·docker·容器
qq_452396232 天前
第十三篇:《K8s 安全基础:RBAC、ServiceAccount、Pod Security》
java·安全·kubernetes
睡不醒男孩0308233 天前
云原生运维实战:高并发架构下的云原生可观测性、韧性降级与自动化干预体系
数据库·kubernetes·高并发·prometheus·devops·sre·缓存调优