Pod 的升级和回滚-podupdaterolling

如果 Pod 是通过 Deployment 创建的,则++用户可以在运行时修改 Deployment 的 Pod 定义(spec.template)或镜像名称,并应用到 Deployment 对象上,系统即可完成 Deployment 的 rollout 动作++,rollout 可被视为 Deployment 的自动更新或者自动部署动作。如果在更新过程中发生了错误,则还可以通过回滚操作恢复 Pod 的版本。

Deployment 的升级

以 Deployment nginx 为例,保存文件名为 nginx-deployment.yaml:

apiVersion: apps/v1
	kind: Deployment
	metadata:
	  name: nginx-deployment
	spec:
	  selector:
	    matchLabels:
	      app: nginx
	  replicas: 3
	  template:
	    metadata:
	      labels:
	        app: nginx
	    spec:
	      containers:
	      - name: nginx
	        image: nginx:1.7.9
	        ports:
	        - containerPort: 80

已运行的 Pod 副本数量有 3 个:
在这里插入图片描述

现在Pod 镜像需要被更新为 Nginx:1.9.1,可以通过 kubectl set image 命令为 Deployment 设置新的 镜像名称:

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

在这里插入图片描述

另一种更新的方法是使用 kubectl edit 命令修改 Deployment 的配置,将 spec.template.spec.containers[0].image 从 Nginx:1.7.9 更改为 Nginx:1.9.1:

kubectl edit deployment/nginx-deployment

在这里插入图片描述

保存退出
在这里插入图片描述

镜像名(或 Pod 定义)一旦发送了修改,则将触发系统完成 Deployment 所有运行 Pod 的滚动升级操作。可以使用 kubectl rollout status 命令查看 Deployment 的更新过程:
在这里插入图片描述

查看当前运行的 Pod,名称已经更新了:
在这里插入图片描述

可以使用 kubectl describe deployments/nginx-deployment 命令观察 Deployment 的更新过程。

在这里插入图片描述

  1. 初始创建 Deployment 时,系统创建了一个 ReplicaSet (nginx-deployment-5d59d67564),并按用户的需求创建了3个 Pod 副本。
  2. 更新 Deployment 时,系统创建了一个新的 ReplicaSet (replica set nginx-deployment-69c44dfb78),并将其副本数量扩展到1,然后将旧的 ReplicaSet 缩减为 2。
  3. 之后,系统继续按照相同的更新策略对新旧两个 ReplicaSet 进行逐个调整。新的 ReplicaSet 副本数量扩展至2,旧的 ReplicaSet 数量缩减到1。
  4. 最后的 ReplicaSet 运行了3个新版的 Pod 副本,旧的 ReplicaSet 副本缩减为0。

运行 kubectl get rs 命令,查看两个 ReplicaSet 的最终状态:
在这里插入图片描述

在整个升级过程中,系统会保证至少有两个 Pod 可用,并且最多同时运行4个 Pod,这是 Deployment 通过复杂的算法完成的。Deployment 需要确保在整个更新过程中只有一定数量的 Pod 可能处于不可用状态。在默认情况下,Deployment 确保可用的 Pod 总数量至少为所需的副本数量(DESIRED)减1,也就是最多1个不可用(maxUnavailable=1)。
Deployment 还需要确保在整个更新过程中 Pod 的总数量不会超过所需的副本数量太多。在默认情况下,Deployment 确保 Pod 的总数量最多比所需的 Pod 数量多1个,也就是最多1个浪涌值(maxSurge=1)。
Kubernetes 从 1.6 版本开始,maxUnavailable 和 maxSurge 的默认值将从1、1更新为所需副本数量的 25%、25%。

这样在升级过程中,Deployment 就能够保证服务不中断,并且副本数量始终维持为用户指定的数量(DESIRED)。

