更新 Deployment 而不中断服务

更新 Deployment 而不中断服务

本文介绍如何使用滚动更新将运行中的 Deployment 更新到新版本。滚动更新会逐步用新 Pod 替换旧 Pod,因此你的应用在整个更新过程中保持可用。

教程目标

  • 触发 Deployment 的滚动更新。
  • 监控上线进度。
  • 暂停和恢复上线。
  • 配置滚动更新策略参数。
  • (如果需要)回滚到之前的版本。

准备开始

你必须拥有一个 Kubernetes 的集群,且必须配置 kubectl 命令行工具让其与你的集群通信。 建议运行本教程的集群至少有两个节点,且这两个节点不能作为控制平面主机。 如果你还没有集群,你可以通过 Minikube 构建一个你自己的集群,或者你可以使用下面的 Kubernetes 练习环境之一:

你需要一个已存在的 Deployment。如果你还没有, 可以按照使用 Deployment 运行无状态应用中的说明创建一个 nginx Deployment:

kubectl apply -f https://k8s.io/examples/application/deployment.yaml

验证该 Deployment 运行了两个 Pod:

kubectl get deployment nginx-deployment

输出类似于这样:

NAME               READY   UP-TO-DATE   AVAILABLE   AGE
nginx-deployment   2/2     2            2           10s

执行滚动更新

对 Deployment 的 .spec.template 字段的任何更改都会触发滚动更新。 Kubernetes 会使用更新后的配置创建新 Pod,并逐步终止旧 Pod。

使用 kubectl apply 进行更新

你可以通过编辑 Deployment 清单文件并应用更改来触发滚动更新。 当你将清单文件保存在版本控制中时,这种方法效果很好。

将当前 Deployment 导出到本地文件:

kubectl get deployment nginx-deployment -o yaml > /tmp/nginx-deployment.yaml

编辑 /tmp/nginx-deployment.yaml,将 .spec.template.spec.containers[0].imagenginx:1.14.2 改为 nginx:1.16.1

在应用之前,将本地更改与集群状态进行比较:

kubectl diff -f /tmp/nginx-deployment.yaml

输出类似于这样:

diff -u -N /tmp/LIVE/apps.v1.Deployment.default.nginx-deployment /tmp/MERGED/apps.v1.Deployment.default.nginx-deployment
--- /tmp/LIVE/apps.v1.Deployment...
+++ /tmp/MERGED/apps.v1.Deployment...
@@ -29,7 +29,7 @@
       containers:
-      - image: nginx:1.14.2
+      - image: nginx:1.16.1
         name: nginx

应用更新后的清单:

kubectl apply -f /tmp/nginx-deployment.yaml

仅更新容器镜像

要在不编辑清单文件的情况下更新容器镜像,请使用 kubectl set image

kubectl set image deployment/nginx-deployment nginx=nginx:1.16.1

输出类似于这样:

deployment.apps/nginx-deployment image updated

验证镜像已更新:

kubectl get deployment nginx-deployment -o jsonpath='{.spec.template.spec.containers[0].image}'

输出类似于这样:

nginx:1.16.1

监控上线进度

使用 kubectl rollout status 来观察滚动更新的进度:

kubectl rollout status deployment/nginx-deployment

输出类似于这样:

Waiting for deployment "nginx-deployment" rollout to finish: 1 out of 2 new replicas have been updated...
Waiting for deployment "nginx-deployment" rollout to finish: 1 out of 2 new replicas have been updated...
Waiting for deployment "nginx-deployment" rollout to finish: 1 old replicas are pending termination...
deployment "nginx-deployment" successfully rolled out

上线完成后,验证该 Deployment:

kubectl get deployment nginx-deployment

输出类似于这样:

NAME               READY   UP-TO-DATE   AVAILABLE   AGE
nginx-deployment   2/2     2            2           2m

暂停和恢复上线

你可以暂停上线过程,以便检查部分更新或将多个更改合并到一次上线中。

暂停上线

kubectl rollout pause deployment/nginx-deployment

输出类似于这样:

deployment.apps/nginx-deployment paused

暂停期间进行其他更改

当上线暂停时,你可以进行其他更改。这些更改在你恢复上线之前不会触发新的上线:

kubectl set image deployment/nginx-deployment nginx=nginx:1.17.0

说明:

你可以对暂停的 Deployment 进行多次更改。当你恢复上线时,Kubernetes 会将所有更改一起应用。

恢复上线

kubectl rollout resume deployment/nginx-deployment

输出类似于这样:

deployment.apps/nginx-deployment resumed

验证上线是否完成:

kubectl rollout status deployment/nginx-deployment

配置滚动更新策略

Deployment 支持两种更新策略类型

  • RollingUpdate(默认):逐步用新 Pod 替换旧 Pod。
  • Recreate:在创建新 Pod 之前终止所有现有 Pod。这会导致停机。

对于 RollingUpdate 策略,以下参数控制 Kubernetes 执行更新的方式:

参数控制内容默认值示例
maxUnavailable更新期间不可用 Pod 的最大数量25%125%
maxSurge更新期间允许创建的额外 Pod 的最大数量25%125%

说明:

maxUnavailablemaxSurge 接受绝对数值或百分比。Kubernetes 基于所需副本数计算百分比, 对 maxUnavailable 向下取整,对 maxSurge 向上取整。

要配置这些参数,请使用 kubectl patch

kubectl patch deployment nginx-deployment -p \
  '{"spec":{"strategy":{"rollingUpdate":{"maxUnavailable":"25%","maxSurge":"25%"}}}}'

你也可以在 Deployment 清单的 .spec.strategy.rollingUpdate 下设置这些字段。有关详细示例,请参阅 Deployment 概念文档中的最大不可用数量最大峰值

检测停滞的上线

如果上线过程在 .spec.progressDeadlineSeconds(默认:600 秒)指定的时间内没有进展,Kubernetes 会将 Deployment 的 Progressing 状况标记为 False。你可以通过描述 Deployment 来检查此状况:

kubectl describe deployment nginx-deployment

在输出的 Conditions 部分查找 Progressing 状况。停滞的上线通常表明新 Pod 启动失败。输出的 Events 部分可以帮助诊断问题。

回滚到之前的版本

如果新版本引入了问题,你可以回滚到之前的版本。

查看上线历史

kubectl rollout history deployment/nginx-deployment

输出类似于这样:

deployment.apps/nginx-deployment
REVISION  CHANGE-CAUSE
1         <none>
2         <none>

说明:

CHANGE-CAUSE 列显示每个版本对应时刻 kubernetes.io/change-cause 注解的值。 此注解不会被自动设置,但如果你使用自动化方案来管理 Deployment,你所使用的工具可能会将一些文本写入该注解。

回滚到上一个版本

kubectl rollout undo deployment/nginx-deployment

输出类似于这样:

deployment.apps/nginx-deployment rolled back

回滚到特定版本

kubectl rollout undo deployment/nginx-deployment --to-revision=1

验证回滚是否完成:

kubectl rollout status deployment/nginx-deployment

说明:

Deployment 的版本历史存储在其控制的 ReplicaSet 中。默认情况下,Kubernetes 会保留 10 个旧 ReplicaSet。你可以通过在 Deployment 清单中设置 .spec.revisionHistoryLimit 来更改此限制。 将其设置为 0 将完全禁用回滚。

清理现场

删除该 Deployment:

kubectl delete deployment nginx-deployment

接下来

最后修改 August 04, 2026 at 10:13 AM PST: [zh] Add update-deployment-rolling.md (d9c496c137)