
Я собираю кластер Kubernetes на чистом железе (ничего сложного, всего три сервера) с помощью kubeadm на Debian 9. Как и просил Kubernetes, я отключаю SWAP:
- swapoff -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% ОЗУ каждый. А процесс kswapd0 начинает использовать много ресурсов ЦП.
Если я немного напрягаю микросервисы, они перестают отвечать, потому что kswapd0 использует весь процессор. Я пытаюсь подождать, пока kswapd0 остановит свою работу, но этого так и не произошло. Даже после 10 часов.
Я прочитал много информации, но так и не нашел решения.
Я могу увеличить объем оперативной памяти, но это не решит мою проблему.
Как мастера Kubernetes справляются с такого рода проблемами?
Подробнее:
- Kubernetes версии 1.15
- Калико версия 3.8
- Дебиан версии 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
~4000 из 4K страниц на моем тестовом сервере), kswapd вступает в дело. Это приводит к высокой загрузке ЦП.
Вы можете воспроизвести проблему и исследовать ее глубже следующим образом. Вам понадобится инструмент, который позволит вам потреблять память контролируемым образом, например скрипт, предложенный Романом Евстифеевым:ramhog.py
Скрипт заполняет память 100-мегабайтными фрагментами ASCII-кода "Z". Для честности эксперимента скрипт запускается на хосте Kubernetes, а не в pod, чтобы не задействовать k8s. Этот скрипт следует запустить в Python3. Он немного изменен, чтобы:
- быть совместимым с версиями Python ниже 3.6;
- установите размер выделяемого фрагмента памяти менее 4000 страниц памяти (малые страницы для зоны Normal в /proc/zoneinfo; я установил 10 МБ), чтобы в конечном итоге ухудшение производительности системы было более заметным.
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 терминальных соединения с тестовой системой, чтобы наблюдать за происходящим:
- запустить скрипт;
- выполнить верхнюю команду;
- получить /proc/zoneinfo
Запустите скрипт:
$ python3 ramhog.py
После нескольких нажатий клавиши Enter (из-за небольшого выделенного нами фрагмента памяти (10 МБ)) вы заметите, что
становится MemAvailable
все меньше и ваша система становится все менее и менее отзывчивой:вывод ramhog.py
Бесплатные страницы окажутся ниже нижней отметки:бесплатные страницы
В результате kswapd и процессы k8s проснутся, а загрузка ЦП возрастет до 100%:вершина
Обратите внимание, что скрипт работает отдельно от k8s, а SWAP отключен. Поэтому и Kubernetes, и kswapd0 простаивали в начале теста. Работающие pod'ы не были затронуты. Хотя со временем нехватка доступной памяти, вызванная третьим приложением, приводит к высокой загрузке ЦП: не только kswapd, но и k8s. Это означает, что первопричина — нехватка памяти, а не сами k8s или kswapd.
Как вы можете видеть из /proc/meminfo
предоставленного вами, MemAvailable
становится довольно низким, что приводит к пробуждению kswapd. Пожалуйста, посмотрите /proc/zoneinfo
также на вашем сервере.
На самом деле, первопричина не в конфликте или несовместимости k8s и kswap0, а в противоречии между отключенным swap и нехваткой памяти, что в свою очередь вызывает активацию kswapd. Перезагрузка системы временно решит проблему, но добавление большего количества оперативной памяти действительно рекомендуется.
Хорошее объяснение поведения kswapd можно найти здесь: kswapd использует много циклов ЦП
решение2
Kubernetes позволяет нам определить, сколько оперативной памяти мы должны сохранить для системы Linux, используя evictionHard.memory.available
параметр. Этот параметр задается в ConfigMap, который называется kubelet-config-1.XX
. Если объем оперативной памяти превышает уровень, разрешенный конфигурацией, Kubernetes начинает убивать Pod, чтобы сократить их использование.
В моем случае evictionHard.memory.available
параметр был установлен слишком низко (100Mi). Поэтому для системы Linux не хватает места в оперативной памяти, поэтому kswapd0 начинает бардак, когда использование оперативной памяти слишком велико.
После некоторых тестов, чтобы избежать появления kswapd0, я установил значение evictionHard.memory.available
. 800Mi
Процесс kswapd0 больше не глючил.