在 Deployment 的定义中,可以通过 spec.strategy 指定 Pod 更新的策略,目前支持两种策略:Recreate(重建)和 RollingUpdate(滚动更新)默认值为 RollingUpdate。

  • Recreate:设置 spec.strategy.type=Recreate,表示 Deployment 在更新 Pod 时,会先“杀掉”所有正在运行的 Pod,然后创建新的 Pod。

  • RollingUpdate:设置 spec.strategy.type=RollingUpdate,表示 Deployment 会以滚动更新的方式来逐个更新 Pod。同时,可以通过设置 spec.strategy.rollingUpdate 下的两个参数(maxUnavailable 和 maxSurge)来控制滚动更新的过程。

  • maxUnavailable 和 maxSurge 两个参数说明如下:

    • spec.strategy.rollingUpdate.maxUnavailable:用于指定Deployment在更新过程中不可用状态的Pod数量的上限。该maxUnavailable的数值可以是绝对值(例如5)或Pod期望的副本数量的百分比(例如10%),如果被设置为百分比,那么系统会先以向下取整的方式计算出绝对值(整数)。而当另一个参数maxSurge被设置为0时,maxUnavailable则必须被设置为绝对数值大于0(从Kubernetes 1.6开始,maxUnavailable的默认值从1改为25%)。举例来说,当maxUnavailable被设置为30%时,旧的ReplicaSet可以在滚动更新开始时立即将副本数量缩小到所需副本总数量的70%。一旦新的Pod创建并准备好,旧的ReplicaSet就会进一步缩容,新的ReplicaSet又继续扩容,整个过程中系统在任意时刻都可以确保可用状态的Pod总数量至少占Pod期望副本总数量的70%。
    • spec.strategy.rollingUpdate.maxSurge:用于指定在Deployment更新Pod的过程中Pod总数量超过Pod期望副本数量部分的最大值。该maxSurge的数值可以是绝对值(例如5)或Pod期望副本数量的百分比(例如10%)。如果设置为百分比,那么系统会先按照向上取整的方式计算出绝对数值(整数)。从Kubernetes 1.6开始,maxSurge的默认值从1改为25%。举例来说,当maxSurge的值被设置为30%时,新的ReplicaSet可以在滚动更新开始时立即进行副本数量扩容,只需保证新旧ReplicaSet的Pod副本数量之和不超过期望副本数量的130%即可。一旦旧的Pod被“杀掉”,新的ReplicaSet就会进一步扩容。在整个过程中系统在任意时刻都能确保新旧ReplicaSet的Pod副本总数量之和不超过所需副本数量的130%。

Deployment 的回滚

假设在更新 Deployment 镜像时,将容器镜像名错误设置成 Nginx:19.1
在这里插入图片描述

则这时 Deployment 的部署过程会卡住:
在这里插入图片描述

所以需要 ctrl + c 命令来终止这个查看命令。
查看 ReplicaSet,可以看到新建的 ReplicaSet(nginx-deployment-d645d84b6)
在这里插入图片描述

在查看创建的 Pod,会发现新的 ReplicaSet 创建的 1 个 Pod 被卡在镜像拉取的过程中。
在这里插入图片描述

为了解决上面的问题,需要回滚到之前稳定版本的 Deployment。

  1. 首选用 kubectl rollout history 命令检查这个 Deployment 部署的历史记录:
kubectl rollout history deployment/nginx-deployment

在这里插入图片描述

注意:如果想要在 history 里面看到历史记录,需要在执行的创建和升级的命令里加上–record=true 才能看到。
将 Deployment 回滚到之前的版本时,只有 Deployment 的 Pod 模板部分会被修改,在默认情况下,所有 Deployment 的发布历史记录都被保留在系统中(可以配置历史记录数量)以便进行回滚操作。
如果需要查看特定版本的详细信息,则可以加上 --revision=参数:

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

在这里插入图片描述

  1. 撤回本次发布并回滚到上一个部署版本:
kubectl rollout undo deployment/nginx-deployment

在这里插入图片描述

也可以使用 --to-reversion 参数指定回滚到的部署版本号:

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

在这里插入图片描述

可以在 kubectl describe Deployment 的事件信息中查看到回滚版本2 的操作过程:

kubectl describe deployments/nginx-deployment

暂停和恢复 Deployment 的部署操作

对于一次复杂的 Deployment 配置修改,为了避免频繁触发 Deployment 的更新操作,可以先粘贴 Deployment 的更新操作,然后进行配置修改,再恢复 Deployment,一次性触发完整的更新操作,就可以避免不必要的 Deployment 更新操作了。
以之前创建的 Nginx 为例:

kubectl create -f nginx-deployment.yaml --record=true

在这里插入图片描述

通过 kubectl rollout pause 命令暂停 Deployment 的更新操作:

kubectl rollout pause deployment/nginx-deployment

在这里插入图片描述

然后修改 Deployment 的镜像信息:

