您的位置 首页 > AI资讯 > 产业资讯

当k8s节点停机维护时,如何迁移pod?

需求

k8s集群中的node节点需要升级内存,以应对服务迁移、pod扩缩容带来的资源短缺;或者node节点宕机了,这种情况需要关闭node节点进行维护,那么node节点服务器上的pod应该怎么办呢?

默认迁移

当node节点关闭时,k8s集群中不会立即发生自动迁移。如果node节点上的副本数为1,就会出现服务中断。事实上,情况并非如此。等待5分钟后,k8s会自动将宕机节点上的pod迁移到其他节点。

具体流程如下:

当k8s节点停机维护时,如何迁移pod?

# 1. 模拟node节点关闭,stop kubeletsystemctl stop kubelet# 2. 集群状态# 此时停止的节点点处于NotReady状态# kubectl get nodeNAME STATUS ROLES AGE VERSIONk8s-3-217 Ready master 88d v1.18.2k8s -3-218 NotReady none 88d v1.18.2k8s-3-219 Ready none 88d v1.18.2# 3. 监控pod 状态,等待约5 分钟集群开始采取行动# kubectl get pod -n test -o Wide -n test -wNAME 就绪状态重新启动年龄IP 节点指定节点就绪GATEShelloworld-79956d95b4-q7jjg 1/1 运行0 19h 10.244.1.154 k8s-3-218 无nonehelloworld-79956d95b4-q7jjg 1/1 运行0 19h 10.2 44.1.154 k8 s-3-218 none none# 5 分钟后,pod 终止并重建helloworld-79956d95b4-q7jjg 1/1 Termination 0 19h 10.244.1.154 k8s-3-218 none nonehelloworld-79956d95b4-nnlrq 0/1 Pending 0 0s none none无nonehelloworld-79956d95b4-nnlrq 0/1 待处理0S 无K8S-3-219 无NonehellowOrld-79956D95B4-NNLRQ 0/1 Containercause 0 1S 无K8S-219 无Nonehellown 3S 10.244.2.215 K8S-3-219 无NonehellowOn -799 56d95b4-nnlrq 1/1 Running 0 66s 10.244.2.215 k8s-3-219 none none# 4、访问测试:pod重新迁移到其他节点时,服务不可用。 # Curl -X 192.168.3.219:80 Hello.test.cnhtmlHeadtitle503 服务暂时不可用/Title/HeadBody1503 服务暂时不可用LABLE/H1/Centerhrcenternginx/1.17.8/Center# 5、迁移后:正常访问# CURL -X 192.168.3.219:80 您好。 test.cn你好,世界!从上面的过程可以看出,down掉的node节点上的pod会被终止,然后在5分钟后重建,直到pod在新节点上启动并被readiness探针检测到正常并处于1\1运行状态。正式对外提供服务。因此,服务中断时间=5分钟关机时间+重建时间+服务启动时间+Readiness探针检测正常时间。

这里你可能有一个疑问:为什么Pod在5分钟后就开始迁移了?这时候我们就需要涉及到k8s中的Taint(污点)和Toleration(容错),它们是Kubernetes 1.6开始提供的高级调度功能。 Taint 和Toleration 协同工作,防止pod 被分配到不合适的节点。每个节点可以应用一个或多个Taints,这意味着不能容忍Taints 的Pod 将不会被该节点接受。如果将Toleration 应用于pod,则意味着这些pod 可以(但不要求)调度到具有匹配污点的节点上。

我们来具体分析一下:

# 1.检查停止的服务节点的状态# kubelet停止后,node节点自动添加Taints; # kubectl 描述节点k8s-3-218Name: k8s-3-218Roles: noneCreationTimestamp: 2020 年5 月22 日星期五11:36:16 +0800Taints: node.kuber netes.io/unreachable:NoExecute node.kubernetes.io/unreachable3 3360NoScheduleUnschedulable: falseLease: HolderIdentity: k8s-3-218 AcquireTime: 未设置RenewTime: 星期三, 2020 年8 月19 日09:31:22 +0800 Conditions: 类型状态LastHeartbeatTime LastTransitionTime 原因消息---- ------ -------- ---------- --------- --------- ------ ------- NetworkUnavailable False Tue, 18 Aug 2020 09:07:59 +0800 Tue, 18 Aug 2020 09:07:59 +0800 FlannelIsUp Flannel 正在该节点上运行MemoryPressure Unknown Wed , 2020 年8 月19 日09:29:56 +0800 否deStatusUnknown Kubelet 停止发布节点状态。 DiskPressure Unknown 2020 年8 月19 日星期三09:29:56 +0800 2020 年8 月19 日星期三09:32:07 +0800 NodeStatusUnknown Kubelet 停止发布节点状态。 PIDPressure Unknown 2020 年8 月19 日星期三09:29:56 +0800 0 NodeStatusUnknown Kubelet 停止发布节点状态。 Ready Unknown Wed, 19 Aug 2020 09:29:56 +0800 Wed, 19 Aug 2020 09:32:07 +0800 NodeStatusUnknown Kubelet 停止发布节点状态.省略.Events: none# 2. 查看pod 状态# kubectl describe pod helloworld-8565c46 87b-rrfmj- n testName: helloworld-8565c4687b-rrfmj Namespace: testPriority: 0.Node-Selectors: noneTolerations: node.kubernetes.io/not-ready:NoExecute for 300s node.kubernetes.io/unreachable:NoExecute for 300sEvents3336 0 none此时pod的Tolerations默认容忍度具有相应Taint 的节点节点的时间为300s,超过此时间pod 将被驱逐到其他可用节点。因此,该节点上的所有Pod 将在5 分钟后重新调度,在此期间服务将中断。

既然默认的Pod迁移无法避免服务中断,那么我们是否可以在节点宕机之前手动迁移节点呢?

当k8s节点停机维护时,如何迁移pod?

手动迁移

为了避免等待默认的5分钟,我们还可以使用cordon、drain和uncordor命令来实现节点的主动维护。此时需要以下三个命令:

cordon:将该节点标记为不可调度,后续新的pod不会被调度到该节点,但该节点上的pod可以正常对外服务; dance:将该节点上的pod驱逐到其他可调度的节点上; uncordon:将节点标记为可调度;具体操作流程如下:

# 1.将节点标记为不可调度# kubectl cordon k8s-3-219node/k8s-3-219 cordoned # 查看节点状态,此时219标记为不可调度# kubectl get nodeNAME STATUS ROLES AGE VERSIONk8s-3-217 Ready master 89d v1.18.2k8s-3-218 Ready 无88d v1.18.2k8s-3-219 Ready,SchedulingDisabled 无88d v1.18.2# 2. Deport pod# kubectl dance k8s-3-219 --delete-local-data - -ignore -daemonsets --forcenode/k8s-3-219 已封锁警告: 忽略DaemonSet 管理的Pods: ingress-nginx/nginx-ingress-controller-gmzq6、kube-system/kube-flannel-ds-amd64-5gfwh、kube-system/kube- proxy-vdckkevicting pod kube-system/tiller-deploy-6c65968d87-75pfmevicting pod kube-system/metrics-server-7f96bbcc66-bgt7jevicting pod test/helloworld-79956d95b4-nnlrq# 参数如下: --delete-local- data 删除本地数据,甚至emptyDir也会被删除; --ignore-daemonsets 忽略DeamonSet,否则DeamonSet删除后会自动重建; --force 不带force参数只会删除节点上的ReplicationController、ReplicaSet、DaemonSet、StatefulSet或Job。添加后,所有Pod都会被删除; # 3.检查驱逐,219上的pod将迁移到218。 # kubectl get pod -n test -o WideNAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATEShelloworld-79956d95b4-gg58c 0/1 Running 0 20s 10.244. 1.165 k8s-3-218 none nonehelloworld-79956d95b4-nnlrq 1/1 Termination 0 7 7m 10.244.2.215 k8s-3-219 none none 此时与默认迁移的区别是pod会先重建,然后终止。此时的服务中断时间=重建时间+ 服务启动时间+ 就绪探针检测正常时间,必须等到1/1 运行服务才会正常。因此,从单个副本迁移时,服务端点是不可避免的。

如何实现平滑迁移?我们继续往下看。

当k8s节点停机维护时,如何迁移pod?

平滑迁移

要实现平滑迁移,需要使用pdb(PodDisruptionBudget),即主动驱逐保护。默认迁移和手动迁移都会导致服务中断,但pdb在节点维护时可以保证不少于一定数量的pod正常运行,从而保证服务可用性。

以helloworld为例,由于只有一份副本,因此需要保证在维护期间迁移完成之前这份副本不会被终止。

