如何优雅的从k8s中移除Node?

内容纲要

背景

在目前的环境下,公司的业务缩减。公司开启了一波降本增效, 我们IT部门也进行了积极的响应。

首先先对我们的服务器进行大幅缩减,然后数据库和带宽配置进行了腰斩。

由于我们的业务系统运行在阿里云,涉及到的资源基本包括:EIP, CLB, ECS, RDS-Redis,RDS-MySQL等等。此次降本增效大部分都是阿里云给我们提供了无缝切换,但是唯一一个就是ECS。我们业务系统运行在自建的k8s集群中,并没有使用阿里云提供的AKS。那么减少ECS数量需要我们自己来干, 减少ECS在我们的场景中就是移除k8s Node。

需求

优雅移除k8s Node而不影响业务的可用性,对用户无感知。

k8s对增减Node支持

  1. 添加Node到集群: kubeadmin join
  2. 查询集群中Node列表: kubectl get nodes
  3. 从集群移除Node: kubectl drain node, kubectl cordon node, kubectl delete node

特别注意

这个特别注意就是不要在你驱逐node的时候服务还有其他Pod可以支持继续为用户提供服务。

这个可以有很多方案来实现啦,我这儿提供2个:

  1. 确保Pod副本是分布在不同的Node中,从而避免一个服务的所有Pod副本都在一个Node导致驱逐Node时导致系统宕机
  2. 保证服务Pod最小可用副本数

第一个解决方案可以使用Node的反亲和性来解决:

第二个解决方案可以使用PDB(PodDisruptionBudget )来保证Pod的最小副本数。

实施步骤

  1. 获取Node
  2. 驱逐节点上的 Pod
  3. 确认 Pod 已迁移
  4. 从集群中删除节点
  5. (可选)停止并重置kubelet
  6. (可选)重新加入集群

第一步和第二步可以使用kubectl drain命令来完成。
file

详细步骤

1. 获取Node

首先我们使用kubectl get nodes | grep <node-name>获取想要驱逐的Node,


kubectl get nodes

2. 驱逐节点上的 Pod

接下来,我们需要将节点上的现有 Pod 驱逐到其他节点。使用 kubectl drain 命令可以完成这个操作(可能你的node中有daemonset和local data, 可以使用--ignore-daemonsets--delete-local-data来忽略和删除):

kubectl drain <node-name> --ignore-daemonsets --delete-local-data

示例:

kubectl drain node-1 --ignore-daemonsets --delete-local-data

参数解释:

  • --ignore-daemonsets:忽略 DaemonSet 管理的 Pod。
  • --delete-local-data:删除使用 emptyDir 卷的 Pod。

这个命令会驱逐节点上的所有 Pod,并将它们重新调度到其他节点。注意,这一步可能需要一些时间,具体取决于节点上的 Pod 数量和资源情况。

3. 确认 Pod 已迁移

在驱逐操作完成后,使用以下命令确认所有 Pod 已经从目标节点迁移:

kubectl get pods --all-namespaces -o wide | grep <node-name>

示例:

kubectl get pods --all-namespaces -o wide | grep node-1

如果命令没有返回任何结果,说明 Pod 已经成功迁移。

4. 从集群中删除节点

确认 Pod 已迁移后,我们可以安全地从集群中删除节点:

kubectl delete node <node-name>

示例:

kubectl delete node node-1

这个命令会将节点从 Kubernetes 集群中移除。

5. (可选)停止并重置kubelet

如果Node后面不再使用了,那么可以停止kubelet服务:


sudo systemctl stop kubelet

另外,还可以使用kubeadm 重置Node

sudo kubeadm reset
sudo rm -rf ~/.kube

6. (可选)重新加入集群

如果你的Node只是想做一些系统维护的工作,维护完成后重新加入集群并接受调度,那么就可以使用kubeadm重新加入集群:

# 生成加入集群的Token
kubeadm token create --print-join-command

# 加入集群
kubeadm join <master-node>:<api-port> --token <your-token> --discovery-token-ca-cert-hash sha256:<hash>

# 验证Node是否加入集群
kubectl get nodes

# 此时可以看到Node并且状态是Ready

注意事项

  • 在执行这些操作之前,请确保集群有足够的资源来承载被驱逐的 Pod(根据情况给当前Node加点CPU和内存不过分吧~)。
  • 驱逐操作可能会影响业务,建议在业务低峰期执行(在之前先通知用户,系统升级可能会不可用,先说断后不乱~)。

参考

  1. kubectl drain
  2. How to gracefully remove a node from Kubernetes?

发表评论

您的电子邮箱地址不会被公开。 必填项已用 * 标注

滚动至顶部