Kubernetes 和 kswapd0 是一对邪恶的夫妇?

Wal*_*ldo 0 memory debian kubernetes

我在 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
Run Code Online (Sandbox Code Playgroud)

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

如果我稍微强调一下微服务,它们就会停止响应,因为 kswapd0 使用了所有 CPU。我试着等待 kswapd0 停止他的工作,但它从未发生过。即使在 10 小时后。

我阅读了很多东西,但没有找到任何解决方案。

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

Kubernetes Masters 如何处理此类问题?

更多细节:

  • Kubernetes 1.15 版
  • 印花布 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
Run Code Online (Sandbox Code Playgroud)

meb*_*s99 6

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

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

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

该脚本用 100MB 的“Z”ASCII 代码块填充内存。为了实验公平,脚本在 Kubernetes 主机上启动,而不是在 pod 中启动,以便不涉及 k8s。这个脚本应该在 Python3 中运行。对其进行了一些修改,以便:

  • 兼容 3.6 之前的 Python 版本;
  • 将内存分配块设置为小于 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)
Run Code Online (Sandbox Code Playgroud)

您可以与测试系统建立 3 个终端连接以观察发生了什么:

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

运行脚本:

$ python3 ramhog.py
Run Code Online (Sandbox Code Playgroud)

在多次输入 Enter 键后(由我们设置的小内存分配块 (10MB) 引起),您会注意到

MemAvailable是越来越低,你的系统变得越来越少响应:ramhog.py输出

ramhog.pu 输出

免费页面会降到低水印以下:免费页面

区域信息

因此 kswapd 和 k8s 进程将被唤醒,CPU 利用率将提高至 100%:top

顶部命令输出

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

正如您从/proc/meminfo您提供的信息中看到的那样,MemAvailable它变得非常低,导致 kswapd 唤醒。也请查看/proc/zoneinfo您的服务器。

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

kswapd 行为的一个很好的解释是: kswapd is using a lot of CPU cycle