一文读懂Deployment以及实践攻略

在这里插入图片描述

❤️ 摘要:本文详细介绍了Kubernetes中Deployment的概念及其实践攻略。Deployment是一种用于管理一组Pod的工作负载,主要负责应用的部署、更新及回滚等操作。文章首先解释了Deployment的基本概念,包括其如何管理Pod、与ReplicaSet的关系以及生命周期状态。接着,通过一系列实践案例,展示了如何创建、更新、回滚及扩展Deployment。此外,还介绍了如何暂停和恢复Deployment的rollout流程。通过这些详细的步骤和示例,读者可以更好地理解和掌握Deployment的使用方法。

目录

1 概念

1.1 什么是Deployment

Deployment是用于管理一组 Pod从而运行应用程序的工作负载,通常是无状态的工作负载。

Deployment 就像是一位“项目经理”,负责规划和监督整个应用的运行。它定义了应用如何部署、多少副本运行、更新的方式等重要策略。通过使用 Deployment,用户可以轻松管理应用的滚动更新、扩展副本数量、回滚到之前的版本,确保应用在任何时候都能正常工作。

1.2 Deployment 如何管理 Pod?

上一篇导航: 《一文读懂Pod以及实践攻略》

前文所述,Pod 是 Kubernetes 中最小的计算单元,承载着应用的容器。Deployment 就像是一个“指挥官”,它可以告诉 Kubernetes 需要启动多少个 Pod;在运行时持续监控这些Pod,在更新时实现不影响用户体验完成更新或者Pod扩容和缩容。

举个例子,如果一个网站需要始终保持 3 个 Pod 在运行,Deployment 就会确保无论发生什么情况(比如某个 Pod 崩溃或更新),都会有 3 个副本保持在线,像是“纪律严明的运维团队”,确保始终有人在岗位上。

Deployment 还可以控制应用的滚动更新。当我们需要更新应用时,Deployment 会“有条不紊”地逐一更新 Pod,而不是一下子重启所有,避免服务中断,就像在流水线上逐步替换零件一样高效安全。

❔ 说明: Deployment 处于 master 节点上,通过发布 Deployment,master 节点会选择合适的 worker 节点创建 Container(即图中的正方体),Container 会被包含在 Pod (即蓝色圆圈)里。

1.3 Deployment 与 ReplicaSet 的关系

在pod的管理中, Deployment是明面的管理者,但是ReplicaSet才是管理 Pod 副本的真正“执行者”,负责根据指令启动或终止特定数量的 Pod。可以把 ReplicaSet 想象成是 Deployment 手下的“组长”,而Pod就是实际干活的人。当 Deployment 下达指令时,ReplicaSet 会具体执行这些命令,比如生成指定数量的 Pod 副本。

Deployment 实际上管理着多个 ReplicaSet。每次 Deployment 更新时,都会生成一个新的 ReplicaSet,并逐步将流量从旧的 ReplicaSet 切换到新的ReplicaSet,这样确保在更新过程中不会出现应用中断的情况。而旧的 ReplicaSet 也可以在回滚时被重新启用。

⚠️ 不要尝试绕过Deployment,直接操作现有的Replica, 这样可能导致Deployment无法有效管理Pod。

1.4 Deployment的生命周期状态

Deployment在其生命周期中会进入不同状态, 状态清单如下:

状态可能情况
progressing1) Deployment 创建一个新的 ReplicaSet。 2) Deployment 正在扩展其最新的 ReplicaSet。 3) Deployment 正在缩减其旧的 ReplicaSet。 4) 新 Pod 准备就绪或可用(至少准备MinReadySeconds )。
complete1)与部署关联的所有副本均已更新至您指定的最新版本,这意味着您请求的所有更新均已完成。 2)与部署关联的所有副本均可用。 3)部署的旧副本没有正在运行。
fail to progress1)配额不足 2) 就绪探针故障 3) 镜像拉取错误 4) 权限不足 5) 限制范围 6)应用程序运行时配置错误

2 Deployment的实践

