Керування своп-памʼяттю

Керування своп-памʼяттю

Kubernetes можна налаштувати на використання своп-памʼяті на вузлі, що дозволяє ядру звільняти фізичну памʼять, витісняючи сторінки до резервного сховища. Це корисно в багатьох сценаріях. Наприклад, на вузлах, де працюють робочі навантаження, яким може бути корисний своп, зокрема ті, що займають багато памʼяті, але в кожен момент часу звертаються лише до її частини. Своп також допомагає запобігти завершенню Podʼів під час стрибків тиску на памʼять, захищає вузли від стрибків використання памʼяті на рівні системи, які можуть порушити їх стабільність, дозволяє гнучкіше керувати памʼяттю на вузлі й багато іншого.

Щоб дізнатися про налаштування свопу у вашому кластері, прочитайте Налаштування своп-памʼяті на вузлах Kubernetes.

Підтримка операційних систем

  • Вузли Linux підтримують своп; для його увімкнення потрібно налаштувати кожен вузол. Стандартно kubelet не запускається на вузлі Linux, на якому увімкнено своп.
  • Вузли Windows потребують простору свопу. Стандартно kubelet не запускається на вузлі Windows, на якому вимкнено своп.

Як це працює?

Використання свопу на вузлі можна уявити кількома способами. Якщо kubelet уже працює на вузлі, після налаштування свопу його потрібно перезапустити, щоб він виявив своп.

Коли kubelet запускається на вузлі, на якому своп налаштовано й доступно (з конфігурацією failSwapOn: false), kubelet:

  • Зможе запуститися на цьому вузлі з увімкненим свопом.
  • Вказуватиме реалізації Container Runtime Interface (CRI), яку часто називають середовищем виконання контейнерів, стандартно виділяти робочим навантаженням Kubernetes нульовий обсяг своп-памʼяті.

Конфігурація свопу на вузлі доступна адміністратору кластера через memorySwap у KubeletConfiguration. Як адміністратор кластера ви можете вказати поведінку вузла за наявності своп-памʼяті, встановивши memorySwap.swapBehavior.

Поведінка свопу

Вам потрібно вибрати поведінку свопу. Різні вузли у вашому кластері можуть використовувати різну поведінку свопу.

Для вузлів Linux можна вибрати таку поведінку свопу:

NoSwap (стандартно)
Робочі навантаження, що працюють як Podʼи на цьому вузлі, не використовують і не можуть використовувати своп.
LimitedSwap
Робочі навантаження Kubernetes можуть використовувати своп-памʼять.

Примітка:

Якщо ви виберете поведінку NoSwap і налаштуєте kubelet на допуск простору свопу (failSwapOn: false), ваші робочі навантаження не використовуватимуть своп.

Однак процеси поза контейнерами під керуванням Kubernetes, такі як сервіси systemd (і навіть сам kubelet!), можуть використовувати своп.

Про ввімкнення свопу у вашому кластері читайте в розділі Налаштування своп-памʼяті на вузлах Kubernetes.

Інтеграція із середовищем виконання контейнерів

kubelet використовує API середовища виконання контейнерів і вказує йому застосувати певну конфігурацію (наприклад, для cgroup v2 — memory.swap.max) так, щоб увімкнути бажану конфігурацію свопу для контейнера. Для середовищ виконання, які використовують контрольні групи (cgroups), середовище виконання контейнерів відповідає за запис цих налаштувань до cgroup на рівні контейнера.

Спостережуваність використання свопу

Статистика метрик на рівні вузла та контейнера

kubelet тепер збирає статистику метрик на рівні вузла та контейнера, доступну через HTTP-точки доступу kubelet /metrics/resource (її використовують переважно інструменти моніторингу, такі як Prometheus) та /stats/summary (її використовують переважно автомасштабувальники). Це дозволяє клієнтам, які можуть безпосередньо надсилати запити до kubelet, відстежувати використання свопу та залишок своп-памʼяті під час використання LimitedSwap. Крім того, до cadvisor додано метрику machine_swap_bytes, яка показує загальну фізичну місткість свопу машини. Докладніше дивіться на цій сторінці.

