Назад | Перейти на главную страницу

Kubernetes и kswapd0 злая парочка?

Я создаю кластер kubernetes с нуля (ничего тяжелого, всего три сервера) с помощью kubeadm на Debian 9. Как и в случае с Kubernetes, я отключаю SWAP:

Итак, на моих серверах больше нет 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 справляются с подобными проблемами?

Подробнее:

Заранее благодарю вас за вашу бесценную помощь.

- Редактировать 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

Такое поведение kswapd0 является намеренным и объяснимым.

Хотя вы отключили и удалили файл подкачки и установили для swappiness значение 0, kswapd следит за доступной памятью. Это позволяет вам использовать почти всю память, не предпринимая никаких действий. Но как только доступная память упадет до критически низкого значения (низкие страницы для зоны Нормальный в /proc/zoneinfo, ~ 4000 страниц размером 4 КБ на моем тестовом сервере) вмешивается kswapd. Это приводит к высокой загрузке ЦП.

Вы можете воспроизвести проблему и изучить ее более детально следующим образом. Вам понадобится инструмент, позволяющий контролировать потребление памяти, например скрипт, предложенный Романом Евстифеевым: ramhog.py

Сценарий заполняет память фрагментами кода ASCII "Z" размером 100 МБ. Для честности эксперимента скрипт запускается на хосте Kubernetes, а не в поде, чтобы 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 в начале теста простаивали. Ходовые стручки не тронули. Хотя со временем нехватка доступной памяти, вызванная третьим приложением, вызывает высокую загрузку процессора: не только kswapd, но и k8s. Это означает, что основная причина - нехватка памяти, но не сами k8s или kswapd.

Как видно из /proc/meminfo вы предоставили MemAvailable становится достаточно низким, из-за чего kswapd просыпается. Пожалуйста, посмотрите на /proc/zoneinfo на вашем сервере тоже.

На самом деле основная причина не в конфликте или несовместимости между k8s и kswap0, а в противоречии между отключенным свопом и нехваткой памяти, что, в свою очередь, вызывает активацию kswapd. Перезагрузка системы временно решит проблему, но рекомендуется добавить больше ОЗУ.

Хорошее объяснение поведения kswapd находится здесь: kswapd использует много циклов процессора

Kubernetes позволяет нам определить, сколько оперативной памяти мы должны оставить для системы Linux, используя evictionHard.memory.available параметр. Этот параметр устанавливается в ConfigMap под названием kubelet-config-1.XX. Если объем оперативной памяти превышает допустимый конфигурацией уровень, Kubernertes начинает убивать поды, чтобы уменьшить их использование.

В моем случае evictionHard.memory.available параметр был установлен слишком низким (100Mi). Таким образом, для системы Linux недостаточно места в ОЗУ, поэтому kswapd0 начинает беспорядок, когда используется слишком много ОЗУ.

После некоторых тестов, чтобы избежать роста kswapd0, я установил evictionHard.memory.available к 800Mi. Процесс kswapd0 больше не мешал.