Ви натискаєте Start на ВМ, а Proxmox відповідає цифровим еквівалентом зітхання:
«неможливо виділити пам’ять». Або ще гірше — ВМ запускається, а хост починає вбивати випадкові процеси,
ніби стресований театральний суфлер у залі з одним виходом.
Помилки пам’яті в Proxmox не містять містики. Це проблеми звітності: що хост вважає, що у нього є,
що ВМ заявляють, що вони можуть використати, що вони фактично торкаються, і що ядро готове
обіцяти в цей момент. Виправте облік — і більшість драми зникне.
Швидкий план діагностики
Якщо ви на виклику і кластер кричить, вам не потрібна філософська лекція. Потрібен короткий цикл:
підтвердити режим відмови, визначити обмежувач, зробити одну безпечну зміну, повторити.
По-перше: це виснаження пам’яті хоста чи обмеження на ВМ?
-
Якщо ВМ не вдається запустити з повідомленням «неможливо виділити пам’ять», підозрюйте
ліміти коміту хоста, обмеження cgroup, hugepages або фрагментацію — це часто помітно одразу вdmesg/ журналах. -
Якщо ВМ запускається, а потім її вбивають, зазвичай це OOM killer у гостьовій ОС (всередині ВМ) або
OOM killer хоста (вбиває QEMU), залежно від того, в яких логах видно труп.
По-друге: перевірте реальний запас хоста, а не гарні графіки
- Вільна пам’ять хоста і swap:
free -h - Тиск пам’яті і затримки при звільненні:
vmstat 1 - Докази OOM:
journalctl -kтаdmesg -T - Розмір ZFS ARC (якщо використовуєте ZFS):
arcstat//proc/spl/kstat/zfs/arcstats
По-третє: перевірте політику та виділення зі сторони Proxmox
-
Конфіг ВМ: ціль балона vs max, hugepages, NUMA тощо:
qm config <vmid> -
Політика перевиділення на вузлі:
pvesh get /nodes/<node>/statusта
/etc/pve/datacenter.cfg -
Якщо це контейнер (LXC), перевірте обмеження пам’яті cgroup і ліміт swap:
pct config <ctid>
По-четверте: виберіть найменш шкідливе негайне пом’якшення
- Зупиніть одну некритичну ВМ, щоб звільнити RAM і знизити тиск прямо зараз.
- Якщо ZFS «їсть» сервер: обмежте ARC (постійно) або, в крайньому разі, перезавантажте.
- Якщо ви перевиділяєте: зменшіть max-пам’ять ВМ (не лише ціль балона).
- Якщо swap відсутній і ви напружені: додайте swap (на хості), щоб уникнути миттєвого OOM, поки ви виправляєте розміри.
Жарт №1: Перевиділення пам’яті — як корпоративний бюджет: все працює, поки всі не спробують одночасно відшкодувати обід.
Що насправді означає «неможливо виділити пам’ять» в Proxmox
Proxmox — це шар управління. Реальний аллокатор — Linux, а для ВМ зазвичай QEMU/KVM. Коли ви бачите
«неможливо виділити пам’ять», відбувається одне з наступного:
-
QEMU не може зарезервувати запитану ВМ оперативну пам’ять під час старту. Це може завершитись невдачею,
навіть якщоfreeвиглядає нормально, бо Linux дбає про правила коміту і фрагментацію. -
Ядро відмовляє в алокації через логіку overcommit/CommitLimit. Linux відстежує, скільки пам’яті
процеси пообіцяли потенційно використати (віртуальна пам’ять), і може відмовляти новим обіцянкам. -
Запитані hugepages відсутні. Hugepages вирізані заздалегідь. Якщо їх немає, алокація провалюється
миттєво й голосно. - Обмеження cgroup блокують алокацію. Частіше трапляється з контейнерами, але може впливати, якщо залучені systemd slices або кастомні cgroups.
- Пам’ять є, але не в формі, яку ви просите. Фрагментація може перешкодити великим суміжним виділенням, особливо для hugepages або певних DMA-вимог.
Тим часом «рішення», до якого звертаються люди — балонінг — не змінює того, що QEMU попросив, якщо ви все ще встановили великий
max пам’яті. Балонінг регулює те, що гість заохочують використовувати, а не те, що хост має бути готовий забезпечити в найгірший момент.
Два числа, що мають значення: target гостьової пам’яті і guest max
В опціях ВМ Proxmox балонінг дає вам:
- Memory (max): стеля ВМ. QEMU виконує облік для неї.
- Balloon (min/target): ціль під час виконання, яку можна зменшити під тиском.
Якщо ви встановлюєте max на 64 ГіБ «на всяк випадок» і ціль балона на 8 ГіБ «бо зазвичай простаєте», ви сказали хосту:
«Будь ласка, будь готовий фінансувати мій 64 ГіБ стиль життя». Хост, будучи дорослим, може сказати «ні».
Цікавинки та трохи історії (щоб більше не повторювати помилок)
-
Поведінка Linux щодо overcommit стара і свідома: вона існує, бо багато алокацій ніколи не використовуються повністю,
і суворий облік витрачав би RAM на порожні обіцянки. - OOM killer з’явився задовго до сучасних віртуалізаційних стеків; це був прагматичний відповідь Linux на «хтось брешe про пам’ять» задовго до того, як маркетинг хмар перетворив брехню на фічу.
- Балонінг став поширеним з ранніми гіпервізорами, бо прості гості скуповували кеш і робили консолідацію гіршою, ніж вона мала бути.
- KSM (Kernel Samepage Merging) призначений для дедуплікації ідентичних сторінок пам’яті між ВМ — корисно, коли багато ВМ з однаковим образом ОС.
- Transparent Huge Pages (THP) були введені для підвищення продуктивності через більші сторінки, але вони можуть створювати спади латентності під тиском пам’яті через роботу з компактування.
-
ZFS ARC — це не «просто кеш». Він конкурує з анонімною пам’яттю. Якщо ви не обмежите його, він із задоволенням візьме RAM,
поки ядро не змусить віддати — іноді запізно. - cgroups змінили гру: замість того, щоб весь хост був однією дружною сім’єю, тепер обмеження пам’яті можуть зробити так, що одна ВМ або контейнер впаде, навіть коли хост виглядає нормально.
- Swap колись був обов’язковою порадою; потім люди ним зловживали; потім його відкидали; потім сучасні SSD зробили «невеликий контрольований swap» знову розумним у багатьох випадках.
Операційна цитата, що лишається болісно актуальною (парафраз): Вернер Фогельс казав, що суть надійності — очікувати відмов і проектувати під них, а не прикидатися, що їх не буде.
Балонінг: що він робить, чого не робить і чому він вас вводить в оману
Що таке балонінг насправді
Балонінг використовує драйвер всередині гостя (зазвичай virtio-balloon). Хост просить гостя «надути» балон,
тобто: виділити пам’ять всередині гостя й зафіксувати її так, щоб гість не міг її використовувати. Ця пам’ять стає
придатною для звільнення з точки зору хоста, бо гість добровільно її віддав.
Це хитро. Але є обмеження фізики та поведінки гостя:
- Якщо гість під реальним тиском пам’яті, він не зможе багато віддати без swap або OOM всередині себе.
- Якщо в гості немає драйвера балона, балонінг — це по суті пантоміма.
- Балонінг реактивний. Якщо хост уже в біді, може бути запізно.
Важливий нюанс балонінгу в Proxmox
Конфігурація балонінгу в Proxmox часто дає хибне відчуття безпеки. Люди ставлять низькі цілі балона і високі max-пам’яті,
думаючи, що «використовують лише ціль». Але облік QEMU і логіка коміту ядра часто повинні враховувати максимум.
Операційна позиція: балонінг — це інструмент налаштування, а не привід уникати правильної оцінки розміру.
Використовуйте його для еластичних навантажень, де гостьова ОС може впоратися. Не робіть з нього основну стратегію упакування хоста до межі.
Коли балонінг вартий застосування
- Кластери для розробки/тестування, де гості простаивают, а стрибки рідкісні й терпимі.
- Флоти VDI-подібних ВМ з багатьма схожими образами, часто разом із KSM.
- Звичайні серверні флоти, де ви можете забезпечити реалістичні max-значення, а не фантазії.
Коли балонінг — пастка
- Бази даних з жорсткою затримкою та великими buffer pool — тиск в гості переводиться в IO-тиск.
- Системи з вимкненим swap всередині гостей (балонінг може викликати OOM у гості).
- Хости, що вже напружені по пам’яті, де час реакції балона занадто повільний.
Перевиділення: коли це розумно, а коли — ризиковано
Три різні «перевиділення», які плутають люди
На практиці ви балансуєте три шари:
-
Перевиділення у планувальнику/обліку Proxmox: чи вважає Proxmox, що можна запустити ще одну ВМ
на основі налаштованої RAM, цілей балона і пам’яті вузла. -
Поведінка перевиділення в Linux:
vm.overcommit_memoryіCommitLimit. -
Фактичне фізичне перевиділення: чи перевищує сума активно використовуваної гостями пам’яті RAM хоста
(і чи є у вас swap, компресія чи план дій).
Коротко про облік коміту в Linux в одній абзаці для операцій
Linux вирішує, чи дозволити алокацію, виходячи з того, скільки пам’яті може бути використано, якщо процеси її торкнуться.
Це число відстежується як Committed_AS. Дозволений поріг — CommitLimit,
приблизно RAM + swap мінус деякі резерви, змінений налаштуваннями overcommit. Якщо Committed_AS наближається
до CommitLimit, ядро починає відмовляти в алокаціях — привіт, «неможливо виділити пам’ять».
Думка щодо практики
-
Продакшен: тримайте перевиділення помірним і забезпечуйте реалістичні max ВМ. Якщо ви не можете вказати
співвідношення перевиділення і план евакуації, ви не перевиділяєте — ви граєте в азартні ігри. - Лабораторія: перевиділяйте агресивно, якщо готові до випадкових OOM. Просто маркуйте це чесно і не прикидайтеся, що це продакшен.
-
Змішані навантаження: або відокремте «шумних» користувачів пам’яті (БД, аналітика) на окремі вузли,
або ж жорстко їх обмежуйте. «Співіснування» — так називають те, що люди говорять перед інцидентом.
ZFS ARC, page cache і пам’ять хоста, про яку ви забули
Proxmox часто працює на ZFS через зручність снапшотів і send/receive. Але ZFS не соромиться: він використовує RAM
для ARC (Adaptive Replacement Cache). Це добре, поки не стає проблемою.
ARC проти «вільної пам’яті»
ARC придатний для звільнення, але не миттєво і не завжди в тій формі, яку потребує запуск ВМ. При тиску ядро
намагається звільнити page cache і ARC, але якщо ви в циклі швидких алокацій (запуск ВМ, надування пам’яті,
форкінг процесів), ви можете отримати транзитні відмови.
Що робити
-
На хостах з ZFS і багатьма ВМ встановіть розумний максимум ARC (
zfs_arc_max). Не дозволяйте ARC «боротися» з вашими гостями. -
Розглядайте пам’ять хоста як спільну інфраструктуру. Хост потребує пам’яті для:
ядра, slab, мережі, метаданих ZFS, оверхеду QEMU та ваших агентів моніторингу, які клянуться бути легкими.
Swap: не гріх, але й не план життя
Відсутність swap означає, що ви забрали амортизатори. У віртуалізації це може бути фатально, бо раптовий сплеск тиску
перетворюється на миттєві OOM-вбивства замість повільного, діагностованого погіршення.
Але swap також може стати перетягуванням продуктивності. Мета — контрольований swap: достатньо, щоб пережити сплески,
але не стільки, щоб приховати хронічне перевиділення.
Рекомендації щодо swap на хості (практично, не догма)
- Якщо ви працюєте на ZFS і маєте багато ВМ: додайте swap. Навіть помірна кількість може запобігти вбиванню QEMU під час коротких сплесків.
- Якщо ваше сховище повільне: тримайте swap меншим і віддавайте пріоритет правильному розміруванню RAM. Свап на повільних HDD — це не «стабільність», а «тривале страждання».
- Якщо ви використовуєте SSD/NVMe: swap значно більш терпимий, але все одно не безкоштовний. Моніторте швидкість swap-in/out, а не тільки використання swap.
Жарт №2: Swap — це як зустріч, яка могла бути листом — іноді рятує день, але якщо ви там живете, ваша кар’єра закінчена.
Практичні завдання: команди, виводи та рішення (12+)
Ось перевірки, які я реально запускаю, коли вузол Proxmox починає кидати помилки алокації пам’яті. Кожне завдання містить:
команду, приклад виводу, що це означає і яке рішення воно визначає.
Завдання 1: Перевірити RAM і swap хоста на око
cr0x@server:~$ free -h
total used free shared buff/cache available
Mem: 62Gi 54Gi 1.2Gi 2.3Gi 6.9Gi 2.8Gi
Swap: 8Gi 1.6Gi 6.4Gi
Значення: «available» — ваш ближній запас перед тим, як звільнення стане некрасивим. 2.8 ГіБ на хості 62 ГіБ
з віртуалізацією — тісно, але не миттєво катастрофічно.
Рішення: Якщо available < 1–2 ГіБ і ВМ не стартують, зупиніть некритичні ВМ. Якщо swap = 0, додайте swap як стабілізатор, поки виправляєте розміри.
Завдання 2: Визначити, чи ядро відхиляє алокації через CommitLimit
cr0x@server:~$ grep -E 'CommitLimit|Committed_AS' /proc/meminfo
CommitLimit: 71303168 kB
Committed_AS: 70598240 kB
Значення: Ви близькі до стелі коміту. Ядро може відмовляти новим резервуванням пам’яті навіть якщо є кеш, який можна звільнити.
Рішення: Зменшити max-пам’ять ВМ, додати swap (збільшує CommitLimit) або перемістити навантаження.
Зміна цілей балона не допоможе, якщо проблема в max.
Завдання 3: Підтвердити політику overcommit
cr0x@server:~$ sysctl vm.overcommit_memory vm.overcommit_ratio
vm.overcommit_memory = 0
vm.overcommit_ratio = 50
Значення: Режим 0 — евристичне перевиділення. Ratio важливий здебільшого для режиму 2. Все одно, поведінка коміту в дії.
Рішення: Не міняйте ці налаштування в паніці, якщо не розумієте наслідків. Якщо ви досягаєте ліміту коміту,
краще виправити розміри, ніж «просто сильніше перевиділити».
Завдання 4: Шукати докази роботи OOM killer на хості
cr0x@server:~$ journalctl -k -b | tail -n 30
Dec 26 10:14:03 pve1 kernel: Out of memory: Killed process 21433 (qemu-system-x86) total-vm:28751400kB, anon-rss:23110248kB, file-rss:0kB, shmem-rss:0kB
Dec 26 10:14:03 pve1 kernel: oom_reaper: reaped process 21433 (qemu-system-x86), now anon-rss:0kB, file-rss:0kB, shmem-rss:0kB
Значення: Хост вбив QEMU. Та ВМ не «поїхала», її виконали.
Рішення: Розглядайте як виснаження пам’яті хоста/перевиділення. Зменшіть консолідацію, обмежте ARC, додайте swap
і не покладайтеся на балонінг як ремінь безпеки.
Завдання 5: Перевірити тиск пам’яті та поведінку звільнення в реальному часі
cr0x@server:~$ vmstat 1 5
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
r b swpd free buff cache si so bi bo in cs us sy id wa st
6 1 1677720 312000 8200 5120000 40 120 180 260 900 1800 18 12 55 15 0
5 2 1677800 280000 8100 5010000 10 200 140 320 920 1700 15 10 50 25 0
7 3 1677850 260000 8000 4920000 80 500 220 600 1100 2200 20 15 35 30 0
Значення: Ненульові si/so вказують на свапінг. Високий wa — IO wait.
Якщо b росте, а id падає, хост трясеться (thrashing).
Рішення: Якщо свапінг тривалий і IO wait підіймається, зупиніть ВМ або перемістіть навантаження.
Ви не зможете «відтюнити» себе з бурі thrash у реальному часі.
Завдання 6: Знайти найбільших споживачів пам’яті на хості (RSS, не VIRT-мрії)
cr0x@server:~$ ps -eo pid,comm,rss,vsz --sort=-rss | head -n 10
21433 qemu-system-x86 23110248 28751400
19877 qemu-system-x86 16188012 21045740
1652 pveproxy 312400 824000
1321 pvedaemon 210880 693000
1799 zfs 180200 0
1544 pvestatd 122000 610000
Значення: RSS — це реальна резидентна пам’ять. QEMU-процеси домінують, як і очікувалось.
Рішення: Якщо одна ВМ розженена, обмежте її max-пам’ять або розслідуйте всередині гостя.
Якщо «багато середніх» ВМ навантажують — це математика консолідації, а не один негідник.
Завдання 7: Подивитись конфіг ВМ (балон vs max)
cr0x@server:~$ qm config 104 | egrep 'memory|balloon|numa|hugepages'
memory: 32768
balloon: 8192
numa: 1
hugepages: 2
Значення: Max — 32 ГіБ, ціль балона 8 ГіБ. Hugepages увімкнено (2 = 2MB hugepages).
Рішення: Якщо вузол не вдається виділити пам’ять, max цієї ВМ у 32 ГіБ може бути надто щедрим.
Якщо hugepages увімкнено, підтвердіть їх наявність (Завдання 8) або вимкніть для гнучкості.
Завдання 8: Перевірити наявність hugepages (класична причина помилок старту)
cr0x@server:~$ grep -i huge /proc/meminfo
AnonHugePages: 1048576 kB
HugePages_Total: 8192
HugePages_Free: 120
HugePages_Rsvd: 50
Hugepagesize: 2048 kB
Значення: Вільних лише 120 hugepages (~240 МіБ). Якщо ви спробуєте стартувати ВМ, що потребує багато hugepages, вона впаде.
Рішення: Або забезпечте достатньо hugepages при завантаженні, або припиніть використовувати hugepages для цього класу ВМ.
Hugepages — інструмент продуктивності, а не налаштування за замовчуванням.
Завдання 9: Перевірити поведінку THP (може викликати латентність при тиску)
cr0x@server:~$ cat /sys/kernel/mm/transparent_hugepage/enabled
[always] madvise never
Значення: THP увімкнено завжди.
Рішення: Для вузлів, чутливих до латентності, розгляньте madvise або never.
Не змінюйте це під час інциденту, якщо ви не впевнені; плануйте в maintenance-вікні і вимірюйте.
Завдання 10: Якщо використовуєте ZFS — швидко перевірити розмір ARC
cr0x@server:~$ awk '/^size/ {print}' /proc/spl/kstat/zfs/arcstats
size 4 34359738368
Значення: ARC ≈ 32 ГіБ. На хості 64 ГіБ з багатьма ВМ це може бути забагато.
Рішення: Якщо вам не вистачає пам’яті і ARC великий, обмежте ARC постійно (див. розділ контрольного списку)
і заплануйте перезавантаження для негайного полегшення.
Завдання 11: Підтвердити статус KSM (допомагає при багатьох схожих ВМ, але коштує CPU)
cr0x@server:~$ systemctl is-active ksmtuned
inactive
Значення: Сервіс налаштування KSM не працює. На деяких Proxmox-настройках KSM налаштовано інакше;
це швидкий індикатор.
Рішення: Якщо ви запускаєте десятки схожих Linux-ВМ, увімкнення KSM може зменшити використання пам’яті.
Якщо CPU вже гарячий, KSM може зашкодити. Тестуйте на одному вузлі спочатку.
Завдання 12: Перевірити інформацію про пам’ять вузла в Proxmox (що Proxmox думає)
cr0x@server:~$ pvesh get /nodes/pve1/status | egrep '"memory"|"swap"|"loadavg"'
"loadavg": [
"2.61",
"2.45",
"2.31"
],
"memory": {
"free": 1288490188,
"total": 66571993088,
"used": 651834
},
"swap": {
"free": 6871947673,
"total": 8589934592,
"used": 1717986919
}
Значення: API Proxmox дає вигляд, який може відрізнятися від ваших очікувань (одиниці, кешування, час).
Не вважайте його абсолютною істинною; перевіряйте free і meminfo.
Рішення: Використовуйте це для автоматики та дашбордів, але при налагодженні відмов алокації довіряйте доказам ядра і логам QEMU перш за все.
Завдання 13: Проаналізувати помилку старту ВМ у логах завдань
cr0x@server:~$ journalctl -u pvedaemon -b | tail -n 20
Dec 26 10:18:11 pve1 pvedaemon[1321]: start VM 104: UPID:pve1:0000A3F9:00B2B6D1:676D5A13:qmstart:104:root@pam:
Dec 26 10:18:12 pve1 pvedaemon[1321]: VM 104 qmp command failed - unable to execute QMP command 'cont': Cannot allocate memory
Dec 26 10:18:12 pve1 pvedaemon[1321]: start failed: command '/usr/bin/kvm -id 104 ...' failed: exit code 1
Значення: Помилка відбувається на стадії старту/cont QEMU, не всередині гостя.
Рішення: Сфокусуйтеся на лімітах коміту хоста, hugepages і фрагментації — не на тонкому тюнінгу гостя.
Завдання 14: Перевірити конфіг контейнера (LXC) та ліміт swap
cr0x@server:~$ pct config 210 | egrep 'memory|swap|features'
memory: 4096
swap: 512
features: nesting=1,keyctl=1
Значення: Контейнер має 4 ГіБ RAM і 512 МіБ swap. Якщо він стрибне вище, алокації всередині контейнера проваляться.
Рішення: Для контейнерів «неможливо виділити пам’ять» часто означає досягнення ліміту cgroup.
Збільшуйте memory/swap або виправляйте поведінку додатка. Вільна RAM хоста не врятує LXC з жорсткою межею.
Завдання 15: Перевірити сигнали ризику фрагментації (швидко і грубо)
cr0x@server:~$ cat /proc/buddyinfo | head
Node 0, zone DMA 1 1 1 1 0 0 0 0 0 0 0
Node 0, zone DMA32 1024 512 220 12 0 0 0 0 0 0 0
Node 0, zone Normal 2048 1880 940 110 2 0 0 0 0 0 0
Значення: Buddy allocator показує, скільки вільних блоків є в різних порядках. Якщо вищі порядки майже нуль,
великі суміжні виділення (включно з потребами hugepage) можуть провалюватись навіть при «достатній загальній вільній пам’яті».
Рішення: Якщо hugepages/THP і компактування важливі для вашої конфігурації, розгляньте зменшення залежності від суміжних виділень
або плануйте періодичні обслуговування/перезавантаження для вузлів, які мають задовольняти такі виділення.
Три корпоративні короткі історії з поля бою
Інцидент: хибне припущення («балонінг означає, що max не резервується»)
Середня компанія тримала внутрішній Proxmox-кластер для бізнесових додатків і кількох важких пакетних задач.
Команда мала звичку: ставити високу max-пам’ять ВМ «щоб ніхто не писав тикет», а ціль балона — низьку,
щоб «підтримувати ефективність».
Це працювало — поки вони не оновили декілька ВМ і не запустили квартальний звіт. Нові процеси породилися, карти пам’яті
розширилися, і кілька ВМ перезапустилися для патчів. Раптом: «неможливо виділити пам’ять» при старті ВМ.
Дашборд усе ще показував «вільно», бо кеш здався відновлюваним.
Корінь проблеми — не витік. Це був облік. Committed_AS хоста повільно підбирався до CommitLimit.
Кожна ВМ з щедрим max додавала до суми «пообіцяної» пам’яті, навіть якщо «зазвичай» сиділа на низькому рівні. Коли декілька
рестартів відбулися одночасно, QEMU спробував зарезервувати те, що йому казали, що може знадобитись. Ядро відмовило.
Помилка була правдивою; їхня ментальна модель — ні.
Виправлення було нудним: вони зменшили max-пам’ять ВМ до обґрунтованих значень, зберегли балонінг для еластичності
і додали swap на хости, де його не було. Найголовніше — вони перестали ставитись до «max» як до бажання.
Наступний квартальний прогін ще підскакував, але перестав ламати рестарти.
Оптимізація, що відпалила (hugepages усюди)
Інша організація гналася за затримкою. Інженер з продуктивності увімкнув hugepages для цілого класу ВМ, бо блог казав,
що це покращить TLB-поведінку. І справді може. Вони також залишили Transparent Huge Pages у положенні «always»,
бо більше hugepages звучало як більше продуктивності. Так оптимізм перетворився на конфігурацію.
Тижнями все виглядало нормально. Потім один вузол почав падати при старті ВМ після рутинних міграцій. Та сама ВМ на інших вузлах стартувала.
На цьому вузлі: «неможливо виділити пам’ять». Вільної пам’яті не було катастрофічно мало, але free hugepages майже не було.
Buddyinfo показав фрагментацію: пам’ять була, але не в потрібних шматках.
Вони спробували «виправити» це динамічним збільшенням hugepages. Стало гірше: ядру довелося компактувати пам’ять, щоб задовольнити запит,
підвищився CPU і процес звільнення затримався. Латентність вийшла вбік під час піку. Найкращою частиною був звіт про інцидент, який назвали «періодичним».
Це було «періодично», як гравітація — вона теж лише іноді відчувається, коли ви впадете.
План відновлення: вимкнути hugepages для загальних ВМ, резервувати hugepages лише для невеликого набору критичних випадків із передбачуваним розміром,
і встановити THP в madvise. Загальна продуктивність покращилася, бо система припинила битися сама з собою.
Скучно, але вірно: резерв хоста і ліміти врятували ситуацію
Третя команда тримала Proxmox для змішаних навантажень: веб-додатки, кілька Windows-ВМ і пара сховищних appliance.
У них була нудна правило: кожен вузол тримає фіксований «резерв хоста» RAM, який ніколи не виділяється гостям офіційно.
Вони також обмежили ZFS ARC з першого дня.
Це не було красиво. Це означало, що вони могли запускати менше ВМ на вузол, ніж хотіли фанатики таблиць.
Але під час інциденту, коли шумна ВМ раптово почала споживати пам’ять (невірно налаштований Java-сервіс), хост мав достатньо запасу,
щоб тримати процеси QEMU живими і уникнути OOM хоста.
Гість все одно постраждав (як і має бути), але зона ураження залишилася всередині тієї ВМ. Кластер не почав вбивати сторонні навантаження.
Вони злили вузол, виправили конфіг гістьової, і відновили роботу. Ніяких північних перезавантажень, ніяких каскадних відмов, ніяких «чому впала наш фаєрвол-ВМ?»
Практика, що врятувала їх, не була секретним тюнінгом ядра. Це було бюджетування і відмова витрачати аварійний фонд.
Типові помилки: симптом → причина → виправлення
ВМ не стартує: «Неможливо виділити пам’ять» відразу
- Симптом: Старт падає миттєво; QEMU виходить з помилкою алокації.
- Причина: Досягнутий CommitLimit хоста, відсутні hugepages або фрагментація пам’яті для запитаного виділення.
- Виправлення: Зменшити max-пам’ять ВМ; додати swap на хості; вимкнути hugepages для цієї ВМ; забезпечити hugepages при завантаженні, якщо вони потрібні.
ВМ стартує, а потім раптово вимикається або скидається
- Симптом: ВМ ніби «крушиться», в логах немає чистого завершення.
- Причина: OOM killer хоста вбив QEMU, часто після стрибка пам’яті або важкого reclaim.
- Виправлення: Знайти OOM-логи; зменшити перевиділення хоста; резервувати пам’ять хоста; обмежити ZFS ARC; переконатися, що swap існує і моніторити його активність.
Гості спочатку повільні, потім хост повільнішає, потім всі починають філософствувати
- Симптом: IO wait піднімається; швидкості swap-in/out зростають; латентність ВМ підскакує.
- Причина: Thrashing: недостатньо RAM для робочих наборів, і свап/reclaim домінує.
- Виправлення: Зупинити або мігрувати ВМ; зменшити ліміти пам’яті; додати RAM; переглянути план консолідації. Жоден sysctl вас тут не врятує.
Балонінг увімкнено, але пам’ять ніколи не «повертається»
- Симптом: Хост залишається заповненим; гості не звільняють пам’ять, як очікувалось.
- Причина: Драйвер балона не встановлено/не працює, гість не може звільнити пам’ять, або «max» все ще зобов’язує хост.
- Виправлення: Встановити драйвер virtio-balloon; перевірити всередині гостя; встановити реалістичний max; використовувати балонінг для еластичності, а не як заміну розміру.
Все було гаразд, поки не збільшилися ZFS snapshots і реплікація
- Симптом: Тиск пам’яті хоста зростає під час інтенсивної роботи зі сховищем; старти ВМ падають.
- Причина: Зростання ARC, тиск метаданих, нарощування slab і IO-керована пам’ять.
- Виправлення: Обмежити ARC; моніторити slab; тримати запас; уникати роботи вузла на 95% «використано» і називати це ефективністю.
Контейнери показують «неможливо виділити пам’ять», хоча хост має запас
- Симптом: Додатки в LXC не можуть виділити пам’ять; хост виглядає нормально.
- Причина: Досягнутий ліміт пам’яті cgroup (memory/swap контейнера).
- Виправлення: Підвищити ліміти контейнера; налаштувати додаток; дозволити swap контейнера, якщо ви очікуєте сплесків.
Контрольні списки / покроковий план
Покроково: виправити вузол, який кидає помилки алокації
-
Підтвердити OOM хоста проти помилки при старті.
Перевіртеjournalctl -kна OOM-вбивства і логиpvedaemonдля контексту помилки старту. -
Виміряти тиск коміту.
ЯкщоCommitted_ASблизький доCommitLimit, ви в території «обіцянки перевищують реальність». -
Перелічити ВМ з великим max-пам’яттю.
Зменшіть max-пам’ять для винних. Не обмежуйтеся зміною лише цілей балона. -
Перевірити hugepages і налаштування THP.
Якщо hugepages увімкнено для ВМ, переконайтеся в достатній препризначеності або вимкніть для загальних навантажень. -
Перевірити ZFS ARC, якщо це стосується.
Якщо ARC великий і ви хост для ВМ перш за все, обмежте його. -
Переконатися, що swap існує і він адекватний.
Додайте swap, якщо його нема; монітортеsi/so. Swap — для сплесків, а не для щоденної оренди. -
Резервувати пам’ять хоста.
Тримайте фіксований буфер для ядра + ZFS + оверхед QEMU. Ваше майбутнє «я» дякуватиме мовчки. -
Повторно тестуйте запуск ВМ у контрольованій послідовності.
Не запускайте все одразу після налаштувань. Стартуйте критичні служби першими.
Постійне налаштування: обмеження ZFS ARC (приклад)
Якщо вузол — це хост ВМ і ZFS — лише засіб, встановіть максимум ARC. Один поширений метод:
створити конфіг modprobe і оновити initramfs, щоб застосувати при завантаженні.
cr0x@server:~$ echo "options zfs zfs_arc_max=17179869184" | sudo tee /etc/modprobe.d/zfs.conf
options zfs zfs_arc_max=17179869184
cr0x@server:~$ sudo update-initramfs -u
update-initramfs: Generating /boot/initrd.img-6.8.12-4-pve
Значення: ARC обмежено до 16 ГіБ (значення в байтах). Ви сказали ZFS не їсти всю машину.
Рішення: Виберіть обмеження, що залишає достатньо RAM для гостей плюс резерв хоста. Підтвердіть після перезавантаження, читаючи arcstats.
Постійне налаштування: додати swap на хості (приклад файлу)
cr0x@server:~$ sudo fallocate -l 8G /swapfile
cr0x@server:~$ sudo chmod 600 /swapfile
cr0x@server:~$ sudo mkswap /swapfile
Setting up swapspace version 1, size = 8 GiB (8589930496 bytes)
no label, UUID=0a3b1e4c-2f1e-4f65-a3da-b8c6e3f3a8d7
cr0x@server:~$ sudo swapon /swapfile
cr0x@server:~$ swapon --show
NAME TYPE SIZE USED PRIO
/swapfile file 8G 0B -2
Значення: Swap активний. CommitLimit зростає, і у вас є буфер проти раптових сплесків алокацій.
Рішення: Якщо використання swap стає постійним разом з високими si/so, це не «працює як задумано».
Це сигнал зменшити консолідацію або додати RAM.
Політика: резервувати RAM для хоста (проста і дієва практика)
-
Резервуйте принаймні 10–20% RAM хоста для хоста на змішаних вузлах.
Більше — якщо ви запускаєте ZFS, Ceph, потужні мережі або багато малих ВМ. -
Тримайте «цільову суму max ВМ», яку можете відстояти. Якщо сума max ВМ перевищує заданий коефіцієнт від RAM хоста,
робіть це свідомо й лише там, де поведінка навантаження це підтримує.
Контрольний список для балонінгу (використовуйте його правильно)
Поширені питання
1) Чому Proxmox каже «неможливо виділити пам’ять», коли free показує ГБ вільних?
Тому що free показує знімок фізичної пам’яті, тоді як облік коміту ядра і правила фрагментації можуть відмовити новій алокації.
Також «free» ігнорує, чи доступна пам’ять у потрібній формі (наприклад, hugepages).
2) Чи зменшує балонінг те, що хост повинен резервувати?
Він зменшує те, що гість використовує під час виконання, але якщо у вашої ВМ високий max, хост все одно може бути зобов’язаний за обіцянкою.
Балонінг не звільняє від відповідальності правильно розмірювати.
3) Чи варто ставити vm.overcommit_memory=1, щоб зупинити відмови алокацій?
Це грубий інструмент. Він може зменшити відмови при старті, але підвищує ризик катастрофічного OOM пізніше.
У продакшені краще виправити розмір ВМ і додати swap, ніж послаблювати захисні механізми ядра.
4) Скільки swap має бути на хості Proxmox?
Достатньо, щоб пережити сплески і підвищити CommitLimit, але не настільки, щоб приховати хронічне перевиділення.
Зазвичай: кілька ГБ до низьких десятків ГБ залежно від RAM хоста і волатильності навантаження. Міряйте активність swap; якщо вона постійна, ви недорозміровані.
5) Чи є ZFS ARC причиною, чому мій вузол «залипає без пам’яті»?
Іноді. ARC може рости і конкурувати з ВМ. Якщо старти ВМ провалюються або хост OOM, коли ARC великий,
обмежте ARC. Якщо ARC невеликий, дивіться інші причини (комітліміт, hugepages, розгінні ВМ).
6) Чи варто увімкнути KSM на Proxmox?
Якщо ви запускаєте багато схожих ВМ (той самий ОС, схожі сторінки пам’яті), KSM може зекономити RAM.
Це коштує CPU і може додати латентності. Увімкніть свідомо, вимірюйте вплив на CPU і не вважайте це безкоштовною пам’яттю.
7) Чому контейнери б’ються «неможливо виділити пам’ять», якщо хост в порядку?
LXC керується cgroups. Контейнер може досягти ліміту всередині свого простору, навіть якщо хост має запас.
Підніміть ліміти pct memory/swap або виправте навантаження контейнера.
8) Чи варті hugepages того?
Для певних високопродуктивних, чутливих до латентності навантажень — так. Для загальної консолідації — часто ні.
Hugepages підвищують передбачуваність TLB, але знижують гнучкість і можуть створювати проблеми запуску, якщо їх не забезпечити.
9) У чому різниця між гостевим OOM і OOM хоста?
Гостевий OOM відбувається всередині ВМ: гостьове ядро вбиває процеси, але ВМ залишається запущеною. OOM хоста вбиває процеси
на гіпервізорі, включно з QEMU — ваша ВМ зникає. OOM хоста псує вам день.
10) Чи можна «постійно вирішити» це без додавання RAM?
Часто так: встановіть реалістичні max-пам’яті ВМ, резервуйте RAM для хоста, обмежте ARC за потреби і уникайте фантастичних співвідношень перевиділення.
Якщо робочі набори реально перевищують фізичну RAM, постійне рішення — більше RAM або менше навантажень на вузол.
Наступні кроки (розумні)
«Неможливо виділити пам’ять» в Proxmox — не прокляття. Це ядро, яке відстоює межу, яку ви вже перейшли в політиці, конфігурації або очікуваннях.
- Припиніть ставитись до max-пам’яті ВМ як до пропозиції. Зробіть її контрактом.
- Використовуйте балонінг для еластичності, а не як заперечення. Ціль — низька, стеля — реалістична.
- Дайте хосту аварійний фонд. Резервуйте RAM; додайте swap; тримайте ZFS ARC у своїй смузі.
- Віддавайте перевагу передбачуваним вузлам над героїчним тюнінгом. Розділяйте навантаження, коли їх режими відмов різняться.
- Опрацюйте це як процес. Додайте алерти на близькість до CommitLimit, швидкість swap-in/out, OOM-логи і розмір ARC.
Зробіть це — і наступного разу, коли Proxmox пожалкує про пам’ять, це буде тому, що ви дійсно використали все, а не тому що ваша
конфігурація розповіла чарівну історію, якій ядро відмовилось вірити.