kubectl set image deployment/nginx-deployment nginx=nginx:1.9.1 --record=true

在这里插入图片描述

查看 Deployment 的历史记录,发现并没有触发新的 Deployment 部署操作
在这里插入图片描述

在暂停 Deployment 部署之后,可以根据需要进行任意次数的配置更新。例如,再次更新容器的资源限制:

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

在这里插入图片描述

最后恢复这个 Deployment 的部署操作:

kubectl rollout resume deployment nginx-deployment

在这里插入图片描述

注意,在恢复暂停的 Deployment 之前,无法回滚该 Deployment。

DaemonSet 的更新策略

目前DaemonSet 的升级策略(updateStrategy)包括两种:OnDelete 和 RollingUpdate。

  • OnDelete:当使用 OnDelete作为升级策略时,在创建好新的 DaemonSet 配置之后,新的 Pod 并不会被创建,直到用户手动删除旧版本的 Pod,才出发新建操作,即只有手工删除了 DaemonSet 创建的 Pod 副本,新的 Pod 副本才会被创建出来。
  • RollingUpdate:默认选项。当使用 RollingUpdate 作为升级策略对 DaemonSet 进行更新时,旧版本的 Pod 将被自动“杀掉”,然后自动创建新版本的 DaemonSet Pod。整个过程与普通 Deployment 的滚动升级一样是可控的。不过有两点不同于普通 Pod 的滚动升级:
  1. 目前 Kubernetes 还不支持查看和管理 DaemonSet 的更新历史记录;
  2. DaemonSet 的回滚(Rollback)并不能如同 Deployment 一样直接通过 kubectl rollback 命令来实现,必须通过再次提交旧版本配置的方式实现。

例子如下:

创建带有 RollingUpdate 更新策略的 DaemonSet

保存为daemonset_rollingUpdate.yaml

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: fluentd-elasticsearch
  namespace: kube-system
  labels:
    k8s-app: fluentd-logging
spec:
  selector:
    matchLabels:
      name: fluentd-elasticsearch
  updateStrategy:
    type: RollingUpdate
    rollingUpdate:
      maxUnavailable: 1
  template:
    metadata:
      labels:
        name: fluentd-elasticsearch
    spec:
      # tolerations:
      # # this toleration is to have the daemonset runnable on master nodes
      # # remove it if your masters can't run pods
      # - key: node-role.kubernetes.io/master
      #   effect: NoSchedule
      containers:
      - name: fluentd-elasticsearch
        image: registry.aliyuncs.com/google_containers/fluentd-elasticsearch:1.17
        volumeMounts:
        - name: varlog
          mountPath: /var/log
        - name: varlibdockercontainers
          mountPath: /var/lib/docker/containers
          readOnly: true
      terminationGracePeriodSeconds: 30
      volumes:
      - name: varlog
        hostPath:
          path: /var/log
      - name: varlibdockercontainers
        hostPath:
          path: /var/lib/docker/containers

执行 kubectl apply 创建这个 DaemonSet

kubectl apply -f daemonset_rollingUpdate.yaml

检查 DaemonSet 的滚动更新策略

kubectl get ds/fluentd-elasticsearch -o go-template='{{.spec.updateStrategy.type}}{{"\n"}}' -n kube-system

在这里插入图片描述

运行这个 DaemonSet
在这里插入图片描述

更新 DaemonSet 模板,保存为daemonset_rollingUpdate_2.yaml

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: fluentd-elasticsearch
  namespace: kube-system
  labels:
    k8s-app: fluentd-logging
spec:
  selector:
    matchLabels:
      name: fluentd-elasticsearch
  updateStrategy:
    type: OnDelete
  template:
    metadata:
      labels:
        name: fluentd-elasticsearch
    spec:
      # tolerations:
      # # this toleration is to have the daemonset runnable on master nodes
      # # remove it if your masters can't run pods
      # - key: node-role.kubernetes.io/master
      #   effect: NoSchedule
      containers:
      - name: fluentd-elasticsearch
        image: registry.aliyuncs.com/google_containers/fluentd-elasticsearch:1.19
        volumeMounts:
        - name: varlog
          mountPath: /var/log
        - name: varlibdockercontainers
          mountPath: /var/lib/docker/containers
          readOnly: true
      terminationGracePeriodSeconds: 30
      volumes:
      - name: varlog
        hostPath:
          path: /var/log
      - name: varlibdockercontainers
        hostPath:
          path: /var/lib/docker/containers
  • 声明式命令
    如果你使用 配置文件 来更新 DaemonSet,请使用 kubectl apply:
kubectl apply -f daemonset_rollingUpdate_2.yaml
  • 指令式命令
    如果你使用 指令式命令 来更新 DaemonSets,请使用kubectl edit:
kubectl edit ds/fluentd-elasticsearch -n kube-system


image: registry.aliyuncs.com/google_containers/fluentd-elasticsearch:1.17
改为
image: registry.aliyuncs.com/google_containers/fluentd-elasticsearch:1.19

保存退出

  • 只更新容器镜像
    如果只需要更新 DaemonSet 模板里的容器镜像,比如,.spec.template.spec.containers[*].image, 请使用 kubectl set image:
kubectl set image ds/fluentd-elasticsearch fluentd-elasticsearch=registry.aliyuncs.com/google_containers/fluentd-elasticsearch:1.19 -n kube-system
  • 监视滚动更新状态
    最后,观察 DaemonSet 最新滚动更新的进度:
kubectl rollout status ds/fluentd-elasticsearch -n kube-system

当滚动更新完成时,输出结果如下:
daemonset “fluentd-elasticsearch” successfully rolled out
在这里插入图片描述

查看 DaemonSet 事件信息:

kubectl describe daemonsets -n kube-system fluentd-elasticsearch

在这里插入图片描述

符合 RollingUpdate 的升级规则,旧版本的 Pod 将被自动“杀掉”,然后自动创建新版本的 DaemonSet Pod。

创建带有 OnDelete 更新策略的 DaemonSet

保存文件名为:daemonset_onDelete.yaml

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: fluentd-elasticsearch
  namespace: kube-system
  labels:
    k8s-app: fluentd-logging
spec:
  selector:
    matchLabels:
      name: fluentd-elasticsearch
  updateStrategy:
    type: OnDelete
  template:
    metadata:
      labels:
        name: fluentd-elasticsearch
    spec:
      # tolerations:
      # # this toleration is to have the daemonset runnable on master nodes
      # # remove it if your masters can't run pods
      # - key: node-role.kubernetes.io/master
      #   effect: NoSchedule
      containers:
      - name: fluentd-elasticsearch
        image: registry.aliyuncs.com/google_containers/fluentd-elasticsearch:1.17
        volumeMounts:
        - name: varlog
          mountPath: /var/log
        - name: varlibdockercontainers
          mountPath: /var/lib/docker/containers
          readOnly: true
      terminationGracePeriodSeconds: 30
      volumes:
      - name: varlog
        hostPath:
          path: /var/log
      - name: varlibdockercontainers
        hostPath:
          path: /var/lib/docker/containers

执行 kubectl apply 创建这个 DaemonSet

kubectl apply -f daemonset_onDelete.yaml
  • 指令式命令修改这个 DaemonSet:
kubectl edit daemonsets -n kube-system fluentd-elasticsearch


image: registry.aliyuncs.com/google_containers/fluentd-elasticsearch:1.17
改为
image: registry.aliyuncs.com/google_containers/fluentd-elasticsearch:1.19
保存退出

  • 声明式命令
    如果使用配置文件来更新 DaemonSet,请使用 kubectl apply:
kubectl apply -f daemonset_onDelete_2.yaml
  • 查看这个 DaemonSet 的配置:
kubectl describe daemonsets -n kube-system fluentd-elasticsearch

在这里插入图片描述

发现已经修改成1.19,然后查看下面两个 Pod 的版本信息:
在这里插入图片描述

○ 发现还是1.17版本,然后手动删除这两个 Pod:

kubectl delete pod -n kube-system fluentd-elasticsearch-cpp2w
kubectl delete pod -n kube-system fluentd-elasticsearch-9fkwx

执行 kubectl 查看这个 daemonset 的状态
在这里插入图片描述

○ 查看新创建 Pod 的版本信息:
在这里插入图片描述

发现已成功更新1.19版本。

StatefulSet 的更新策略

StatefulSet 的更新策略跟 DaemonSet 类似,也有RollingUpdate 和 OnDelete 的策略

参考:《Kubernetes 权威指南 第五版》、https://v1-19.docs.kubernetes.io/zh/docs/tasks/manage-daemon/update-daemon-set/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值