假设我们需要在 Kubernetes 集群中部署一个简单的 Web 应用(如 nginx),要求它有 3 个副本,实践在应用部署、更新、回滚和扩展的过程。

2.1 创建Deployment

编辑nginx-deployment.yaml,定义一个 ReplicaSet 来启动三个nginx Pod:

apiVersion: apps/v1
kind: Deployment
metadata:
# 定义Deployment的名字
  name: nginx-deployment
  labels:
    app: nginx
spec:
  # 定义副本数
  replicas: 3
  # 选择器指定label与pod模板的label匹配
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
    # 与选择器指定label匹配
      labels:
        app: nginx
    spec:
      containers:
      # pod名字,可自定义
      - name: nginx
      # 镜像源, 这里设置私有镜像源
        image: harbor.zx/hcie/nginx:1.26.1
      # pod暴露端口号
        ports:
        - containerPort: 80
          name: http
          protocol: TCP

运行以下命令部署

kubectl apply -f nginx-deployment.yaml

检查 Deployment 是否已创建

[root@k8s-master1 hcie]# kubectl get deployments
NAME                              READY   UP-TO-DATE   AVAILABLE   AGE
nginx-deployment                  3/3     3            3           104m

❔ 说明: 当您检查集群中的部署时,会显示以下字段:

字段说明
NAME列出命名空间中部署的名称。
READY显示有多少个应用程序副本可供用户使用。它遵循准备/期望的模式。
UP-TO-DATE显示已更新以达到所需状态的副本数量。
AVAILABLE显示有多少个应用程序副本可供您的用户使用。
AGE显示应用程序已运行的时间量。

2.1.1 Deployment的pod如何命名?

ReplicaSet 的名称始终采用[DEPLOYMENT-NAME]-[HASH]格式,该名称将成为创建的 Pod 的前缀。HASH字符串与 ReplicaSet 上的pod-template-hash标签相同。

可以执行以下命令查看到pod-template-hash标签。

1)查看Replicaset的label

[root@k8s-master1 hcie]# kubectl get rs --show-labels
NAME                                         DESIRED   CURRENT   READY   AGE    LABELS
nginx-deployment- 64db67d8bc                   3         3         3       114m   app=nginx, pod-template-hash=64db67d8bc

2) 查看pod的label

[root@k8s-master1 hcie]# kubectl get pod --show-labels
NAME                                               READY   STATUS    RESTARTS   AGE    LABELS
nginx-deployment- 64db67d8bc -h6vsv                  1/1     Running   0          113m   app=nginx, pod-template-hash=64db67d8bc 
nginx-deployment-64db67d8bc-lf57x                  1/1     Running   0          113m   app=nginx,pod-template-hash=64db67d8bc
nginx-deployment-64db67d8bc-ljh85                  1/1     Running   0          113m   app=nginx,pod-template-hash=64db67d8bc
  • 可以看到replicaset的label会被关联的pod继承;
  • 同时也是replicaset通过label关联pod
[root@k8s-master1 hcie]# kubectl get rs -oyaml
...
    selector:
      matchLabels:
         app: nginx
        pod-template-hash: 64db67d8bc

⚠️ 注意不要让多个控制器(如 Deployment、StatefulSet)使用相同的标签(labels)和选择器(selectors)来管理 Pod。Kubernetes 不会自动阻止这种重叠,但如果多个控制器同时选择并尝试管理同一组 Pod,可能会导致意外行为或冲突。

⚠️ 警告:不要尝试修改selector和pod-template现有的标签,否则导致ReplicaSet无法管理关联的pod。

2.2 更新Deployment

❔ 说明: 当且仅当 Deployment 的 Pod 模板(即.spec.template )发生更改(例如,模板的标签或容器映像更新)时,才会触发 Deployment 的滚动更新。

执行以下命令,更新 nginx Pod 的映像使用nginx:1.27.1代替 nginx:1.26.1

