有时候,部署一套k8s集群相对简单和轻松,但是在集群维护过程中,往往需要遵循一些规则和流程,否则可能会出现不可预知的故障,然而,一旦建立了规则和理清了流程,这些维护工作也会变得更加简单和流畅。
01、背景
在k8s集群的维护工作中,我们难免会遇到多节点维护的场景,如规格升级、集群迁移等,通过打污点和排空的操作将变得繁琐,且有风险,容易出现服务中断、集群抖动等情况,那么如何在多节点维护(下线)时保障应用的可用性及集群的稳定性将至关重要,接下来为大家分享网上或者教程极少提及的多节点维护安全排空的方法。
02、维护流程及问题
首先,我们先看一下简单的维护流程,以及在多节点维护场景中可能出现的问题。
kubectl taint nodes k8s-node-1 drain=true:NoSchedule
2. 节点排空,驱逐节点上的Pods
kubectl drain k8s-node-1 --ignore-daemonsets
参数说明:
--ignore-daemonsets: 不驱逐节点上的deamonset容器,这个参数是常用的
--delete-emptydir-data: 当Pods被驱逐时,如果使用了emptyDir临时存储,数据也将被删除,可按需使用
03、解决方案
PDB是k8s中的一种机制,用于确保节点在进行维护时,应用的Pod副本不会被全部驱逐,从而保障应用的高可用性。所以建议将核心的应用配置上PDB,保障其最小可运行的容器数量,如下是配置的示例。
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: zeus
namespace: prod
spec:
minAvailable: 1 # 保障最小可用数量为1
selector:
matchLabels:
app: zeus
PDB的两个参数:
minAvailable: 指定最少必须可用的Pod数量或比例。
maxUnavailable: 指定最多可以不可用的Pod数量或比例。
PDB策略查看:
kubectl get pdb -n prod
有PDB的加持,会让多节点维护得更加安全和放心。
为了减轻kube-apiserver和etcd的压力,避免造成k8s集群抖动,但是依靠人肉敲指令,数量少还好,如果数量多简直是要了运维老命,所以我们会借助脚本实现,具体如下:
这个脚本可以帮助你逐台进行打污点和排空,可根据实际场景调整执行的时间间隔,另外也会将执行的结果输出到日志drain_nodes.log。
#!/bin/bash
# 节点列表,用逗号分隔
NODES_STRING="k8s-node-1,k8s-node-2,k8s-node-3"
# 将字符串转换为数组
IFS=',' read -r -a NODES <<< "$NODES_STRING"
SLEEP_INTERVAL=300 # 节点操作间隔(秒)
TAINT_KEY="drain" # 污点Key
TAINT_VALUE="true" # 污点Value
TAINT_EFFECT="NoSchedule" # 污点效果
# 日志文件
LOG_FILE="drain_nodes.log"
# 清空日志
> $LOG_FILE
# 排空节点方法
drain_node() {
local NODE=$1
echo "[$(date)] Starting to process node $NODE" | tee -a $LOG_FILE
# 给节点添加污点
if kubectl taint nodes $NODE $TAINT_KEY=$TAINT_VALUE:$TAINT_EFFECT; then
echo "[$(date)] Tainted node $NODE successfully" | tee -a $LOG_FILE
else
echo "[$(date)] Error tainting node $NODE" | tee -a $LOG_FILE
return 1
fi
# 等待 10 秒以确保新 Pod 不会被调度到这个节点
sleep 10
# 排空节点
if kubectl drain $NODE --ignore-daemonsets; then
echo "[$(date)] Drained node $NODE successfully" | tee -a $LOG_FILE
return 0
else
echo "[$(date)] Error draining node $NODE" | tee -a $LOG_FILE
return 1
fi
}
# 节点遍历
for NODE in "${NODES[@]}"; do
if drain_node $NODE; then
echo "[$(date)] Node $NODE processed successfully" | tee -a $LOG_FILE
else
echo "[$(date)] Failed to process node $NODE. Check $LOG_FILE for details." | tee -a $LOG_FILE
fi
sleep $SLEEP_INTERVAL
done
执行效果:
[yilingyi@k8s-node-1 ~]$ sh drain_nodes.sh
[Sun Nov 3 18:13:04 CST 2024] Starting to process node k8s-node-1
node/k8s-node-1 tainted
[Sun Nov 3 18:13:04 CST 2024] Tainted node k8s-node-1 successfully
node/k8s-node-1 cordoned
[Sun Nov 3 18:13:14 CST 2024] Node k8s-node-1 processed successfully
节点恢复后需要清除添加的污点,Pods才能调度到节点上:
#!/bin/bash
# 定义包含节点名称的字符串变量
NODES_STRING="k8s-node-1,k8s-node-2,k8s-node-3"
# 将NODES_STRING分割成数组
IFS=',' read -r -a nodes <<< "$NODES_STRING"
# 遍历每个节点并删除特定污点
for node in "${nodes[@]}"
do
echo "Removing taint from node: $node"
kubectl taint nodes "$node" drain-
if [ $? -eq 0 ]; then
echo "Successfully removed taint from node: $node"
else
echo "Failed to remove taint from node: $node"
fi
done
echo "Taint removal process completed."
04、结 语
通过PDB的加持,及脚本的辅助,会让多节点维护的操作更加安全、顺畅和放心,本期分享就到这里,谢谢!