# 从218 驱逐到219# 1. 将节点标记为不可调度# kubectl cordon k8s-3-218node/k8s-3-218 cordoned# 2. 创建新的pdbvim pdb-test.yamlapiVersion:policy/v1beta1kind: PodDisruptionBudgetmetadata: name: pdb-testnamespace33 36 0 testspec: minAvailable: 1 selector: matchLabels: app: helloworld# 2. Apply and view status# kubectl apply -f pdb-test.yaml# kubectl get pdb -n testNAME MIN AVAILABLE MAX UNAVAILABLE ALLOWED DISRUPTIONS AGEpdb-test 1 N/A 0 7s# 3. Eviction # kubectl排出k8s-3-218 --delete-local-data --ignore-daemonsets --forcenode/k8s-3-218已经cordonedWARNING:忽略DaemonSet管理的Pods: ingress-nginx/nginx-ingress-controller-hhb6h,kube-系统/kube-flannel-ds-amd64-pb4d7,kube-system/kube-proxy-rzdcjevicting pod kube-system/tiller-deploy-6c65968d87-ktqmmevicting pod kube-system/metrics-server-7f96bbcc66-6p6wmevicting pod test/helloworld- 79956d95b4-gg58 驱逐pod 'helloworld-79956d95b4-gg58c' 时出错(将在5 秒后重试): 无法驱逐pod,因为这会违反pod 的中断预算。驱逐pod test/helloworld-79956d95b4-gg58c 驱逐pod 'helloworld-79956d95b4-gg58c' 时出错(将在5 秒后重试): 无法驱逐pod,因为这会违反pod 的中断预算。pod/tiller-deploy-6c65968d87-ktqmm 驱逐#At这次,由于只有一份副本,可用的最小值为1,则ALLOWED 为0,因此在一份副本中不会通过pdb 发生驱逐。我们需要先扩容,调整副本数大于1。 # 3.手动调整副本数,设置副本数为2kubectl edit deploy helloworld -n test#再次检查pdb# kubectl get pdb -n testNAME MIN AVAILABLE MAX UNAVAILABLE ALLOWED DISRUPTIONS AGEpdb-test 1 N/A 1 13m#此时最小可用为1,ALLOWED为1,此时会自动计算数量。 # 4. 驱逐# kubectl duck k8s-3-218 --delete-local-data --ignore-daemonsets --force # 5. 维护后,调整节点为可调度# kubectl uncordon k8s-3-218 这次驱逐,由于helloworld始终维护一个pod提供服务,因此服务不会中断。最后将副本数调整为1并且将node节点调整为可调度,维护完成。

用户评论

此刻不是了i

k8s节点停机维护太头疼了~ 还是得想办法将pod迁移到其他可用节点.

    有17位网友表示赞同!

哭花了素颜

有没有什么工具可以帮助自动迁移pod呢?直接操作手动有点费劲啊。

    有20位网友表示赞同!

凝残月

我之前遇到过这种情况,后来用kubectl drain命令把pod驱逐到别的地方再重启节点挺管用的.

    有13位网友表示赞同!

夏以乔木

DRAIN命令要注意哪些参数设置?我试了没效果...

    有16位网友表示赞同!

歇火

迁移pod的时候要留意资源限制和服务依赖关系啊。

    有13位网友表示赞同!

温柔腔

这种维护,最好提前做好预告通知,避免影响业务可用

    有11位网友表示赞同!

繁华若梦

如果节点停机时间长,需要考虑部署到多租户环境下.

    有13位网友表示赞同!

微信名字

是不是应该定期测试一下pod迁移方案呢?提前预演,万一出意外就能及时解决。

    有10位网友表示赞同!

軨倾词

k8s真是个复杂的玩意儿...

    有6位网友表示赞同!

娇眉恨

这个节点维护策略文档在哪里找啊?

    有9位网友表示赞同!

糖果控

migrate pod, draining node, i need info!

    有14位网友表示赞同!

仅有的余温

集群升级的时候也要考虑pod迁移的问题吧

    有12位网友表示赞同!

何必锁我心

提前规划好资源分配,才能顺利进行node维护操作

    有11位网友表示赞同!

有一种中毒叫上瘾成咆哮i

这个drain命令的使用手册在哪里?

    有16位网友表示赞同!

你瞒我瞒

希望能找到一个全自动的pod迁移工具

    有12位网友表示赞同!

在哪跌倒こ就在哪躺下

有没有什么学习资源可以推荐一下?

    有14位网友表示赞同!

满心狼藉

希望migration能尽量快速,以减少业务受影响!

    有10位网友表示赞同!

本站涵盖的内容、图片、视频等数据,部分未能与原作者取得联系。若涉及版权问题,请及时通知我们并提供相关证明材料,我们将及时予以删除!谢谢大家的理解与支持!

Copyright © 2023