kubectl set image deployment/nginx-deployment nginx=harbor.zx/hcie/nginx:1.27.1

  • 其中, deployment/nginx-deployment表示部署, nginx表示将进行更新的容器, nginx:1.27.1表示新映像及其标签。
  • 或者执行edit命令并修改 .spec.template.spec.containers[0].imagenginx:1.26.1nginx:1.27.1
kubectl edit deployment/nginx-deployment

执行以下命令,查看部署状态:

kubectl rollout status deployment/nginx-deployment

输出类似于:


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

部署成功后,您可以通过kubectl get deployments查看 Deployment信息

[root@k8s-master1 hcie]# kubectl get deployments nginx-deployment -owide
NAME               READY   UP-TO-DATE   AVAILABLE   AGE    CONTAINERS   IMAGES                        SELECTOR
nginx-deployment   3/3     3            3           141m   nginx         harbor.zx/hcie/nginx:1.27.1    app=nginx

执行kubectl get rs可以看到 Deployment 通过创建新的 ReplicaSet 并将其扩展到 3 个副本,以及将旧的 ReplicaSet 缩减到 0 个副本来更新 Pod。

[root@k8s-master1 hcie]# kubectl get rs
NAME                                         DESIRED   CURRENT   READY   AGE
nginx-deployment-546946b498                  3         3         3       3m10s
nginx-deployment-5dd79cf485                  0         0         0       10m

❔ 说明: 输出字段说明

字段说明定义
NAMEReplicaSet的名称上面已说明,字段组成是[DEPLOYMENT-NAME]-[HASH]
DESIRED期望的 Pod 数量该字段显示的是 ReplicaSet 中希望维持的 Pod 副本数量。这个值是根据 ReplicaSet 的 spec.replicas 来设置的,代表应用正常运行时需要的 Pod 数量。
CURRENT当前的 Pod 数量该字段显示的是当前由 ReplicaSet 管理的 Pod 的实际数量。这个值可能小于或等于 DESIRED,具体取决于是否正在进行扩容、缩容或滚动更新。
READY准备好的 Pod 数量。该字段显示的是处于 Ready 状态并且可以接受流量的 Pod 数量。Pod 只有在所有的健康检查(如 readiness probe)通过之后才会被认为是 “Ready”。
AGEReplicaSet 存在的时间。该字段表示该 ReplicaSet 自创建以来的持续时间,单位通常为秒s、分钟m、小时h或天d

❓ 思考: Deployment的更新过程怎么执行的? 如何从旧的pod过渡到新的pod?

  • 通常,滚动更新(Rolling Update)是 Deployment 的默认更新策略,它允许在更新过程中逐步替换旧的 Pod,而不是直接销毁所有旧 Pod,从而保证应用始终有足够的可用实例来处理请求。
  • 例如:当 Deployment 控制器观察到新的 Deployment 时,会创建一个 ReplicaSet 来启动所需的 Pod。如果更新了Deployment,那么控制标签与.spec.selector匹配但模板内容与.spec.template不匹配的 ReplicaSet会将所属的Pod缩放为 0,而新的 ReplicaSet 所属的pod被扩展为.spec.replicas 的数量。
  • 更新的关键参数有两个:maxUnavailablemaxSurge,它们控制了在更新过程中 Pod 的替换策略。参数说明如下:
字段说明可能值作用
maxUnavailablemaxUnavailable 指定在更新过程中,最多有多少个 不可用的 Pod。换句话说,它控制了在更新过程中允许离线的 Pod 数量。1)该值可以是绝对数字,也可以是百分比。 2) 例如,maxUnavailable: 1 表示在更新过程中,最多可以有 1 个 Pod 处于不可用状态(即正在被删除或替换)。 3)如果设置为百分比,如 maxUnavailable: 25%,则表示最多有 25% 的 Pod 可以在更新过程中不可用。maxUnavailable 决定了集群在更新期间的可用性。如果这个值设置得太高,可能会在更新时造成较大的服务中断;设置得较低,更新速度则会减慢。
maxSurgemaxSurge 指定在更新过程中,允许临时多创建的 额外 Pod 数量。这些额外 Pod 会在旧 Pod 被删除之前创建,确保有足够的新 Pod 在更新时提前准备好。1)该值也可以是绝对数字或者百分比。 2)例如,maxSurge: 2 表示更新过程中最多可以有 2 个额外的新 Pod 被创建。 3)如果设置为百分比,如 maxSurge: 50%,则表示更新过程中最多可以比所需的 Pod 副本数多创建 50% 的 Pod。maxSurge 控制了更新的速度和容量。通过增加额外的 Pod 副本,maxSurge 可以加快更新进程,确保新的 Pod 在旧的 Pod 被终止之前已经就绪,从而减少服务的影响。

