DaemonSet 升级模型

背景介绍

在边缘化场景下,原生 DaemonSet 升级模型无法满足用户现有需求。在云边网络断连的情况下,DaemonSet 升级流程可能被阻塞。除此之外,原生升级模型并未提供相应的升级操作接口,节点上用户无法自主控制应用升级。

为了解决上述问题,我们对原生 DaemonSet 升级模型进行扩展,新增自定义控制器daemonPodUpdater-controller,提供 Auto 与 OTA 两种升级模型。

  • Auto 模型:解决云边断连时,节点Not-Ready导致的 DaemonSet 升级阻塞问题,在升级过程中会忽略Not-Ready节点,从而保证升级流程的顺利完成,并且在节点状态从Not-Ready转变为Ready后,自动完成 DaemonSet 应用的升级。
  • OTA 模型:新增 Pod status condition PodNeedUpgrade来表明更新可用信息。YurtHub OTA 升级组件可以通过该 condition 判断 DaemonSet 应用是否存在新版本。

配置

  1. # auto 或 ota 升级模型配置文件示例
  2. apiVersion: apps/v1
  3. kind: DaemonSet
  4. metadata:
  5. # ···
  6. annotations:
  7. # 该注解是使用 auto 或者 ota 升级模型的前提条件之一,目前支持的配置值为"auto" 或者 "ota"。
  8. apps.openyurt.io/update-strategy: ota
  9. # 该注解用于滚动更新时设置最大不可用 pod 数量,仅在 auto 模式下起作用。
  10. # 该注解支持的配置值与原生 DaemonSet 配置中 maxUnavailable 相同,默认值为10%。
  11. apps.openyurt.io/max-unavailable: 30%
  12. # ···
  13. spec:
  14. # ···
  15. # 使用 auto 或者 ota 升级模型的另一个前提条件是将 updateStrategy 设置为 OnDelete。
  16. updateStrategy:
  17. type: OnDelete
  18. # ···

总的来说,如果你希望使用 auto 或者 ota 升级模型,那么你需要将注解 apps.openyurt.io/update-strategy 设置为 “auto” 或者 “ota”, 并且将 .spec.updateStrategy.type 设置为 “OnDelete”。

用户使用:

1)安装Yurt-Controller-Manager组件

daemonPodUpdater控制器集成于Yurt-Controller-Manager组件,使用 Auto 或 OTA 升级模型前需要安装部署Yurt-Controller-Manager,相关操作可以参照部署OpenYurt组件

