高效运维!K8s 多节点自动安全排空

本文首发:SRE运维手记 ,作者亦零一

有时候,部署一套 K8s 集群相对简单和轻松,但是在集群维护过程中,往往需要遵循一些规则和流程,否则可能会出现不可预知的故障,然而,一旦建立了规则和理清了流程,这些维护工作也会变得更加简单和流畅。

背景

在 K8s 集群的维护工作中,我们难免会遇到多节点维护的场景,如规格升级、集群迁移等,通过直接排空节点的操作将变得繁琐,且有风险,容易出现服务中断、集群抖动等情况,那么如何在多节点维护(下线)时保障应用的可用性及集群的稳定性将至关重要,接下来为大家分享多节点维护如何做到安全排空的方法。

维护流程及问题

首先,我们先看一下简单的维护流程,以及在多节点维护场景中可能出现的问题。

操作流程:

  1. 将节点设置为不可调度,阻止新的Pods调度到准备维护的节点上(K8s-node-1是示例节点名称,可通过kubectl get nodes进行查看)

kubectl cordon k8s-node-1

  1. 节点排空,驱逐节点上的Pods

kubectl drain k8s-node-1 --ignore-daemonsets

参数说明: --ignore-daemonsets: 不驱逐节点上的deamonset容器,这个参数是常用的

复制代码
--delete-emptydir-data: 当Pods被驱逐时,如果使用了emptyDir临时存储,数据也将被删除,可按需使用

多节点场景套用上述流程可能面临的问题:

  • 服务中断,如某个应用有 2 个副本,但同时被驱逐;或者其中一个副本未正常启动,另一个副本又被驱逐,导致服务不可用。
  • Kube-apiserver和etcd负荷过大,在短时间内触发多节点的Pods驱逐将会造成集群压力,可能引发集群抖动等风险。

解决方案

  • 引入PDB(PodDisruptionBudget)

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  # 节点操作间隔(秒)

# 日志文件
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 cordon $NODE; then
    echo "[$(date)] cordon node $NODE successfully" | tee -a $LOG_FILE
  else
    echo "[$(date)] Error cordon node $NODE" | tee -a $LOG_FILE
    return 1
  fi

  # 等待 3 秒以确保配置生效
  sleep 3

  # 排空节点
  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

节点恢复后,需要恢复可节点调度:

复制代码
#!/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 uncordon "$node"
  if [ $? -eq 0 ]; then
    echo "Successfully uncordon from node: $node"
  else
    echo "Failed to uncordon from node: $node"
  fi
done

echo "node uncordon process completed."

结 语

通过 PDB 的加持,及脚本的辅助,会让多节点维护的操作更加安全、顺畅和放心,本期分享就到这里,谢谢!

本文由博客一文多发平台 OpenWrite 发布!

相关推荐
iconball8 小时前
个人用云计算学习笔记 --18(NFS 服务器、iSCSI 服务器)
linux·运维·笔记·学习·云计算
₯㎕星空&繁华20 小时前
阿里云服务器安装MySQL服务器
服务器·ubuntu·阿里云·云计算
你的大佬9991 天前
阿里云百炼ai模型
人工智能·阿里云·云计算
一只栖枝1 天前
备考华为HCIA - 云计算,培训与自学到底该怎么选?
云计算·华为认证·hcia·考证·职业规划
数据与人工智能律师2 天前
AI的法治迷宫:技术层、模型层、应用层的法律痛点
大数据·网络·人工智能·云计算·区块链
荣光波比2 天前
Docker(三)—— Docker Compose 编排与 Harbor 私有仓库实战指南
运维·docker·容器·云计算
企鹅侠客2 天前
mysqldump导入备份数据到阿里云RDS会报错吗
阿里云·adb·云计算
iHero2 天前
【Jitsi Meet】阿里云Docker安装Jitsi Meet后的调整
阿里云·docker·云计算
荣光波比2 天前
Ansible(三)—— 使用Ansible自动化部署LNMP环境实战指南
运维·自动化·云计算·ansible
荣光波比2 天前
Docker(五)—— Docker Compose 一键搭建 LNMP 架构并部署 WordPress
运维·docker·容器·云计算