RollingUpdateStrategy默认策略

执行以下命令,查看Deployment的详细信息:

kubectl describe deployments  nginx-deployment

输出如下:

Name:                   nginx-deployment
Namespace:              default
CreationTimestamp:      Thu, 05 Sep 2024 19:53:56 +0800
Labels:                 app=nginx
Annotations:            deployment.kubernetes.io/revision: 3
Selector:               app=nginx
Replicas:               3 desired | 3 updated | 3 total | 3 available | 0 unavailable
StrategyType:           RollingUpdate
MinReadySeconds:        0
 RollingUpdateStrategy:  25% max unavailable, 25% max surge

❔ 说明:

  • 默认情况下,它确保至少有 75% 的所需 Pod 数量处于运行状态(最多 25% 不可用)。
  • 默认情况下,它确保最多 125% 的所需 Pod 数量处于启动状态(最大激增 25%)。
  • 如果你仔细观察上面的 Deployment更新过程,你会发现它首先创建了一个新的 Pod,然后删除了一个旧的 Pod,再创建了另一个新的 Pod。在出现足够数量的新 Pod 之前,它不会杀死旧 Pod;并且在杀死足够数量的旧 Pod 之前,它不会创建新 Pod。它确保至少有 3 个 Pod 可用,并且总共最多有 4 个 Pod 可用。

Terminating Pods 不被计入 availableReplicas

❓ 思考: 观察Deployment的更新过程时,会发现有时候pod的数量会大于所设置的replicas + maxSurge值。

当一个 Pod 被标记为 “终止”(Terminating)时,它可能还没有完全停止运行,比如还在处理请求或在等待资源释放。这些处于 “终止” 状态的 Pod 不会被计入 availableReplicas,即 Kubernetes 不会把这些正在终止的 Pod 视为可用的副本。

所以Pod 数量多于replicas + maxSurge的原因:

  • 旧 Pod 的延迟终止:当新 Pod 启动并开始处理流量时,旧的 Pod 可能还处于 “终止” 状态。这些终止中的 Pod 仍然在运行,虽然不计入 availableReplicas,但仍占用资源。
  • 新旧 Pod 共存:由于 maxSurge 的作用,Kubernetes 允许额外创建的新 Pod 在旧 Pod 被完全终止之前就已经开始工作。这可能会有replicas + maxSurge 更多 的 Pod 同时存在。

2.2.3 验证RollingUpdateStrategy策略

修改nginx-deployment.yaml的RollingUpdateStrategy策略

apiVersion: apps/v1
kind: Deployment
metadata:
# 定义Deployment的名字
  name: nginx-deployment
  labels:
    app: nginx
spec:
  # 定义副本数
  replicas: 5
  # 新增策略描述
  strategy:
    type: RollingUpdate
    rollingUpdate:
      # 最大不可用 Pod 数量
      maxUnavailable: 1
      # 最大新增 Pod 数量
      maxSurge: 1
  # 选择器指定label与pod模板的label匹配
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
    # 与选择器指定label匹配
      labels:
        app: nginx
    spec:
      containers:
      # pod名字,可自定义
      - name: nginx
      # 镜像源, 这里设置私有镜像源
        image: harbor.zx/hcie/nginx:1.26.1
      # pod暴露端口号
        ports:
        - containerPort: 80
          name: http
          protocol: TCP


