#!/usr/bin/env bash
# ==============================================================================
# 脚本名称: check_node_notready.sh
# 功能描述: 节点 NotReady 本地链路一键排查 (纯只读)
# 使用方式: 在故障 Node 节点以 root 权限执行
# ==============================================================================
set -o pipefail
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[0;33m'
BLUE='\033[0;34m'
PLAIN='\033[0m'
echo -e "${BLUE}================================================================${PLAIN}"
echo -e "${BLUE} Node NotReady 节点底层状态诊断 ${PLAIN}"
echo -e "${BLUE}================================================================${PLAIN}"
# 1. 检查核心组件运行状态
echo -e "\n${YELLOW}[1/4] 检查系统服务进程状态...${PLAIN}"
for svc in kubelet containerd docker; do
if systemctl list-unit-files | grep -q "^${svc}.service"; then
IS_ACTIVE=$(systemctl is-active "$svc" 2>/dev/null)
if [ "$IS_ACTIVE" == "active" ]; then
echo -e " -> ${GREEN}[OK] ${svc} 服务运行正常 (Active)。${PLAIN}"
else
echo -e " -> ${RED}[WARN] ${svc} 服务异常,当前状态: ${IS_ACTIVE}。请查阅 journalctl -u ${svc}。${PLAIN}"
fi
fi
done
# 2. 检查 Containerd Socket 通信路径
echo -e "\n${YELLOW}[2/4] 检查 Containerd Socket 配置与文件...${PLAIN}"
CONF_PATH="/etc/containerd/config.toml"
if [ -f "$CONF_PATH" ]; then
# 提取配置文件中配置的 address
SOCK_CONF=$(grep 'address' "$CONF_PATH" | grep '\.sock' | awk -F'"' '{print $2}' | head -n 1)
if [ -n "$SOCK_CONF" ]; then
echo -e " -> 配置文件中的 Socket 路径: ${SOCK_CONF}"
if [ -S "$SOCK_CONF" ]; then
echo -e " -> ${GREEN}[OK] Socket 文件实际存在,路径一致。${PLAIN}"
else
echo -e " -> ${RED}[WARN] 物理文件不存在!配置可能异常或服务未成功监听。${PLAIN}"
fi
else
echo -e " -> ${YELLOW}[INFO] 未在 config.toml 中提取到明文 socket address,可能使用了默认配置。${PLAIN}"
fi
else
echo -e " -> ${YELLOW}[INFO] 未找到 $CONF_PATH 文件。${PLAIN}"
fi
# 3. 检查常规默认套接字是否存在
echo -e "\n${YELLOW}[3/4] 检查默认通信通道物理连通性...${PLAIN}"
DEFAULT_SOCK="/var/run/containerd/containerd.sock"
if [ -S "$DEFAULT_SOCK" ]; then
echo -e " -> ${GREEN}[OK] 默认 Socket ($DEFAULT_SOCK) 存在并可读。${PLAIN}"
else
echo -e " -> ${RED}[WARN] 默认 Socket ($DEFAULT_SOCK) 丢失!如果是 Containerd 节点,Kubelet 将无法通信。${PLAIN}"
fi
# 4. 检查是否有引发失联的资源压力
echo -e "\n${YELLOW}[4/4] 检查系统资源硬限制 (Disk/Memory)...${PLAIN}"
MEM_FREE=$(free -m | awk 'NR==2{print $4}')
if [ "$MEM_FREE" -lt 200 ]; then
echo -e " -> ${RED}[WARN] 节点可用物理内存不足 200MB (${MEM_FREE}MB),易触发 Kubelet 僵死或 Eviction。${PLAIN}"
else
echo -e " -> ${GREEN}[OK] 内存容量相对安全 (可用 ${MEM_FREE}MB)。${PLAIN}"
fi
DISK_USE=$(df -h / | awk 'NR==2{print $5}' | tr -d '%')
if [ "$DISK_USE" -ge 90 ]; then
echo -e " -> ${RED}[WARN] 根分区使用率达到 ${DISK_USE}\%,易触发 DiskPressure 导致节点 NotReady。${PLAIN}"
else
echo -e " -> ${GREEN}[OK] 根分区使用率正常 (${DISK_USE}\%)。${PLAIN}"
fi
echo -e "\n${BLUE}================================================================${PLAIN}"
echo -e "${BLUE}诊断结束。若 Socket 路径正常但仍无法连接,请检查是否在集群 Master 执行了 kubectl describe 提取事件。${PLAIN}"
echo -e "${BLUE}================================================================${PLAIN}"