Наприклад, підтримуються такі /metrics/resource:

  • node_swap_usage_bytes: поточне використання свопу вузлом у байтах.
  • container_swap_usage_bytes: поточне використання свопу контейнером у байтах.
  • container_swap_limit_bytes: поточне обмеження свопу контейнера в байтах.

Використання kubectl top --show-swap

Запити до метрик корисні, але дещо незручні, оскільки ці метрики призначені для програмного забезпечення, а не для людей. Щоб отримувати ці дані зручнішим способом, команду kubectl top розширено підтримкою метрик свопу через прапорець --show-swap.

Щоб отримати інформацію про використання свопу на вузлах, можна використовувати kubectl top nodes --show-swap:

kubectl top nodes --show-swap

Результат буде подібним до такого:

NAME    CPU(cores)   CPU(%)   MEMORY(bytes)   MEMORY(%)   SWAP(bytes)    SWAP(%)
node1   1m           10%      2Mi             10%         1Mi            0%
node2   5m           10%      6Mi             10%         2Mi            0%
node3   3m           10%      4Mi             10%         <unknown>      <unknown>

Щоб отримати інформацію про використання свопу Podʼами, можна використовувати kubectl top pods --show-swap:

kubectl top pod -n kube-system --show-swap

Результат буде подібним до такого:

NAME                                      CPU(cores)   MEMORY(bytes)   SWAP(bytes)
coredns-58d5bc5cdb-5nbk4                  2m           19Mi            0Mi
coredns-58d5bc5cdb-jsh26                  3m           37Mi            0Mi
etcd-node01                               51m          143Mi           5Mi
kube-apiserver-node01                     98m          824Mi           16Mi
kube-controller-manager-node01            20m          135Mi           9Mi
kube-proxy-ffgs2                          1m           24Mi            0Mi
kube-proxy-fhvwx                          1m           39Mi            0Mi
kube-scheduler-node01                     13m          69Mi            0Mi
metrics-server-8598789fdb-d2kcj           5m           26Mi            0Mi

Повідомлення вузлами про місткість свопу в статусі вузла

Додано нове поле статусу вузла node.status.nodeInfo.swap.capacity, щоб повідомляти про місткість свопу вузла.

Наприклад, за допомогою такої команди можна отримати місткість свопу вузлів у кластері:

kubectl get nodes -o go-template='{{range .items}}{{.metadata.name}}: {{if .status.nodeInfo.swap.capacity}}{{.status.nodeInfo.swap.capacity}}{{else}}<unknown>{{end}}{{"\n"}}{{end}}'

Результат буде подібним до такого:

node1: 21474836480
node2: 42949664768
node3: <unknown>

Примітка:

Значення <unknown> вказує на те, що поле .status.nodeInfo.swap.capacity не встановлено для цього вузла. Імовірно, це означає, що на вузлі не налаштовано своп або, менш імовірно, що kubelet не може визначити місткість свопу вузла.

Виявлення свопу за допомогою Node Feature Discovery (NFD)

Node Feature Discovery — це надбудова Kubernetes для виявлення апаратних можливостей і конфігурації. Її можна використовувати, щоб виявити, на яких вузлах налаштовано своп.

Наприклад, щоб зʼясувати, на яких вузлах налаштовано своп, використайте таку команду:

kubectl get nodes -o jsonpath='{range .items[?(@.metadata.labels.feature\.node\.kubernetes\.io/memory-swap)]}{.metadata.name}{"\t"}{.metadata.labels.feature\.node\.kubernetes\.io/memory-swap}{"\n"}{end}'

Результат буде подібним до такого:

k8s-worker1: true
k8s-worker2: true
k8s-worker3: false

У цьому прикладі своп налаштовано на вузлах k8s-worker1 та k8s-worker2, але не на k8s-worker3.

Ризики та застереження

Увага:

Настійно рекомендується шифрувати простір свопу. Докладніше дивіться в розділі томи в памʼяті.