查看deployment的状态

[root@k8s-master1 ~]# kubectl get deploy nginx-deployment
NAME               READY   UP-TO-DATE   AVAILABLE   AGE
nginx-deployment   5/5     5            5           96s

  • 可以看到5个pod都运行了。

执行以下命令,更新 nginx Pod 的映像使用nginx:1.27.1代替 nginx:1.26.1

kubectl set image deployment/nginx-deployment nginx=harbor.zx/hcie/nginx:1.27.1

执行以下命令观察rs更新的情况。

# 查看ReplicaSet执行情况
kubectl get rs -l app=nginx -w

直到pod数量达到5个, 暂停日志输出,并将日志保存到文件。

查看ReplicaSet执行日志,可以看到nginx-deployment-64db67d8bc是旧的RS,nginx-deployment-546946b498是新的RS。

# 这是新的RS
[root@k8s-master1 ~]# grep -e "nginx-deployment-546946b498" -e "NAME" rs-display.txt
NAME                          DESIRED   CURRENT   READY   AGE
nginx-deployment-546946b498   0         0         0       78m
nginx-deployment-546946b498   0         0         0       78m
nginx-deployment-546946b498   1         0         0       78m
nginx-deployment-546946b498   1         0         0       78m
nginx-deployment-546946b498   1         1         0       78m
nginx-deployment-546946b498   2         1         0       78m
nginx-deployment-546946b498   2         1         0       78m
nginx-deployment-546946b498   2         2         0       78m
nginx-deployment-546946b498   2         2         1       78m
nginx-deployment-546946b498   2         2         2       78m
nginx-deployment-546946b498   3         2         2       78m
nginx-deployment-546946b498   3         2         2       78m
nginx-deployment-546946b498   3         3         2       78m
nginx-deployment-546946b498   4         3         2       78m
nginx-deployment-546946b498   4         3         2       78m
nginx-deployment-546946b498   4         4         2       78m
nginx-deployment-546946b498   4         4         3       78m
nginx-deployment-546946b498   5         4         3       78m
nginx-deployment-546946b498   5         4         3       78m
nginx-deployment-546946b498   5         5         3       78m
nginx-deployment-546946b498   5         5         4       78m
nginx-deployment-546946b498   5         5         5       78m

# 这是旧的RS
[root@k8s-master1 ~]grep -e "nginx-deployment-64db67d8bc" -e "NAME" rs-display.txt
NAME                          DESIRED   CURRENT   READY   AGE
nginx-deployment-64db67d8bc   5         5         5       87m
nginx-deployment-64db67d8bc   4         5         5       87m
nginx-deployment-64db67d8bc   4         5         5       87m
nginx-deployment-64db67d8bc   4         4         4       87m
nginx-deployment-64db67d8bc   3         4         4       87m
nginx-deployment-64db67d8bc   3         4         4       87m
nginx-deployment-64db67d8bc   3         3         3       87m
nginx-deployment-64db67d8bc   2         3         3       87m
nginx-deployment-64db67d8bc   2         3         3       87m
nginx-deployment-64db67d8bc   2         2         2       87m
nginx-deployment-64db67d8bc   1         2         2       87m
nginx-deployment-64db67d8bc   1         2         2       87m
nginx-deployment-64db67d8bc   1         1         1       87m
nginx-deployment-64db67d8bc   0         1         1       87m
nginx-deployment-64db67d8bc   0         1         1       87m
nginx-deployment-64db67d8bc   0         0         0       87m

❔ 说明:

  • 日志输出与策略描述一致,新的RS与旧的RS并行执行;
  • 新RS的DESIRED数值按MaxSurge递增,旧RS的DESIRED数值按maxUnavailable递减
  • 当DESIRED等于CURRENT,RS才会继续向下执行递增(递减)。

2.2.4 多次更新并行时

❓ 思考: 如果在执行了Deployment的第一次更新操作后,立刻执行第二次更新操作,K8S会怎么处理呢?