2)使用Auto升级模型

  • 创建 daemonset 实例
  1. cat <<EOF | kubectl apply -f -
  2. apiVersion: apps/v1
  3. kind: DaemonSet
  4. metadata:
  5. name: nginx-daemonset
  6. annotations:
  7. apps.openyurt.io/update-strategy: auto
  8. spec:
  9. selector:
  10. matchLabels:
  11. app: nginx
  12. updateStrategy:
  13. type: OnDelete
  14. template:
  15. metadata:
  16. labels:
  17. app: nginx
  18. spec:
  19. containers:
  20. - name: nginx
  21. image: nginx:1.19.4
  22. EOF
  • 查看 nginx-daemonset pods
  1. $ kubectl get pods | grep nginx-daemonset
  2. nginx-daemonset-bv5jg 1/1 Running 0 21m 10.244.2.2 openyurt-e2e-test-worker3 <none> <none>
  3. nginx-daemonset-fhsr6 1/1 Running 0 21m 10.244.1.2 openyurt-e2e-test-worker <none> <none>
  4. nginx-daemonset-lmmtd 1/1 Running 0 21m 10.244.3.2 openyurt-e2e-test-worker2 <none> <none>
  • 模拟云边网络断连, 假定断开边缘节点openyurt-e2e-test-worker2openyurt-e2e-test-worker3与云端节点的网络连接,该示例采用Kind创建集群,可以通过将容器从虚拟网桥中移除的方式模式网络断连
  1. $ docker network disconnect kind openyurt-e2e-test-worker2
  2. $ docker network disconnect kind openyurt-e2e-test-worker3
  3. $ kubectl get nodes -o wide
  4. AME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
  5. openyurt-e2e-test-control-plane Ready control-plane,master 36m v1.22.7 172.18.0.4 <none> Ubuntu 21.10 5.10.76-linuxkit containerd://1.5.10
  6. openyurt-e2e-test-worker Ready <none> 35m v1.22.7 172.18.0.2 <none> Ubuntu 21.10 5.10.76-linuxkit containerd://1.5.10
  7. openyurt-e2e-test-worker2 NotReady <none> 35m v1.22.7 172.18.0.3 <none> Ubuntu 21.10 5.10.76-linuxkit containerd://1.5.10
  8. openyurt-e2e-test-worker3 NotReady <none> 35m v1.22.7 172.18.0.5 <none> Ubuntu 21.10 5.10.76-linuxkit containerd://1.5.10
  • 更新 daemonset,将容器镜像从 nginx:1.19.4 修改为 nginx:1.19.5
  1. ***
  2. containers:
  3. - name: nginx
  4. image: nginx:1.19.5
  5. ***
  • 查看 pods:openyurt-e2e-test-worker节点上旧 pod default/nginx-daemonset-fhsr6已被删除,新 pod default/nginx-daemonset-slp5t被创建; 两个网络断连节点上的 pods 暂不进行更新升级
  1. nginx-daemonset-bv5jg 1/1 Running 0 33m 10.244.2.2 openyurt-e2e-test-worker3 <none> <none>
  2. nginx-daemonset-lmmtd 1/1 Running 0 33m 10.244.3.2 openyurt-e2e-test-worker2 <none> <none>
  3. nginx-daemonset-slp5t 1/1 Running 0 5m54s 10.244.1.3 openyurt-e2e-test-worker <none> <none>
  • 恢复节点网络连接
  1. $ docker network connect kind openyurt-e2e-test-worker2
  2. $ docker network connect kind openyurt-e2e-test-worker3
  3. $ kubectl get nodes -o wide
  4. NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
  5. openyurt-e2e-test-control-plane Ready control-plane,master 49m v1.22.7 172.18.0.4 <none> Ubuntu 21.10 5.10.76-linuxkit containerd://1.5.10
  6. openyurt-e2e-test-worker Ready <none> 48m v1.22.7 172.18.0.2 <none> Ubuntu 21.10 5.10.76-linuxkit containerd://1.5.10
  7. openyurt-e2e-test-worker2 Ready <none> 48m v1.22.7 172.18.0.3 <none> Ubuntu 21.10 5.10.76-linuxkit containerd://1.5.10
  8. openyurt-e2e-test-worker3 Ready <none> 48m v1.22.7 172.18.0.5 <none> Ubuntu 21.10 5.10.76-linuxkit containerd://1.5.10
  • 查看 pods, 所有节点上 daemonset pods 均已完成更新升级
  1. nginx-daemonset-kbkf6 1/1 Running 0 88s 10.244.3.3 openyurt-e2e-test-worker2 <none> <none>
  2. nginx-daemonset-scgtv 1/1 Running 0 51s 10.244.2.3 openyurt-e2e-test-worker3 <none> <none>
  3. nginx-daemonset-slp5t 1/1 Running 0 11m 10.244.1.3 openyurt-e2e-test-worker <none> <none>
  • 查看 pods 镜像版本,均已升级至nginx:1.19.5
  1. ***
  2. Containers:
  3. nginx:
  4. Container ID: containerd://f7d4b3f1257a0d1d8da862671c11cb094f9fba1ba0041b7a5f783d9c9e4d8449
  5. Image: nginx:1.19.5
  6. Image ID: docker.io/library/nginx@sha256:31de7d2fd0e751685e57339d2b4a4aa175aea922e592d36a7078d72db0a45639
  7. Port: <none>
  8. Host Port: <none>
  9. State: Running
  10. Started: Fri, 14 Oct 2022 14:21:25 +0800
  11. Ready: True
  12. Restart Count: 0
  13. Environment: <none>
  14. Mounts:
  15. /var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-wrhj8 (ro)
  16. ***

3)OTA升级模型

OTA 升级接口

YurtHub 提供了两个 OTA 升级相关的 REST APIs。

  1. GET /pods

    通过该接口可以获取节点上 pods 信息。

  2. POST /openyurt.io/v1/namespaces/{ns}/pods/{podname}/upgrade

    通过该接口用户可以指定更新某个 DaemonSet Pod。路径参数 nspodname 分别代表 Pod 的 命名空间以及名称。

