Kubernetes 和 kswapd0 是一对邪恶组合?

Kubernetes 和 kswapd0 是一对邪恶组合?

我在 Debian 9 上使用 kubeadm 构建了一个裸机 Kubernetes 集群(没什么大不了的,只有三台服务器)。按照 Kubernetes 的要求,我禁用了 SWAP:

  • 交换-a
  • 删除 SWAP 行/etc/fstab
  • 添加vm.swappiness = 0/etc/sysctl.conf

因此,我的服务器上不再有 SWAP。

$ free
              total        used        free      shared  buff/cache   available
Mem:        5082668     3679500      117200       59100     1285968     1050376
Swap:             0           0           0

一个节点用于运行一些微服务。当我开始使用所有微服务时,它们每个都使用了 10% 的 RAM。并且 kswapd0 进程开始使用大量 CPU。

如果我稍微强调一下微服务,它们就会停止响应,因为 kswapd0 占用了所有的 CPU。我尝试等待 kswapd0 是否停止工作,但这种情况从未发生过。即使过了 10 小时。

我读了很多资料,但没有找到任何解决方案。

我可以增加 RAM 数量,但这不能解决我的问题。

Kubernetes Masters如何处理此类问题?

更多细节:

  • Kubernetes 版本 1.15
  • Calico 版本 3.8
  • Debian 版本 9.6

首先感谢您的宝贵帮助。

-- 编辑 1 --

根据@john-mahowald 的要求

$ cat /proc/meminfo
MemTotal:        4050468 kB
MemFree:          108628 kB
MemAvailable:      75156 kB
Buffers:            5824 kB
Cached:           179840 kB
SwapCached:            0 kB
Active:          3576176 kB
Inactive:          81264 kB
Active(anon):    3509020 kB
Inactive(anon):    22688 kB
Active(file):      67156 kB
Inactive(file):    58576 kB
Unevictable:          92 kB
Mlocked:              92 kB
SwapTotal:             0 kB
SwapFree:              0 kB
Dirty:                 0 kB
Writeback:             0 kB
AnonPages:       3472080 kB
Mapped:           116180 kB
Shmem:             59720 kB
Slab:             171592 kB
SReclaimable:      48716 kB
SUnreclaim:       122876 kB
KernelStack:       30688 kB
PageTables:        38076 kB
NFS_Unstable:          0 kB
Bounce:                0 kB
WritebackTmp:          0 kB
CommitLimit:     2025232 kB
Committed_AS:   11247656 kB
VmallocTotal:   34359738367 kB
VmallocUsed:           0 kB
VmallocChunk:          0 kB
HardwareCorrupted:     0 kB
AnonHugePages:         0 kB
ShmemHugePages:        0 kB
ShmemPmdMapped:        0 kB
HugePages_Total:       0
HugePages_Free:        0
HugePages_Rsvd:        0
HugePages_Surp:        0
Hugepagesize:       2048 kB
DirectMap4k:      106352 kB
DirectMap2M:     4087808 kB

答案1

kswapd0 的这种行为是设计使然,并且是可以解释的。

尽管您已禁用并删除交换文件并将 swappiness 设置为零,但 kswapd 仍在关注可用内存。它允许您在不采取任何措施的情况下消耗几乎所有内存。但是,一旦可用内存降至极低值(区域 Normal 中的低页面,/proc/zoneinfo在我的测试服务器上约为 4K 页面的 4000 个),kswapd 就会介入。这会导致 CPU 利用率过高。

您可以重现该问题并通过以下方式进行深入调查。您将需要一个允许您以受控方式消耗内存的工具,例如 Roman Evstifeev 提供的脚本:ramhog.py

该脚本用 100MB 的 ASCII 代码“Z”填充内存。为了实验公平起见,该脚本在 Kubernetes 主机上启动,而不是在 pod 中启动,以便不让 k8s 参与。此脚本应在 Python3 中运行。它经过了一些修改,以便:

  • 兼容Python3.6之前的版本;
  • 将内存分配块设置为小于 4000 个内存页(/proc/zoneinfo 中区域 Normal 的低页面;我设置为 10 MB),以便系统性能下降最终更加明显。
from time import sleep

print('Press ctrl-c to exit; Press Enter to hog 10MB more')

one = b'Z' * 1024 * 1024  # 1MB hog = []

while True:
    hog.append(one * 10)  # allocate 10MB
    free = ';\t'.join(open('/proc/meminfo').read().split('\n')[1:3])
    print("{}\tPress Enter to hog 10MB more".format(free), end='')
    input()
    sleep(0.1)

您可以与测试系统建立 3 个终端连接来观察正在发生的事情:

  • 运行脚本;
  • 运行top命令;
  • 获取 /proc/zoneinfo

运行脚本:

$ python3 ramhog.py

在多次按下 Enter 键之后(由于我们设置的内存分配块较小(10MB)),你会注意到

越来越MemAvailable低,你的系统响应也越来越慢:ramhog.py 输出

ramhog.pu 输出

可用页面将落到低水位线以下:空闲页面

区域信息

因此 kswapd 将会唤醒,k8s 进程也会唤醒,CPU 利用率将升至 100%:顶部

top 命令输出

请注意,该脚本与 k8s 分开运行,并且 SWAP 已禁用。因此,在测试开始时,Kubernetes 和 kswapd0 都处于空闲状态。正在运行的 pod 未受到影响。尽管如此,随着时间的推移,第三个应用程序导致的可用内存不足会导致 CPU 利用率过高:不仅是 kswapd,还有 k8s。这意味着根本原因是内存不足,而不是 k8s 或 kswapd 本身。

/proc/meminfo您提供的 可以看出,MemAvailable变得非常低,导致 kswapd 被唤醒。请/proc/zoneinfo同时查看您服务器上的 。

其实根本原因不在于 k8s 与 kswap0 冲突或不兼容,而在于禁用 swap 与内存不足之间的矛盾,进而导致 kswapd 激活。系统重启可以暂时解决问题,但确实建议增加更多 RAM。

这里对 kswapd 行为进行了很好的解释: kswapd 占用了大量的 CPU 周期

答案2

Kubernetes 允许我们使用参数定义应为 Linux 系统保留多少 RAM evictionHard.memory.available。此参数在名为的 ConfigMap 中设置kubelet-config-1.XX。如果 RAM 超出配置允许的级别,Kubernertes 将开始终止 Pod 以减少其使用量。

在我的例子中,该evictionHard.memory.available参数设置得太低(100Mi)。因此,Linux 系统没有足够的 RAM 空间,因此当 RAM 使用率过高时,kswapd0 就会开始混乱。

经过一些测试,为了避免 kswapd0 的出现,我将 设置evictionHard.memory.available800Mi。kswapd0 进程不再混乱。

相关内容