如果你更新了正在进行更新任务的 Deployment,那么Deployment 会根据最新更新的模板内容来创建一个新的 ReplicaSet 并开始扩展,并将之前的ReplicaSet标志成旧的 ReplicaSet 并开始缩减。

例如,假设您创建一个 Deployment 来创建 5 个nginx:1.26.1副本,但随后更新该 Deployment 来创建 5 个nginx:1.27.1副本,而此时只创建了 3 个nginx:1.26.1副本。在这种情况下,Deployment 会立即开始终止其创建的 3 个nginx:1.26.1 Pod,并开始创建nginx:1.27.1 Pod。它不会等待nginx:1.26.1的 5 个副本创建后才改变方向。

2.2.5 验证多次更新并行时

还是沿用nginx-deployment,我们先将镜像更新为nginx:1.26.1,然后将镜像更新为nginx:stable

kubectl set image deployment/nginx-deployment nginx=harbor.zx/hcie/nginx:1.26.1

kubectl set image deployment/nginx-deployment nginx=harbor.zx/hcie/nginx:stable

在这过程,一直观察rs的状态

# 查看ReplicaSet执行情况
kubectl get rs -l app=nginx -w

直到pod数量达到5个, 暂停日志输出。

查看ReplicaSet执行日志,可以看到nginx-deployment-64db67d8bc是原RS,nginx-deployment-546946b498是第一次更新的RS,nginx-deployment-56968dfdd4是第二次更新的RS。


[root@k8s-master1 ~]# kubectl get rs -l app=nginx -w
NAME                          DESIRED   CURRENT   READY   AGE
nginx-deployment-546946b498   0         0         0       110m
nginx-deployment-5dd79cf485   0         0         0       112m
nginx-deployment-64db67d8bc   5         5         5       119m
#第一次更新的RS
nginx-deployment-546946b498   0         0         0       110m
nginx-deployment-546946b498   1         0         0       110m
nginx-deployment-64db67d8bc   4         5         5       119m
nginx-deployment-546946b498   1         0         0       110m
# 原RS进行删除
nginx-deployment-64db67d8bc   4         5         5       119m
nginx-deployment-546946b498   1         1         0       110m
nginx-deployment-546946b498   2         1         0       110m
nginx-deployment-64db67d8bc   4         4         4       119m
nginx-deployment-546946b498   2         1         0       110m
nginx-deployment-546946b498   2         2         0       110m
#第二次更新的RS
nginx-deployment-56968dfdd4   0         0         0       0s
nginx-deployment-56968dfdd4   0         0         0       0s
# 第一次更新的RS,DESIRED直接置为零,开始删第一次更新的Pod
nginx-deployment-546946b498   0         2         0       110m
nginx-deployment-546946b498   0         2         1       110m
#第二次更新的RS继续创建,直到到达Replica指定数量
nginx-deployment-56968dfdd4   2         0         0       0s
nginx-deployment-546946b498   0         2         1       110m
...
# 原RS删除直到pod为0
nginx-deployment-64db67d8bc   0         0         0       120m
nginx-deployment-56968dfdd4   5         5         5       50s

❔ 说明:

  • 当Deployment监听到更新指令时,新RS开始增加,旧RS开始删除
  • 当Deployment监听到第二次更新指令时, 立刻创建第二个新RS, 第一个新RS立刻删除;
  • 最终第二个新RS达到DESIRED数量, 第一个新RS和旧RS被删除。

2.3 回滚Deployment

2.3.1 模拟更新Deployment出错

例如,当 新部署的Deployment 不稳定时,例如应用出现循环崩溃,您可能想要回滚历史版本。默认情况下,所有更新历史记录都保留在系统中,以便您可以随时回滚(您可以通过修改修订历史记录限制来更改它)。

假设您在更新部署时,将映像名称拼写错误,设置为nginx:1.261

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

查询rollout状态,会发现会被卡住:

[root@k8s-master1 ~]# kubectl rollout status deployment/nginx-deployment
Waiting for deployment "nginx-deployment" rollout to finish: 2 out of 5 new replicas have been updated...