OTA 升级示例

  • 创建 daemonset 实例
  1. cat <<EOF | kubectl apply -f -
  2. apiVersion: apps/v1
  3. kind: DaemonSet
  4. metadata:
  5. name: nginx-daemonset
  6. annotations:
  7. apps.openyurt.io/update-strategy: ota
  8. spec:
  9. selector:
  10. matchLabels:
  11. app: nginx
  12. updateStrategy:
  13. type: OnDelete
  14. template:
  15. metadata:
  16. labels:
  17. app: nginx
  18. spec:
  19. containers:
  20. - name: nginx
  21. image: nginx:1.19.4
  22. EOF
  23. # get nginx-daemonset pods
  24. $ kubectl get pods -o wide | grep nginx-daemonset
  25. nginx-daemonset-bwzss 1/1 Running 0 92s 10.244.3.4 openyurt-e2e-test-worker2 <none> <none>
  26. nginx-daemonset-ppf9p 1/1 Running 0 92s 10.244.1.4 openyurt-e2e-test-worker <none> <none>
  27. nginx-daemonset-rgp9h 1/1 Running 0 92s 10.244.2.4 openyurt-e2e-test-worker3 <none> <none>
  • 查看 pod status condition PodNeedUpgrade, 以openyurt-e2e-test-worker2节点上 pod nginx-daemonset-bwzss 为例
  1. $ kubectl describe pods nginx-daemonset-bwzss
  2. ***
  3. Conditions:
  4. Type Status
  5. PodNeedUpgrade False
  6. ***
  • 更新 daemonset,将容器镜像从 nginx:1.19.4修改为 nginx:1.19.5
  1. ***
  2. containers:
  3. - name: nginx
  4. image: nginx:1.19.5
  5. ***
  • 再次查看 pod status condition PodNeedUpgrade
  1. $ kubectl describe pods nginx-daemonset-bwzss
  2. ***
  3. Conditions:
  4. Type Status
  5. PodNeedUpgrade True
  6. ***
  • 进入节点openyurt-e2e-test-worker2,执行OTA升级
  1. # Kind 集群中需要先进入边缘节点
  2. $ docker exec -it openyurt-e2e-test-worker2 /bin/bash
  3. # 调用 Upgrade API, 该升级接口仅在边缘节点上提供
  4. $ curl -X POST 127.0.0.1:10267/openyurt.io/v1/namespaces/default/pods/nginx-daemonset-bwzss/upgrade
  5. Start updating pod default/nginx-daemonset-bwzss
  • 检查OTA升级结果, 节点openyurt-e2e-test-worker2上pod nginx-daemonset-bwzss已经被删除,新创建 pod 为 nginx-daemonset-vrvhn
  1. # 检查OTA升级结果
  2. $ kubectl get pods -o wide | grep nginx-daemonset
  3. nginx-daemonset-ppf9p 1/1 Running 0 15m 10.244.1.4 openyurt-e2e-test-worker <none> <none>
  4. nginx-daemonset-rgp9h 1/1 Running 0 15m 10.244.2.4 openyurt-e2e-test-worker3 <none> <none>
  5. nginx-daemonset-vrvhn 1/1 Running 0 63s 10.244.3.5 openyurt-e2e-test-worker2 <none> <none>
  6. # 查看容器镜像版本
  7. $ kubectl describe pods nginx-daemonset-vrvhn
  8. ***
  9. Containers:
  10. nginx:
  11. Container ID: containerd://18df6aa88076639353ea0b3d87f340cd4c86ab27a7f154bce06345e9764c997a
  12. Image: nginx:1.19.5
  13. Image ID: docker.io/library/nginx@sha256:31de7d2fd0e751685e57339d2b4a4aa175aea922e592d36a7078d72db0a45639
  14. Port: <none>
  15. Host Port: <none>
  16. State: Running
  17. Started: Fri, 14 Oct 2022 16:25:20 +0800
  18. Ready: True
  19. Restart Count: 0
  20. Environment: <none>
  21. Mounts:
  22. /var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-p6kjh (ro)
  23. ***