k8s容器编排技术实践------k8s对象service应用详解
https://blog.csdn.net/xiaochenXIHUA/article/details/161593299k8s容器编排技术实践------K8s对象deployment应用详解
https://coffeemilk.blog.csdn.net/article/details/161427275
一、k8s的滚动更新简介
当某个服务需要升级时,传统的做法是,先将要更新的服务下线,业务停止后再更新版本和配置,然后重新启动服务。如果业务集群规模较大时,这个工作就变成了一个挑战,而且全部停止了服务,再逐步升级的方式会导致服务较长时间不可用。针对这个问题,k8s提供了滚动更新(rolling-update)的方式来解决这些问题。
滚动更新是针对pod来操作的,它通过一次只更新一小部分副本,成功后,再更新更多的副本,最终完成所有副本的更新。滚动更新的最大的好处是零停机,整个更新过程始终有副本在运行,从而保证了服务的连续性
1.1、滚动更新是什么
滚动更新是 K8s Deployment 默认的升级策略 ,核心逻辑:分批、逐步创建新版本 Pod,等新 Pod 就绪后再删除旧 Pod,新旧实例短时并存、循序渐进替换,全程不一次性关停所有业务。
配置:spec.strategy.type: RollingUpdate,Deployment 默认开启。
两个核心控制参数:
-
maxSurge:升级期间最多额外新增的 Pod 数量 / 比例(默认 25%),控制多扩多少新实例; -
maxUnavailable:升级期间最大不可用旧 Pod 比例 / 数量(默认 25%),控制同时下线多少旧实例。举例:副本 4 个、默认参数:每次最多新增 1 个新 Pod,最多下线 1 个旧 Pod,循环迭代完成全量更新。
1.2、滚动更新有啥用
| 滚动更新有啥用 | 说明 |
|---|---|
| 实现应用不停机升级,保障业务连续性 | Service 通过标签负载均衡自动把流量调度到就绪的新 Pod,升级全程服务不中断,满足 7×24 高可用 SLA。 |
| 平滑迭代版本 | 镜像升级、BUG 修复、环境变量 / 配置修改不用关停整站。 |
| 快速故障回滚 | 新版本异常,执行kubectl rollout undo deploy xxx反向滚动,分批切回旧版本。 |
| 节约资源 | 只临时扩容少量 Pod,不用提前准备一整套备用环境。 |
1.3、滚动更新的适用场景
| ✅滚动更新的适用场景 | 说明 |
|---|---|
| 绝大多数无状态微服务 / WEB 业务(最主流) | Java 后端、Nginx 网关、前端服务、API 接口、微服务集群(SpringCloud/Dubbo); |
| 不能中断的在线业务 | 电商、SAAS、支付、政企系统、线上生产环境常规小版本迭代; |
| 资源有限,无法承担双倍机器资源 | 蓝绿部署需要两套全量环境 |
| 小补丁、配置微调、小版本迭代上线 |
| ❌滚动更新不适用场景 | 说明 |
|---|---|
| 有状态应用(MySQL、Redis 集群、MongoDB) | 分批启停容易造成主从同步异常、数据不一致; |
| 新旧版本 API 完全不兼容 | 更新过程新旧实例并存,部分请求到老版本、部分到新版本,接口报错; |
| 需要瞬时全量切流验证新版本(需要蓝绿部署) | 小流量灰度验证(需要金丝雀发布) |
1.4、滚动更新的优缺点
| ✅滚动更新的优点 | 说明 |
|---|---|
| 零停机发布 | 生产环境业务无中断,线上用户无感知; |
| 资源开销小 | 仅临时多出少量 Pod(maxSurge),相比蓝绿部署节省一倍服务器成本; |
| 原生 K8s 支持,开箱即用 | 无需额外部署灰度 / 发布组件; |
| 更新节奏可控 | 通过调整maxSurge/maxUnavailable实现慢速分批发布,出现异常及时停止; |
| 回滚简单 | 一键回滚,反向滚动恢复旧版本。 |
| ❌滚动更新的缺点 | 说明 |
|---|---|
| 发布耗时长 | 实例数量多时,逐个分批替换,全量升级周期很长; |
| 升级过程新旧版本共存 | 若前后版本接口、数据协议不兼容,会出现线上混合报错; |
| 无法瞬间全量切换新版本 | 不能一键 100% 切新版本流量,想要瞬时全量切换需要蓝绿; |
| 有状态服务兼容性差 | 数据库、缓存集群慎用,容易引发集群故障; |
| 故障定位麻烦 | 线上同时跑两个版本代码,问题难以区分是新 / 旧版本 BUG。 |
1.5、滚动更新、蓝绿部署、金丝雀发布对比
| 发布方式 | 核心特点 | 资源 | 风险 |
|---|---|---|---|
| 滚动更新 | 分批逐步替换,慢慢切流 | 低,仅少量临时扩容 | ⭐⭐ 中等 |
| 蓝绿部署 | 两套完整环境,全量部署完一键切 Service | 高,双倍资源 | ⭐⭐ 低 |
| 金丝雀发布 | 少量实例先升级验证,没问题再全量滚动 | 介于两者之间 | ⭐ 极低 |
金丝雀发布 = 最安全的生产发布方案( 它的核心价值是:用最小的流量代价,验证最大的发布风险,是互联网公司核心业务的标配发布策略)。
简单记:滚动更新求快,蓝绿部署求稳,金丝雀发布求安全。
| 对比维度 | 滚动更新 (RollingUpdate) | 蓝绿部署 (Blue-Green) | 金丝雀发布 (Canary) |
|---|---|---|---|
| 核心原理 | 逐步创建新 Pod,逐步删除旧 Pod | 同时运行新旧两套完整环境,切换流量 | 先上线少量新版本,小流量验证后全量 |
| 流量切换 | 自动均匀分流,渐进式替换 | 瞬间 100% 全量切到新版本 | 自定义比例(1%/5%/10%)精准控流 |
| 资源消耗 | 极低(仅临时多几个 Pod) | 极高(双倍服务器资源) | 低(仅多 1~2 个金丝雀 Pod) |
| 发布风险 | ⭐⭐ 中等 | ⭐ 低 | ⭐ 极低(最安全) |
| 发布速度 | 较慢(分批耗时) | 极快(一键切流) | 较慢(需要验证等待) |
| 回滚方式 | 反向分批替换 | 一键切回旧环境 | 直接删除金丝雀 / 切回流量 |
| 回滚速度 | 较慢 | 秒级 | 秒级 |
| K8s 原生支持 | ✅ 原生自带(Deployment 默认) | ❌ 手动 / 简单配置实现 | ❌ 原生仅简易版,需组件控流 |
| 核心优势 | 零停机、省资源、开箱即用 | 无版本共存、切换 / 回滚极速 | 风险最小,不影响大部分用户 |
| 核心劣势 | 新旧版本短时共存 | 浪费双倍资源 | 流程复杂,需要监控配合 |
把发布新版本 比作饭店换菜单:
- 滚动更新:厨师一边做新菜,一边撤旧菜,分批替换,不耽误客人吃饭,最省成本;
- 蓝绿部署 :直接开第二个一模一样的厨房,新菜全部做好后,瞬间把老菜单换成新菜单;
- 金丝雀发布 :先给1 桌客人上新菜试吃,没问题再给所有客人换,出问题只影响这 1 桌。
二、k8s中滚动更新实现
部署一个httpd应用,指定三个副本,初始镜像为 httpd:2.4.60,然后将其更新到 httpd:2.4.67,详细操作步骤如下:
bash
#实现滚动更新示例
#一、创建初始的低版本httpd资源
#1.1-创建httpd2.4.60-deployment.yml资源文件
cat>httpd2.4.60-deployment.yml<<EOF
apiVersion: apps/v1
kind: Deployment
metadata:
name: httpd-deployment
spec:
replicas: 3
selector:
matchLabels:
app: httpd
template:
metadata:
labels:
app: httpd
spec:
containers:
- name: httpd
image: httpd:2.4.60
ports:
- containerPort: 80
EOF
#1.2-创建httpd2.4.60-deployment.yml资源
kubectl apply -f httpd2.4.60-deployment.yml
#1.3-查看当前所有pod的详细状态
kubectl get pod -o wide
#1.4-查看当前的所有pod副本状态详情(可查看到镜像、标签、pod列表等内容)
kubectl get replicaset -o wide
#1.5-查看当前所有的Deployment(应用顶层控制器)的状态详情(可查看到容器名、镜像版本、标签选择器)
kubectl get deploy -o wide
#二、创建高版本的httpd资源
#2.1-创建httpd2.4.67-deployment.yml资源文件
cat>httpd2.4.67-deployment.yml<<EOF
apiVersion: apps/v1
kind: Deployment
metadata:
name: httpd-deployment #注意:这个原数据的名称一定不能改变,否则就是一个新的deployment了!!!
spec:
replicas: 3
selector:
matchLabels:
app: httpd
template:
metadata:
labels:
app: httpd
spec:
containers:
- name: httpd
image: httpd:2.4.67
ports:
- containerPort: 80
EOF
#2.2-创建httpd2.4.67-deployment.yml资源
kubectl apply -f httpd2.4.67-deployment.yml
#2.3-查看当前所有pod的详细状态
kubectl get pod -o wide
#2.4-查看当前的所有pod副本状态详情(可查看到镜像、标签、pod列表等内容)
kubectl get replicaset -o wide
#2.5-查看当前所有的Deployment(应用顶层控制器)的状态详情(可查看到容器名、镜像版本、标签选择器)
kubectl get deploy -o wide
#2.6-查看指定deployment的状态详情(可查看到滚动更新的详情)
kubectl describe deploy httpd-deployment