Наявність свопу в системі знижує передбачуваність. Хоча своп може підвищити продуктивність, роблячи доступною більше оперативної памʼяті, повернення даних у памʼять є важкою операцією, іноді повільнішою на багато порядків, що може призвести до неочікуваного зниження продуктивності. Крім того, своп змінює поведінку системи під тиском на памʼять. Увімкнення свопу збільшує ризик галасливих сусідів, коли Podʼи, що часто використовують свою оперативну памʼять, можуть спричиняти витіснення інших Podʼів до свопу. Крім того, оскільки своп дозволяє робочим навантаженням у Kubernetes використовувати більше памʼяті, ніж можна передбачувано врахувати, а також через неочікувані конфігурації пакування, планувальник наразі не враховує використання своп-памʼяті. Це підвищує ризик галасливих сусідів.

Продуктивність вузла з увімкненою своп-памʼяттю залежить від фізичного сховища. Під час використання своп-памʼяті продуктивність буде значно гіршою в середовищі з обмеженою кількістю операцій вводу-виводу за секунду (IOPS), наприклад у хмарній віртуальній машині з тротлінгом вводу-виводу, порівняно зі швидшими носіями, такими як твердотільні накопичувачі або NVMe. Оскільки своп може спричиняти тиск на ввід-вивід, рекомендується надавати критично важливим системним демонам вищий пріоритет затримки вводу-виводу. Дивіться відповідний розділ у рекомендаціях нижче.

Томи в памʼяті

На вузлах Linux томи в памʼяті (такі як монтування томів secret або emptyDir з medium: Memory) реалізовано за допомогою файлової системи tmpfs. Вміст таких томів завжди має залишатися в памʼяті, тому його не слід витісняти на диск. Щоб вміст таких томів залишався в памʼяті, використовується параметр noswap для tmpfs.

Ядро Linux офіційно підтримує параметр noswap з версії 6.3 (докладніше дивіться у Вимогах до версії ядра Linux). Однак різні дистрибутиви часто переносять цей параметр монтування й у старіші версії Linux.

Щоб перевірити, чи підтримує вузол параметр noswap, kubelet виконує такі дії:

  • Якщо версія ядра вища за 6.3, вважається, що параметр noswap підтримується.
  • В іншому разі kubelet під час запуску спробує змонтувати фіктивний tmpfs з параметром noswap. Якщо kubelet отримає помилку, що вказує на невідомий параметр, вважатиметься, що noswap не підтримується, і його не буде використано. kubelet запише в лог запис, щоб попередити користувача, що томи в памʼяті можуть витіснятися на диск. Якщо kubelet виконає це успішно, фіктивний tmpfs буде видалено, а параметр noswap буде використано.
    • Якщо параметр noswap не підтримується, kubelet запише в лог попередження, а потім продовжить роботу.

Приклад налаштування свопу дивіться в розділі Налаштування своп-памʼяті на вузлах Kubernetes. Однак обробка зашифрованого свопу не входить до сфери відповідальності kubelet; це загальне питання конфігурації ОС, і його слід вирішувати на цьому рівні. Адміністратор відповідає за налаштування зашифрованого свопу, щоб зменшити цей ризик.

Виселення

Налаштування порогів виселення за памʼяттю для вузлів з увімкненим свопом може бути складним завданням.

Якщо своп вимкнено, доцільно налаштувати пороги виселення kubelet трохи нижче за місткість памʼяті вузла. Причина в тому, що Kubernetes має почати виселяти Podʼи до того, як на вузлі закінчиться памʼять і буде викликано OOM killer (Out Of Memory), оскільки OOM killer нічого не знає про Kubernetes, тому не враховує такі речі, як QoS, пріоритет Podʼів чи інші специфічні для Kubernetes чинники.

З увімкненим свопом ситуація складніша. У Linux параметр vm.min_free_kbytes визначає поріг памʼяті, за якого ядро починає агресивно вивільняти памʼять, зокрема витісняти сторінки до свопу. Якщо пороги виселення kubelet налаштовано так, що виселення відбувається раніше, ніж ядро почне вивільняти памʼять, робочі навантаження можуть ніколи не встигнути витіснити дані до свопу під час тиску на памʼять вузла. Однак занадто високі пороги виселення можуть призвести до вичерпання памʼяті на вузлі та виклику OOM killer, що теж не ідеально.

