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 应用是否存在新版本。
配置
# auto 或 ota 升级模型配置文件示例
apiVersion: apps/v1
kind: DaemonSet
metadata:
# ···
annotations:
# 该注解是使用 auto 或者 ota 升级模型的前提条件之一,目前支持的配置值为"auto" 或者 "ota"。
apps.openyurt.io/update-strategy: ota
# 该注解用于滚动更新时设置最大不可用 pod 数量,仅在 auto 模式下起作用。
# 该注解支持的配置值与原生 DaemonSet 配置中 maxUnavailable 相同,默认值为10%。
apps.openyurt.io/max-unavailable: 30%
# ···
spec:
# ···
# 使用 auto 或者 ota 升级模型的另一个前提条件是将 updateStrategy 设置为 OnDelete。
updateStrategy:
type: OnDelete
# ···
总的来说,如果你希望使用 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 实例
cat <<EOF | kubectl apply -f -
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: nginx-daemonset
annotations:
apps.openyurt.io/update-strategy: auto
spec:
selector:
matchLabels:
app: nginx
updateStrategy:
type: OnDelete
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.19.4
EOF
- 查看 nginx-daemonset pods
$ kubectl get pods | grep nginx-daemonset
nginx-daemonset-bv5jg 1/1 Running 0 21m 10.244.2.2 openyurt-e2e-test-worker3 <none> <none>
nginx-daemonset-fhsr6 1/1 Running 0 21m 10.244.1.2 openyurt-e2e-test-worker <none> <none>
nginx-daemonset-lmmtd 1/1 Running 0 21m 10.244.3.2 openyurt-e2e-test-worker2 <none> <none>
- 模拟云边网络断连, 假定断开边缘节点
openyurt-e2e-test-worker2
、openyurt-e2e-test-worker3
与云端节点的网络连接,该示例采用Kind创建集群,可以通过将容器从虚拟网桥中移除的方式模式网络断连
$ docker network disconnect kind openyurt-e2e-test-worker2
$ docker network disconnect kind openyurt-e2e-test-worker3
$ kubectl get nodes -o wide
AME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
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
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
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
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
***
containers:
- name: nginx
image: nginx:1.19.5
***
- 查看 pods:
openyurt-e2e-test-worker
节点上旧 poddefault/nginx-daemonset-fhsr6
已被删除,新 poddefault/nginx-daemonset-slp5t
被创建; 两个网络断连节点上的 pods 暂不进行更新升级
nginx-daemonset-bv5jg 1/1 Running 0 33m 10.244.2.2 openyurt-e2e-test-worker3 <none> <none>
nginx-daemonset-lmmtd 1/1 Running 0 33m 10.244.3.2 openyurt-e2e-test-worker2 <none> <none>
nginx-daemonset-slp5t 1/1 Running 0 5m54s 10.244.1.3 openyurt-e2e-test-worker <none> <none>
- 恢复节点网络连接
$ docker network connect kind openyurt-e2e-test-worker2
$ docker network connect kind openyurt-e2e-test-worker3
$ kubectl get nodes -o wide
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
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
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
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
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 均已完成更新升级
nginx-daemonset-kbkf6 1/1 Running 0 88s 10.244.3.3 openyurt-e2e-test-worker2 <none> <none>
nginx-daemonset-scgtv 1/1 Running 0 51s 10.244.2.3 openyurt-e2e-test-worker3 <none> <none>
nginx-daemonset-slp5t 1/1 Running 0 11m 10.244.1.3 openyurt-e2e-test-worker <none> <none>
- 查看 pods 镜像版本,均已升级至nginx:1.19.5
***
Containers:
nginx:
Container ID: containerd://f7d4b3f1257a0d1d8da862671c11cb094f9fba1ba0041b7a5f783d9c9e4d8449
Image: nginx:1.19.5
Image ID: docker.io/library/nginx@sha256:31de7d2fd0e751685e57339d2b4a4aa175aea922e592d36a7078d72db0a45639
Port: <none>
Host Port: <none>
State: Running
Started: Fri, 14 Oct 2022 14:21:25 +0800
Ready: True
Restart Count: 0
Environment: <none>
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-wrhj8 (ro)
***
3)OTA升级模型
OTA 升级接口
YurtHub 提供了两个 OTA 升级相关的 REST APIs。
GET /pods
通过该接口可以获取节点上 pods 信息。
POST /openyurt.io/v1/namespaces/{ns}/pods/{podname}/upgrade
通过该接口用户可以指定更新某个 DaemonSet Pod。路径参数
ns
与podname
分别代表 Pod 的 命名空间以及名称。
OTA 升级示例
- 创建 daemonset 实例
cat <<EOF | kubectl apply -f -
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: nginx-daemonset
annotations:
apps.openyurt.io/update-strategy: ota
spec:
selector:
matchLabels:
app: nginx
updateStrategy:
type: OnDelete
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.19.4
EOF
# get nginx-daemonset pods
$ kubectl get pods -o wide | grep nginx-daemonset
nginx-daemonset-bwzss 1/1 Running 0 92s 10.244.3.4 openyurt-e2e-test-worker2 <none> <none>
nginx-daemonset-ppf9p 1/1 Running 0 92s 10.244.1.4 openyurt-e2e-test-worker <none> <none>
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
节点上 podnginx-daemonset-bwzss
为例
$ kubectl describe pods nginx-daemonset-bwzss
***
Conditions:
Type Status
PodNeedUpgrade False
***
- 更新 daemonset,将容器镜像从 nginx:1.19.4修改为 nginx:1.19.5
***
containers:
- name: nginx
image: nginx:1.19.5
***
- 再次查看 pod status condition
PodNeedUpgrade
$ kubectl describe pods nginx-daemonset-bwzss
***
Conditions:
Type Status
PodNeedUpgrade True
***
- 进入节点
openyurt-e2e-test-worker2
,执行OTA升级
# Kind 集群中需要先进入边缘节点
$ docker exec -it openyurt-e2e-test-worker2 /bin/bash
# 调用 Upgrade API, 该升级接口仅在边缘节点上提供
$ curl -X POST 127.0.0.1:10267/openyurt.io/v1/namespaces/default/pods/nginx-daemonset-bwzss/upgrade
Start updating pod default/nginx-daemonset-bwzss
- 检查OTA升级结果, 节点
openyurt-e2e-test-worker2
上podnginx-daemonset-bwzss
已经被删除,新创建 pod 为nginx-daemonset-vrvhn
# 检查OTA升级结果
$ kubectl get pods -o wide | grep nginx-daemonset
nginx-daemonset-ppf9p 1/1 Running 0 15m 10.244.1.4 openyurt-e2e-test-worker <none> <none>
nginx-daemonset-rgp9h 1/1 Running 0 15m 10.244.2.4 openyurt-e2e-test-worker3 <none> <none>
nginx-daemonset-vrvhn 1/1 Running 0 63s 10.244.3.5 openyurt-e2e-test-worker2 <none> <none>
# 查看容器镜像版本
$ kubectl describe pods nginx-daemonset-vrvhn
***
Containers:
nginx:
Container ID: containerd://18df6aa88076639353ea0b3d87f340cd4c86ab27a7f154bce06345e9764c997a
Image: nginx:1.19.5
Image ID: docker.io/library/nginx@sha256:31de7d2fd0e751685e57339d2b4a4aa175aea922e592d36a7078d72db0a45639
Port: <none>
Host Port: <none>
State: Running
Started: Fri, 14 Oct 2022 16:25:20 +0800
Ready: True
Restart Count: 0
Environment: <none>
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-p6kjh (ro)
***