当前位置: 首页 > article >正文

高效运维!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 发布!


http://www.kler.cn/a/537083.html

相关文章:

  • 用AVFrame + AVPacket 完成accede编码和直接用ffmpeg命令行实现acc编码的对比
  • 【Linux】25.进程信号(1)
  • NetCore Consul动态伸缩+Ocelot 网关 缓存 自定义缓存 + 限流、熔断、超时 等服务治理
  • 鸿蒙UI(ArkUI-方舟UI框架)- 使用文本
  • ubuntu20使用tigervnc远程桌面配置记录
  • 【工具篇】深度揭秘 Midjourney:开启 AI 图像创作新时代
  • 为多个GitHub账户配置SSH密钥
  • PostgreSQL 中的 EXTRACT 函数_操作日期
  • 服务器磁盘高占用排查
  • Qt 数据库SQLite 使用【01】基本功能
  • Lua中文语言编程源码-第十一节,其它小改动汉化过程
  • Android studio 创建aar包给Unity使用
  • 使用 Axios ——个人信息修改
  • ES6 Set 数据结构用法总结
  • Flutter List 的 every 如果回调函数抛出异常 应该如何处理
  • 尚硅谷 vue3+TS 课程笔记
  • Flutter Isolate解决耗时任务导致卡死
  • 工业以太网profinet网关:解锁生产效率提升的“超级钥匙”
  • 【DeepSeek-R1训练笔记】随手记录一些训练log
  • 【leetcode100】岛屿的最大面积
  • Rust语言进阶之标准输入: stdin用法实例(一百零五)
  • CRM系统中的数据分析和报表功能如何帮助企业?
  • 58页PPT学习华为面向业务价值的数据治理实践
  • windows版的docker如何使用宿主机的GPU
  • nas-群晖docker查询注册表失败解决办法(平替:使用SSH命令拉取ddns-go)
  • opentelemetry-collector 配置elasticsearch