Щоб розвʼязати цю проблему, рекомендується встановлювати пороги виселення kubelet трохи нижчими за значення vm.min_free_kbytes. Так вузол може почати використовувати своп до того, як kubelet почне виселяти Podʼи, що дозволяє робочим навантаженням витісняти невикористовувані дані до свопу й запобігає виселенню. З іншого боку, оскільки значення лише трохи нижче, kubelet, імовірно, почне виселяти Podʼи до того, як на вузлі закінчиться памʼять, тим самим уникаючи OOM killer.

Значення vm.min_free_kbytes можна визначити, виконавши на вузлі таку команду:

cat /proc/sys/vm/min_free_kbytes

Невикористаний простір свопу

У режимі LimitedSwap обсяг свопу, доступний для Podʼа, визначається автоматично на основі частки запитаної памʼяті відносно загальної памʼяті вузла (докладніше дивіться розділ нижче).

Така архітектура означає, що зазвичай певна частина свопу залишатиметься недоступною для робочих навантажень Kubernetes. Наприклад, оскільки Kubernetes 1.37 не дозволяє використовувати своп Podʼам із класом QoS Guaranteed, обсяг свопу, пропорційний запиту памʼяті Podʼів Guaranteed, залишатиметься невикористаним робочими навантаженнями Kubernetes.

Така поведінка несе певний ризик у ситуації, коли багато Podʼів не мають права на своп. З іншого боку, вона фактично зберігає певний зарезервований системою обсяг своп-памʼяті, який можуть використовувати процеси поза межами Kubernetes, такі як системні демони й навіть сам kubelet.

Рекомендації щодо використання свопу в кластері Kubernetes

Вимкнення свопу для критично важливих системних демонів

Під час тестування та на основі відгуків користувачів було помічено, що продуктивність критично важливих системних демонів і сервісів може знижуватися. Це означає, що системні демони, зокрема kubelet, можуть працювати повільніше, ніж зазвичай. Якщо ви зіткнулися з цією проблемою, рекомендується налаштувати cgroup для system slice так, щоб запобігти свопінгу (тобто встановити memory.swap.max=0).

Захист критично важливих системних демонів від затримок вводу-виводу

Своп може збільшити навантаження вводу-виводу на вузлі. Коли тиск на памʼять змушує ядро швидко витісняти сторінки до свопу й повертати їх, критично важливі системні демони й сервіси, що покладаються на операції вводу-виводу, можуть зазнати зниження продуктивності.

Щоб помʼякшити це, користувачам systemd рекомендується надавати пріоритет system slice щодо затримки вводу-виводу. Користувачам без systemd рекомендується налаштувати окрему cgroup для системних демонів і процесів та так само надати їй пріоритет щодо затримки вводу-виводу. Цього можна досягти, встановивши io.latency для system slice, що надає йому вищий пріоритет вводу-виводу. Докладніше дивіться в документації cgroup.

Своп та вузли панелі управління

Проєкт Kubernetes рекомендує запускати вузли панелі управління без налаштованого простору свопу. Панель управління переважно розміщує Podʼи з класом QoS Guaranteed, тому своп зазвичай можна вимкнути. Основна проблема полягає в тому, що свопінг критично важливих сервісів на панелі управління може негативно вплинути на продуктивність.

Використання виділеного диска для свопу

Проєкт Kubernetes рекомендує використовувати зашифрований своп щоразу, коли ви запускаєте вузли з увімкненим свопом. Якщо своп розташований на розділі або в кореневій файловій системі, робочі навантаження можуть заважати системним процесам, яким потрібно записувати на диск. Коли вони використовують той самий диск, процеси можуть перевантажити своп, порушуючи ввід-вивід kubelet, середовища виконання контейнерів і systemd, що вплине на інші робочі навантаження. Оскільки простір свопу розташований на диску, важливо переконатися, що диск достатньо швидкий для запланованих сценаріїв. Альтернативно можна налаштувати пріоритети вводу-виводу між різними відображеними областями одного пристрою зберігання.

