Kubernetes: 非优雅节点关机的操作验证
首先
在本文中,我们将对在Kubernetes v1.28中被正式引入的Non Graceful Node Shutdown进行操作验证。
当关闭Kubernetes节点时,如果关闭过程没有正常完成,可能会导致卷等无法被卸载。
在这种情况下,如果在iSCSI等块存储中,已经被挂载的节点处于可读写状态,其他节点将无法通过读写进行卷的挂载。
将一个卷连接到多个节点被称为Multi Attach,上述错误情况被称为Multi Attach错误。
作为恢复这种情况的手段,Non Graceful Node Shutdown应运而生。
作为这个功能的注意事项,它并不会自动恢复。一旦用户判断节点没有正确关闭,可以添加taint (node.kubernetes.io/out-of-service),从而触发该功能的执行。
另外,本功能支持的版本如下。
-
- Kubernetes v1.24: アルファ (デフォルト無効)
-
- Kubernetes v1.26: ベータ (デフォルト有効)
- Kubernetes v1.28: GA
验证环境
-
- Kubernetes v1.25.9, 1.26.4
-
- ノードOS: Ubuntu 20.04
- ストレージ: NetApp ONTAP AFF9.9 (iSCSIを利用)
验证
在这个验证中,为了确认”Non Graceful Node Shutdown”的行为,我们将使用禁用了该功能的Kubernetes来验证在没有该功能的情况下的行为(验证1)。
然后,我们将使用启用了该功能的Kubernetes来验证该功能的行为(验证2)。
[验证1] 如果禁用了非优雅的节点关机(适用于Kubernetes v1.25之前的版本)
首先,让我们讨论非优雅节点关闭被禁用时的行为。
我们将使用默认情况下禁用非优雅节点关闭的Kubernetes v1.25版本进行验证,其中包括Non Graceful Node Shutdown功能门(NodeOutOfServiceVolumeDetach)。
首先,我们将使用StatefulSet(sts.yaml)创建Pod、PVC和PV。
- sts.yaml
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: pv-test
spec:
serviceName: pv-test
replicas: 1
selector:
matchLabels:
app: pv-test
template:
metadata:
labels:
app: pv-test
spec:
containers:
- name: pv-test
image: ubuntu:20.04
volumeMounts:
- name: block
mountPath: /mnt/block
command:
- sleep
- infinity
volumeClaimTemplates:
- metadata:
name: block
spec:
accessModes: [ "ReadWriteOnce" ]
storageClassName: ontap-block
resources:
requests:
storage: 10Gi
部署(sts.yaml)并验证Pod、PVC、PV。
$ kubectl apply -f sts.yaml
statefulset.apps/pv-test created
$ kubectl get pod,pvc,pv -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
pod/pv-test-0 1/1 Running 0 55s 10.26.107.43 demo-ysakashita-w-default-a7102877-mmh9d <none> <none>
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE VOLUMEMODE
persistentvolumeclaim/block-pv-test-0 Bound pvc-adc68176-5517-4274-85fa-33d5dfcd81c2 10Gi RWO ontap-block 55s Filesystem
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE VOLUMEMODE
persistentvolume/pvc-adc68176-5517-4274-85fa-33d5dfcd81c2 10Gi RWO Delete Bound default/block-pv-test-0 ontap-block 52s Filesystem
接下来,您可以通过ssh登录到部署了Pod的节点(demo-ysakashita-w-default-a7102877-mmh9d),并引发操作系统的严重错误(OS Panic)。
ubuntu@demo-ysakashita-w-default-a7102877-mmh9d:~$ sudo bash
root@demo-ysakashita-w-default-a7102877-mmh9d:/home/ubuntu# vi /etc/sysctl.conf
root@demo-ysakashita-w-default-a7102877-mmh9d:/home/ubuntu# sysctl -p
kernel.panic = 0
root@demo-ysakashita-w-default-a7102877-mmh9d:/home/ubuntu# echo c > /proc/sysrq-trigger
在发生 OS Panic 后,会检查节点的状态。
$ kubectl get node
NAME STATUS ROLES AGE VERSION
...
demo-ysakashita-w-default-a7102877-mmh9d NotReady <none> 176m v1.25.9
該当のノードがNotReadyとなりました。 しばらく待ち、Podのステータスも確認します.
$ kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
pv-test-0 1/1 Terminating 0 10m 10.26.107.43 demo-ysakashita-w-default-a7102877-mmh9d <none> <none>
10分以上経ってもTerminatingのままとなります。
この状態で、ノードにtaint (node.kubernetes.io/out-of-service=nodeshutdown:NoExecute)を付与します。
在Kubernetes v1.25版本中,我们确认由于非优雅节点关闭被禁用,这个操作是没有意义的。
$ kubectl taint node demo-ysakashita-w-default-a7102877-mmh9d "node.kubernetes.io/out-of-service=nodeshutdown:NoExecute"
node/demo-ysakashita-w-default-a7102877-mmh9d tainted
在给予了taint之后,我将Pod放置了20分钟,但Pod的状态仍然是Terminating,并没有恢复。这是预期的行为。
$ kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
pv-test-0 1/1 Terminating 0 30m 10.26.107.43 demo-ysakashita-w-default-a7102877-mmh9d <none> <none>
[验证2] 在启用非优雅节点关闭的情况下 (针对Kubernetes v1.26以前)
Kubernetes v1.26にてNon Graceful Node ShutdownのFeature Gates(NodeOutOfServiceVolumeDetach)がベータとなり、デフォルト有効となりました。
そこで、Kubernetes v1.26を使い Non Graceful Node Shutdown の検証を行います。
上記の検証で用いたsts.yamlを使いPod,PVC,PVを作成します。
$ kubectl apply -f sts.yaml
statefulset.apps/pv-test created
$ kubectl get pod,pvc,pv -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
pod/pv-test-0 1/1 Running 0 47s 10.26.26.23 demo-ysaka-net-w-default-4282754a-px2wm <none> <none>
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE VOLUMEMODE
persistentvolumeclaim/block-pv-test-0 Bound pvc-e5b39376-33bb-44af-8753-85a2bba44a6a 10Gi RWO ontap-block 47s Filesystem
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE VOLUMEMODE
persistentvolume/pvc-e5b39376-33bb-44af-8753-85a2bba44a6a 10Gi RWO Delete Bound default/block-pv-test-0 ontap-block 45s Filesystem
次に、Podがデプロイされているノード(demo-ysaka-net-w-default-4282754a-px2wm)にsshで入り、OS Panicを起こします。
ubuntu@demo-ysaka-net-w-default-4282754a-px2wm:~$ sudo bash
root@demo-ysaka-net-w-default-4282754a-px2wm:/home/ubuntu# vi /etc/sysctl.conf
root@demo-ysaka-net-w-default-4282754a-px2wm:/home/ubuntu# sysctl -p
kernel.panic = 0
root@demo-ysaka-net-w-default-4282754a-px2wm:/home/ubuntu# echo c > /proc/sysrq-trigger
查看节点的状态。
$ kubectl get node
NAME STATUS ROLES AGE VERSION
...
demo-ysaka-net-w-default-4282754a-px2wm NotReady <none> 3h52m v1.26.4
該当のNodeがNotReadyとなっていることを確認しました。 しばらく待ち、Podの状態を確認します。
$ kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
pv-test-0 1/1 Terminating 0 8m43s 10.26.26.23 demo-ysaka-net-w-default-4282754a-px2wm <none> <none>
在这种状态下,将与先前的验证相同地向节点添加taint(node.kubernetes.io/out-of-service = nodeshutdown:NoExecute)。
$ kubectl taint node demo-ysaka-net-w-default-4282754a-px2wm "node.kubernetes.io/out-of-service=nodeshutdown:NoExecute"
node/demo-ysaka-net-w-default-4282754a-px2wm tainted
在将污点添加后,Pod立即被调度到另一节点上,状态变为Running并成功恢复。
$ kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
pv-test-0 1/1 Running 0 30s 10.26.99.39 demo-ysaka-net-w-default-4282754a-4s68h <none> <none>
$ kubectl describe pod pv-test-0
...
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 102s default-scheduler Successfully assigned default/pv-test-0 to demo-ysaka-net-w-default-4282754a-4s68h
Normal SuccessfulAttachVolume 102s attachdetach-controller AttachVolume.Attach succeeded for volume "pvc-e5b39376-33bb-44af-8753-85a2bba44a6a"
Normal Pulled 97s kubelet Container image "ubuntu:20.04" already present on machine
Normal Created 97s kubelet Created container pv-test
Normal Started 97s kubelet Started container pv-test
评论
印象
在本篇文章中,我們進行了對非優雅節點關機的驗證。
在这个功能问世之前,我们需要进入无法正确关闭的节点,并强制卸载卷、注销与存储之间的会话,如iSCSI等。
然而,由于无法正确关闭的节点通常处于某种异常状态,有时甚至无法通过SSH等方式进入节点,因此很多时候无法采取这种手段。
在这种情况下,我们必须等待iSCSI会话超时或在存储端强制断开会话。
如果节点无法正确关闭,恢复的步骤将变得复杂,并且只有具备节点 root 权限和存储管理权限的管理员才能执行,这限制了可执行此操作的管理员的数量。
如果具备设置Kubernetes节点taint的权限的管理员,在执行本次验证的非优雅节点关闭时,即使节点不能正确关闭,可以相对容易地进行恢复。但需要注意的是,需要手动设置taint。要准确判断关闭是否正确执行并不容易。因此,系统设计为管理员可以通过设置taint来恢复被判断为“未正确关闭”的节点。换句话说,管理员需要确保能够检测到“未正确关闭”的情况。一种简单的方法是,在节点状态变为非Ready后,检测其停止时间达到了相当长的时间(这在正确关闭的情况下是不可能的)。
建议您了解非优雅节点关机的用法,这是一种有效的手段,可以在故障发生时快速恢复。同时,推荐您在这个机会上确认运营方法,以确保从故障检测到恢复的过程能在短时间内完成。
参考信息
-
- Kubernetes 1.26: Non-Graceful Node Shutdown Moves to Beta
-
- KEP-2268: Non graceful node shutdown
- kubernetes/kubernetes Issue#65392