执行kubectl get replicaset -o wide命令与kubectl describe deploy httpd-deployment后可以发现:
新创建的ReplicaSet镜像为httpd:2.4.67,并且管理了三个新的 Pod。而老的ReplicaSet里面已经没有任何Pod。结论是老的ReplicaSet的三个httpd:2.4.60 Pod 已经被新的ReplicaSet的三个httpd:2.4.67 Pod逐渐替换了。
三、k8s中版本回滚实现
在执行kubectl apply命令更新应用时,K8s都会记录下当前的配置,保存为一个revision(版本),通过这个版本记录,就可以回滚到某个特定的revision。默认配置下,K8s只会保留最近的几个版本,不过可以在Deployment配置文件中通过revisionHistoryLimit属性增加revision的数量。
bash
#k8s中版本回滚实现
#1、创建三个deployment资源文件httpd2.4.60-rolldeployment.yml、httpd2.4.65-rolldeployment.yml、httpd2.4.67-rolldeployment.yml;
cat>httpd2.4.60-rolldeployment.yml<<EOF
apiVersion: apps/v1
kind: Deployment
metadata:
name: httpd-roll-deployment
spec:
revisionHistoryLimit: 10
replicas: 3
selector:
matchLabels:
app: httpd
template:
metadata:
labels:
app: httpd
spec:
containers:
- name: httpd
image: httpd:2.4.60
ports:
- containerPort: 80
EOF
cat>httpd2.4.65-rolldeployment.yml<<EOF
apiVersion: apps/v1
kind: Deployment
metadata:
name: httpd-roll-deployment
spec:
revisionHistoryLimit: 10
replicas: 3
selector:
matchLabels:
app: httpd
template:
metadata:
labels:
app: httpd
spec:
containers:
- name: httpd
image: httpd:2.4.65
ports:
- containerPort: 80
EOF
cat>httpd2.4.67-rolldeployment.yml<<EOF
apiVersion: apps/v1
kind: Deployment
metadata:
name: httpd-roll-deployment
spec:
revisionHistoryLimit: 10
replicas: 3
selector:
matchLabels:
app: httpd
template:
metadata:
labels:
app: httpd
spec:
containers:
- name: httpd
image: httpd:2.4.67
ports:
- containerPort: 80
EOF
#2、开始创建httpd2.4.60-rolldeployment.yml资源
kubectl apply -f httpd2.4.60-rolldeployment.yml --record
kubectl get deploy -o wide
kubectl get pod
kubectl describe deploy httpd-roll-deployment
#3-开始滚动更新httpd2.4.65-rolldeployment.yml资源,然后查看对应的deploy与pod状态详情
kubectl apply -f httpd2.4.65-rolldeployment.yml --record
kubectl get deploy -o wide
kubectl get pod
kubectl describe deploy httpd-roll-deployment
kubectl describe pod httpd-roll-deployment-79c57c7bcf-jvxhn
kubectl get replicaset -o wide
#4-开始滚动更新httpd2.4.67-rolldeployment.yml资源,然后查看对应的deploy与pod状态详情
kubectl apply -f httpd2.4.67-rolldeployment.yml --record
kubectl get deploy -o wide
kubectl get pod
kubectl describe deploy httpd-roll-deployment
kubectl describe pod httpd-roll-deployment-67476867f7-qh4c5
kubectl get replicaset -o wide
#5-查看revison历史记录、与当前的deploy版本
kubectl rollout history deployment httpd-roll-deployment
kubectl get deploy -o wide
#6-回滚到指定版本(如回滚到revision 2【即httpd2.4.65】)
kubectl rollout undo deployment httpd-roll-deployment --to-revision=2
#7-再次查看revison历史记录、与当前的deploy版本
kubectl rollout history deployment httpd-roll-deployment
kubectl get deploy -o wide






回滚执行完成后,revison历史记录也会发生相应变化,从如上从输出可以看出,回滚后,revison 2变成了revison 4。因此,有回滚需求的话,一定要在执行kubectl apply时加上 --record参数(这样在revison历史记录中可以清晰的了解到序号对应的版本内容,方便区分)。