虚拟机节点正常关机下的 Pod 迁移及异常宕机恢复方案
问题描述
无论节点是 正常关机 还是 异常宕机,运行在该节点上的虚拟机 Pod 都不会自动迁移至其他正常节点。
原因分析
平台基于开源组件 KubeVirt 实现了虚拟机解决方案。然而,从 KubeVirt 的角度来看,无法区分虚拟机是实际宕机还是由于网络或其他原因导致的连接失败。若随意将虚拟机迁移至其他节点,可能会出现多个虚拟机实例同时存在的问题。
解决方法
在维护虚拟机节点时,需要根据此文档进行手动操作。针对 正常关机 和 异常宕机 两种情况,需手动驱逐或强制删除虚拟机 Pod。
注意:下述命令均需在对应集群的 Master 节点上执行。
正常关机下的虚拟机 Pod 迁移
-
在 CLI 工具中,执行下述命令获取节点信息。其中,回显信息中的
NAME字段即为Node-Name。kubectl get nodes回显信息:
NAME STATUS ROLES AGE VERSION 1.1.1.211 Ready control-plane,master 99d v1.28.8 -
(可选)执行下述命令查看节点下的虚拟机实例。
kubectl get vmis --all-namespaces -o wide | grep <Node-Name> # 使用步骤 1 中获取的 Node-Name 替换命令中的 <Node-Name> 部分回显信息:
test-test vm-t-export-clone 13d Running 1.1.1.1 1.1.1.211 True False -
正常关机前,执行下述命令驱逐需关机节点上的所有虚拟机 Pod,出现如下回显信息则表示已经驱逐成功。
kubectl drain <Node-Name> --delete-local-data --ignore-daemonsets=true --force --pod-selector=kubevirt.io=virt-launcher # 使用需关机节点的 Node-Name 替换命令中的 <Node-Name> 部分回显信息:
Flag --delete-local-data has been deprecated, This option is deprecated and will be deleted. Use --delete-emptydir-data. node/1.1.1.211 cordoned evicting pod test-test/virt-launcher-vm-t-export-clone-hmnkk pod/virt-launcher-vm-t-export-clone-hmnkk evicted node/1.1.1.211 drained -
等所有虚拟机在其他节点上启动之后,将节点关机。
-
节点关机并重新开机后,执行下述命令,标记该节点为可调度节点。
kubectl uncordon <Node-Name> # 使用关机并重启节点的 Node-Name 替换命令中的 <Node-Name> 部分回显信息:
node/1.1.1.211 uncordoned -
至此,该节点上的原虚拟机实例已迁移至其他正常节点,此节点重启后已允许新的 Pod 调度。
异常宕机恢复
-
在 CLI 工具中,执行下述命令获取节点信息。其中,回显信息中的
NAME字段即为Node-Name。kubectl get nodes回显信息:
NAME STATUS ROLES AGE VERSION 1.1.1.211 Ready control-plane,master 99d v1.28.8 -
执行下述命令,强制删除该节点上的所有虚拟机 Pod。
kubectl get po -A -l kubevirt.io=virt-launcher -o wide | grep <Node-Name> | awk '{print "kubectl delete pod --force -n " $1, $2}' | bash # 需使用异常宕机节点的 Node-Name 替换命令中的 <Node-Name> 部分。 -
执行下述命令删除该节点上的 volumeattachment。
kubectl get volumeattachments.storage.k8s.io | grep <Node-Name> | awk '{print $1}' | xargs kubectl delete volumeattachments.storage.k8s.io # 需使用异常宕机节点的 Node-Name 替换命令中的 <Node-Name> 部分。 -
执行下述命令查询异常宕机节点上是否存在具有标签 kubevirt.io=virt-api 的 Pod。
kubectl -n kubevirt get po -l kubevirt.io=virt-api -o wide | grep <Node-Name> # 需使用异常宕机节点的 Node-Name 替换命令中的 <Node-Name> 部分。若存在则执行下述命令删除 Pod。
kubectl -n kubevirt get po -l kubevirt.io=virt-api -o name | xargs kubectl -n kubevirt delete --force --grace-period=0 -
执行下述命令查询异常宕机节点上是否存在具有标签 kubevirt.io=virt-controller 的 Pod。
kubectl -n kubevirt get po -l kubevirt.io=virt-controller -o wide | grep <Node-Name> # 需使用异常宕机节点的 Node-Name 替换命令中的 <Node-Name> 部分。若存在则执行下述命令删除 Pod。
kubectl -n kubevirt get po -l kubevirt.io=virt-controller -o name | xargs kubectl -n kubevirt delete --force --grace-period=0 -
至此,节点异常宕机后虚拟机实例会迁移至其他正常节点。