Планування з урахуванням свопу

Kubernetes 1.37 не підтримує розподіл Podʼів по вузлах з урахуванням використання своп-памʼяті. Планувальник зазвичай використовує запити ресурсів інфраструктури для вибору розміщення Podʼів, а Podʼи не запитують простір свопу; вони запитують лише memory. Це означає, що планувальник не враховує своп-памʼять під час прийняття рішень щодо планування. Хоча ми активно працюємо над цим, це ще не реалізовано.

Щоб Podʼи не планувалися на вузли зі своп-памʼяттю, якщо вони спеціально не призначені для її використання, адміністратори можуть додати taints на вузли з доступним свопом і так захиститися від цієї проблеми. Taints гарантують, що робочі навантаження, які допускають своп, не перетікатимуть під навантаженням на вузли без свопу.

Вибір сховища для оптимальної продуктивності

Пристрій зберігання, призначений для простору свопу, критично важливий для збереження чутливості системи під час високого використання памʼяті. Обертові жорсткі диски (HDD) погано підходять для цього, оскільки їх механічна природа вносить значну затримку, що призводить до серйозного зниження продуктивності та пробуксовування системи (thrashing). Для сучасних вимог до продуктивності, ймовірно, відповідним вибором для свопу є такий пристрій, як твердотільний накопичувач (SSD), оскільки його електронний доступ із низькою затримкою мінімізує сповільнення.

Подробиці поведінки свопу

Як визначається обмеження свопу для LimitedSwap?

Конфігурація своп-памʼяті, зокрема її обмежень, є значним викликом. Її не лише легко налаштувати неправильно, але й, оскільки це властивість рівня системи, будь-яке неправильне налаштування може поставити під загрозу весь вузол, а не лише конкретне робоче навантаження. Щоб зменшити цей ризик і забезпечити справність вузла, ми реалізували своп з автоматичною конфігурацією обмежень.

З LimitedSwap Podʼам, які не належать до класу QoS Burstable (тобто Podʼам із класом QoS BestEffort/Guaranteed), заборонено використовувати своп-памʼять. Podʼи з класом QoS BestEffort мають непередбачувані шаблони споживання памʼяті, а інформації про використання ними памʼяті немає, тому важко визначити безпечний обсяг своп-памʼяті. Натомість Podʼи з класом QoS Guaranteed зазвичай використовують для застосунків, які покладаються на точне виділення ресурсів, заданих робочим навантаженням, і на негайну доступність памʼяті. Щоб зберегти згадані вище гарантії безпеки та справності вузла, цим Podʼам не дозволено використовувати своп-памʼять, коли діє LimitedSwap. Крім того, високопріоритетним Podʼам не дозволено використовувати своп, щоб памʼять, яку вони споживають, завжди перебувала в RAM і була готова до використання.

Перш ніж докладно описати обчислення обмеження свопу, потрібно визначити такі терміни:

  • nodeTotalMemory: загальний обсяг фізичної памʼяті, доступної на вузлі.
  • totalPodsSwapAvailable: загальний обсяг своп-памʼяті на вузлі, доступний для використання Podʼами (частину своп-памʼяті може бути зарезервовано для потреб системи).
  • containerMemoryRequest: запит памʼяті контейнера.

Обмеження свопу налаштовується як: ( containerMemoryRequest / nodeTotalMemory ) × totalPodsSwapAvailable

Іншими словами, обсяг свопу, який може використовувати контейнер, пропорційний його запиту памʼяті, загальній фізичній памʼяті вузла та загальному обсягу своп-памʼяті на вузлі, доступному для використання Podʼами.

Важливо зазначити, що для контейнерів у Podʼах із класом QoS Burstable можна відмовитися від використання свопу, вказавши запити памʼяті, що дорівнюють обмеженням памʼяті. Контейнери, налаштовані таким чином, не матимуть доступу до своп-памʼяті.

Що далі

Змінено November 02, 2026 at 7:02 AM PST: [uk] Add cluster-administration/swap-memory-management.md (1d1b192222)