而RS的状态同样是卡住:

[root@k8s-master1 hcie]# kubectl get rs -l app=nginx
NAME                          DESIRED   CURRENT   READY   AGE
nginx-deployment-546946b498   0         0         0       130m
nginx-deployment-56968dfdd4   4         4         4       19m
nginx-deployment-5dd79cf485   0         0         0       132m
nginx-deployment-64db67d8bc   0         0         0       139m
nginx-deployment-f64455fb9    2         2         0       17s

查看pods状态,可以直观看到是镜像拉取出错

[root@k8s-master1 ~]# kubectl get pods -l app=nginx
NAME                                READY   STATUS             RESTARTS   AGE
nginx-deployment-56968dfdd4-6wpmt   1/1     Running            0          21m
nginx-deployment-56968dfdd4-k48mt   1/1     Running            0          22m
nginx-deployment-56968dfdd4-k9zq8   1/1     Running            0          22m
nginx-deployment-56968dfdd4-s7jpp   1/1     Running            0          22m
nginx-deployment-f64455fb9-7p6hw    0/1     ImagePullBackOff   0          2m56s
nginx-deployment-f64455fb9-h9d5h    0/1     ImagePullBackOff   0          2m57s

2.3.2 检查Deployment的Rollout历史记录

首先,检查此 Deployment 的修订(revisions),执行以下命令:

[root@k8s-master1 hcie]# kubectl rollout history deployment/nginx-deployment
deployment.apps/nginx-deployment
REVISION  CHANGE-CAUSE
2         <none>
8         <none>
9         <none>
10        <none>
11        <none>

❔ 说明:

  • 当触发deployment的rollout时,会创建deployment的修订版。这意味着当且仅当 Deployment 的 Pod 模板 ( .spec.template ) 发生更改时才会创建新修订版本,例如,如果您更新模板的标签或容器映像。
  • 原创建修订的方法,--record=true参数已经标记deprecated, 所以建议使用注释的方法;
  • CHANGE-CAUSE在创建时从deployment的注释kubernetes.io/change-cause复制到其修订版本。您可以通过以下方式指定CHANGE-CAUSE消息:
kubectl annotate deployment/nginx-deployment kubernetes.io/change-cause="image updated to 1.26.1"
  • 或者直接修改deployment的注释
kubectl edit deployment/nginx-deployment 
---
apiVersion: apps/v1
kind: Deployment
metadata:
  annotations:
    deployment.kubernetes.io/revision: "11"
    # 更新时新增注释
    kubernetes.io/change-cause: 1.26.1


然后,要查看上一个修订的详细信息,执行以下命令:

kubectl rollout history deployment/nginx-deployment --revision=10

输出如下:

deployment.apps/nginx-deployment with revision #10
Pod Template:
  Labels:       app=nginx
        pod-template-hash=56968dfdd4
  Containers:
   nginx:
    Image:      harbor.zx/hcie/nginx:stable
    Port:       80/TCP
    Host Port:  0/TCP
    Environment:        <none>
    Mounts:     <none>
  Volumes:      <none>

2.3.3 回滚到以前的修订

按照下面给出的步骤将 Deployment 从当前版本回滚到之前的版本,即版本 10。

现在可以撤消当前的rollout操作:

kubectl rollout undo deployment/nginx-deployment

输出如下:

deployment.apps/nginx-deployment rolled back

或者,直接指定历史版本回滚:

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

查看deployment状态

[root@k8s-master1 hcie]# kubectl describe deployments.apps nginx-deployment
Name:                   nginx-deployment
Namespace:              default
CreationTimestamp:      Mon, 09 Sep 2024 20:19:13 +0800
Labels:                 app=nginx
Annotations:             deployment.kubernetes.io/revision: 14 
Selector:               app=nginx
Replicas:               5 desired | 5 updated | 5 total | 5 available | 0 unavailable
StrategyType:           RollingUpdate
MinReadySeconds:        0
RollingUpdateStrategy:  1 max unavailable, 1 max surge
Pod Template:
  Labels:  app=nginx
  Containers:
   nginx:
    Image:         harbor.zx/hcie/nginx:1.27.1 
    Port:         80/TCP
    Host Port:    0/TCP
    Environment:  <none>
    Mounts:       <none>
  Volumes:        <none>

