K8S集群节点NotReady?别急着重启,先检查swap分区关了没(附VMware环境排查)

遇到K8S集群节点突然变成NotReady状态,很多运维人员的第一反应往往是"重启大法好"。但在VMware虚拟化环境中,这可能让你错过真正的罪魁祸首——未关闭的swap分区。本文将带你深入理解swap对K8S的影响,并提供一套完整的排查流程。

1. 为什么swap会导致K8S节点NotReady?

K8S从1.8版本开始就明确要求禁用swap,这背后有几个关键原因:

  • 内存压力管理冲突:K8S依赖cgroups进行内存限制,而swap会绕过这些限制,导致Pod可能使用超出分配的内存
  • 性能不可预测性:swap的随机I/O特性会显著降低容器性能,尤其在高负载时可能引发雪崩效应
  • 调度器决策失真:kube-scheduler基于节点可用内存做调度决策,swap的存在会扭曲真实内存情况

在VMware环境中这个问题尤为隐蔽,因为:

  1. 虚拟机模板可能默认启用swap
  2. 动态内存分配特性可能与K8S内存管理产生冲突
  3. 虚拟化层的内存气球驱动可能干扰K8S的内存统计

2. 诊断swap相关问题的完整流程

2.1 初步症状识别

当出现以下现象时,应该优先怀疑swap问题:

$ kubectl get nodes
NAME       STATUS     ROLES           AGE   VERSION
master01   Ready      control-plane   9d    v1.31.3 
slaver01   NotReady   <none>          9d    v1.31.3

伴随的典型错误信息包括:

  • dial tcp 127.0.1.1:6443: connect: connection refused
  • couldn't get current server API group list
  • The connection to the server was refused

2.2 关键诊断命令

首先检查容器运行时状态:

crictl ps

如果输出为空或只有少数系统容器,接着检查swap状态:

free -h
              total        used        free      shared  buff/cache   available
Mem:           7.7G        1.2G        5.8G         16M        728M        6.2G
Swap:          2.0G        1.5G        512M

重点关注Swap行的used值。在健康的K8S节点上,这个值应该全为0。

2.3 VMware环境特殊检查项

对于VMware虚拟机,还需要检查:

  1. 虚拟内存设置:
grep -i swap /etc/fstab
  1. 动态内存配置:
vmware-toolbox-cmd stat mem
  1. 内存气球驱动状态:
lsmod | grep balloon

3. 彻底解决swap问题的操作指南

3.1 立即禁用swap

临时解决方案(立即生效但重启后失效):

swapoff -a

永久解决方案(需在所有节点执行):

sed -i '/swap/d' /etc/fstab
systemctl mask --now swap.target

3.2 验证swap已关闭

确认命令:

free -h | grep -i swap

期望输出:

Swap:            0B          0B          0B

3.3 重启K8S组件

根据你的安装方式选择适当的重启命令:

对于kubeadm:

systemctl restart kubelet

对于二进制安装:

systemctl restart kube-apiserver kube-controller-manager kube-scheduler kubelet kube-proxy

4. 预防swap问题的长期策略

4.1 基础设施即代码配置

在Terraform或Ansible部署脚本中加入swap检查:

resource "null_resource" "disable_swap" {
  provisioner "local-exec" {
    command = <<EOF
      swapoff -a
      sed -i '/swap/d' /etc/fstab
    EOF
  }
}

4.2 集群初始化检查

在kubeadm init前添加预检:

#!/bin/bash
if [[ $(free | awk '/Swap/{print $2}') -ne 0 ]]; then
  echo "ERROR: Swap must be disabled before installing Kubernetes"
  exit 1
fi

4.3 持续监控方案

配置Prometheus告警规则:

groups:
- name: node.rules
  rules:
  - alert: NodeSwapEnabled
    expr: node_memory_SwapTotal_bytes > 0
    for: 5m
    labels:
      severity: critical
    annotations:
      summary: "Swap is enabled on node {{ $labels.instance }}"
      description: "Kubernetes node {{ $labels.instance }} has swap enabled ({{ $value }} bytes)"

5. 高级排错技巧

当标准方法不奏效时,可以尝试:

  1. 检查内核参数:
sysctl vm.swappiness
  1. 深度分析kubelet日志:
journalctl -u kubelet --no-pager | grep -i swap
  1. 使用systemd-cgtop检查内存压力:
systemd-cgtop -m
  1. 对于顽固的swap使用,定位具体进程:
for file in /proc/*/status ; do awk '/VmSwap|Name/{printf $2 " " $3}END{ print ""}' $file; done | sort -k 2 -n -r | head

记住,在VMware环境中,还需要考虑虚拟化层的内存管理特性。如果问题持续存在,可能需要调整虚拟机的内存预留设置或考虑使用静态内存分配。

更多推荐