2.4 扩展Deployment

如果要临时对deployment进行扩展, 可以使用以下命令:

kubectl scale deployment/nginx-deployment --replicas=10

输出如下:

deployment.apps/nginx-deployment scaled

同样, 如果希望对deployment进行缩减,也可以执行该命令

kubectl scale deployment/nginx-deployment --replicas=3

❔ 说明: 后续文章会对K8S的HPA弹性扩展进行深入剖析,敬请期待。

2.5 暂停和恢复deployment的rollout

❔ 说明: 这个方法在实际场景比较少用到, 这里仅做功能介绍。

当您计划更新deployment时,您可能会做一项或多项更新操作,并希望暂停该deployment的rollout流程,当您准备好应用这些更改时,再恢复deployment的rollout流程。这种方法允许您在暂停和恢复之间应用多个修复,而不会触发不必要的rollout流程。

例如: 你可能需要对deployment更新镜像或者其他操作,如配置资源。

通过运行以下命令暂停:

kubectl rollout pause deployment/nginx-deployment

输出如下:

deployment.apps/nginx-deployment paused

然后更新 deployment 的镜像:

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

输出如下:

deployment.apps/nginx-deployment image updated

请注意,没有开始新的部署:

kubectl rollout history deployment/nginx-deployment

输出如下:

deployment.apps/nginx-deployment
REVISION  CHANGE-CAUSE
2         <none>
8         <none>
12        <none>
13        1.26.1
14        <none>  -- 当前版本,没有创建新版本

还可以根据需要进行任意多次更新,例如,更新将使用的资源:

kubectl set resources deployment/nginx-deployment -c=nginx --limits=cpu=100m,memory=512Mi

输出如下:

deployment.apps/nginx-deployment resource requirements updated

❔ 说明: 暂停部署之前的Pod将继续提供服务,只要暂停了deployment,对deployment的新更新操作就不会产生任何影响。

最后,恢复deployment并观察新的 ReplicaSet 是否出现了所有新更新:

kubectl rollout resume deployment/nginx-deployment

输出如下:

deployment.apps/nginx-deployment resumed

观察RS状态是否完成更新

[root@k8s-master1 hcie]# kubectl get rs -w

NAME                                         DESIRED   CURRENT   READY   AGE
nfs-subdir-external-provisioner-7784486c98   1         1         1       5d5h
nginx-deployment-546946b498                  4         4         4       169m
...
nginx-deployment-546946b498                  0         0         0       169m
nginx-deployment-556dbcb546                  5         5         5       27s

查看详细信息

[root@k8s-master1 hcie]# kubectl describe deploy nginx-deployment
Name:                   nginx-deployment
Namespace:              default
CreationTimestamp:      Mon, 09 Sep 2024 20:19:13 +0800
Labels:                 app=nginx
Annotations:            deployment.kubernetes.io/revision: 15
Selector:               app=nginx
Replicas:               5 desired | 5 updated | 5 total | 5 available | 0 unavailable
StrategyType:           RollingUpdate
MinReadySeconds:        0
RollingUpdateStrategy:  1 max unavailable, 1 max surge
Pod Template:
  Labels:  app=nginx
  Containers:
   nginx:
     Image:      nginx:1.26.1 
    Port:       80/TCP
    Host Port:  0/TCP
     Limits:
      cpu:        100m
      memory:     512Mi

❔ 说明:

  • 镜像和资源限制都更新了

⚠️ 注意:如果deployment被暂停,在被恢复之前您无法对deployment进行回滚操作。

3 参考文献

[1] https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#pausing-and-resuming-a-deployment

[2]https://kubernetes.io/docs/concepts/workloads/controllers/replicaset/

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