Ballooning памяти: как гипервизор забирает RAM обратно
Вы выделили каждой VM на хосте фиксированный объём RAM «с запасом», но большую часть времени половина этой памяти простаивает без дела — а в момент пиковой нагрузки на соседней машине физической памяти не хватает, и гипервизор либо уходит в своп, либо просто не даёт машине вырасти. Memory ballooning — это механизм, которым гипервизор может забрать неиспользуемую память у одной работающей VM и отдать её другой, испытывающей нехватку, не останавливая и не перезагружая ни одну из них. Разберём, как это устроено изнутри, где у механизма реальные пределы и когда он реально помогает, а когда создаёт иллюзию свободной памяти там, где её физически нет.
Содержание
Что такое ballooning памяти и зачем он нужен
В классической схеме гипервизор либо жёстко резервирует RAM за каждой VM (memory reservation), либо честно перераспределяет физическую память между машинами на лету. Первый вариант надёжен, но неэффективен: если VM использует 2 ГБ из выделенных 8 ГБ, оставшиеся 6 ГБ просто простаивают — их нельзя отдать соседу, потому что гипервизор не знает, сколько памяти гостевая ОС реально использует прямо сейчас, а не выделила «про запас».
Ballooning решает именно эту проблему видимости. Это не отдельный самостоятельный механизм оверкоммита, а надстройка поверх него — способ гипервизора спросить у гостевой ОС «отдай мне то, что тебе сейчас не нужно» и получить честный ответ, потому что запрос идёт не снаружи (гипервизор не может заглянуть в таблицы страниц гостя и понять, какие страницы «горячие», а какие — просто выделенный, но неиспользуемый кеш), а изнутри, силами самой гостевой ОС через её штатный менеджер памяти.
Смысл в том, что решение «что можно освободить» принимает не гипервизор, а сама гостевая ОС — точно так же, как она освобождает страницы под любой другой процесс, которому вдруг понадобилась память. Гипервизор просто убеждает гостя, что у него появился ещё один «прожорливый процесс» — сам balloon-драйвер.
Применяется механизм в KVM/QEMU (virtio-balloon), VMware ESXi (vmmemctl / VMware Tools balloon driver), Xen (Xen balloon driver) и Hyper-V (Dynamic Memory). Логика везде одна и та же, различаются детали протокола и то, насколько агрессивно каждый гипервизор им пользуется по умолчанию.
Balloon-драйвер внутри гостевой ОС: как это устроено
Ключевое условие работы ballooning — внутри гостевой VM должен быть установлен и запущен специальный драйвер, обычно поставляемый в составе пакета гостевых дополнений:
- в Linux-гостях под KVM/QEMU — модуль ядра
virtio_balloon, обычно собран как часть ядра или подгружается автоматически при наличии соответствующего virtio-устройства; - в Windows-гостях под Hyper-V — компонент Dynamic Memory в составе Hyper-V Integration Services;
- под VMware — драйвер
vmmemctl(в современных версиях также известен какvmware-balloon), устанавливается вместе с open-vm-tools или VMware Tools; - под Xen — модуль
xen-balloon.
Без этого драйвера ballooning не работает вообще — гипервизор физически не может «попросить» память у гостя, у которого нет посредника, способного этот запрос понять и исполнить. Если вы разворачиваете минимальный образ Linux вручную и выключаете гостевые агенты «для производительности», вы заодно отключаете и ballooning — это стоит иметь в виду при проектировании плотных сред.
Проверить, что драйвер загружен, в Linux-госте под KVM можно так:
lsmod | grep virtio_balloon
dmesg | grep -i balloon
cat /proc/interrupts | grep -i balloon
Если драйвер присутствует, в системе также появляется управляющее устройство, через которое гипервизор передаёт целевой размер балуна и получает статистику:
ls /sys/bus/virtio/devices/ | xargs -I{} sh -c 'cat /sys/bus/virtio/devices/{}/status 2>/dev/null'
Драйвер работает как обычный клиент менеджера памяти ядра: он запрашивает у ядра страницы физической памяти (через стандартный аллокатор, как это делает любое приложение), помечает их «занятыми под себя» и сообщает их адреса гипервизору. С точки зрения гостевой ОС это выглядит ровно как если бы в системе запустился процесс и «съел» N мегабайт RAM — обычная конкуренция за память, ничего специфичного для виртуализации гостевая ОС не видит.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверКак гипервизор «надувает» и «сдувает» балун
Сам термин «balloon» — это именно образ надувного шарика внутри VM, который можно надувать и сдувать по команде снаружи.
Надувание (inflate). Гипервизор решает, что VM A может отдать часть памяти. Он передаёт balloon-драйверу внутри VM A целевой размер балуна — скажем, «займи 1 ГБ». Драйвер запрашивает у гостевого ядра нужное число страниц через обычный механизм выделения памяти. Гостевая ОС на этом этапе ведёт себя как обычно при нехватке памяти: она сначала отдаёт «дешёвые» страницы — файловый кеш, буферы, неиспользуемые страницы приложений, — и только если этого не хватает, начинает давить на активные процессы. Как только страницы гостю выделены и их физические адреса переданы гипервизору, гипервизор помечает соответствующие хостовые физические страницы как свободные — с точки зрения гипервизора это настоящая, реально доступная физическая память, которую драйвер внутри гостя «держит», но не использует.
Перераспределение. Освободившуюся физическую память гипервизор отдаёт VM B, которой она нужна прямо сейчас — например, увеличивает её резидентный набор страниц или использует для нового процесса на этой VM.
Сдувание (deflate). Когда VM A снова начинает нуждаться в памяти (её собственные процессы запрашивают больше RAM, а гостевая ОС видит, что балун — крупный «якобы занятый» блок, который можно вернуть), гипервизор уменьшает целевой размер балуна. Драйвер освобождает захваченные страницы обратно гостевому ядру обычным вызовом free(), и гостевая ОС снова может использовать эту память как обычно.
Важный нюанс: гипервизор не может *заставить* гостя мгновенно отдать память — команда носит форму «пожалуйста, доведи размер балуна до X», а гостевая ОС выполняет её в своём собственном темпе через свой обычный аллокатор. Это одновременно и сильная сторона механизма (гость сохраняет консистентность и не ломается от резкого исчезновения памяти), и источник задержки — надувание балуна не мгновенно, особенно если гостю приходится сначала вытолкнуть много «грязных» страниц кеша на диск.
В Proxmox VE (QEMU/KVM) посмотреть текущее состояние балуна конкретной VM можно через монитор QEMU:
qm monitor 101
(qemu) info balloon
а изменить целевой размер — командой balloon в том же мониторе или через qm set:
qm set 101 --balloon 2048
где значение — целевой объём RAM в мегабайтах, до которого гипервизор пытается «сдуть» или «надуть» балун этой VM.
Ballooning vs оверкоммит памяти: в чём разница
Это два разных, но тесно связанных понятия, и их легко перепутать.
| Оверкоммит памяти | Ballooning | |
|---|---|---|
| Что это | Стратегия: сумма выделенной VM памяти превышает физическую RAM хоста | Конкретный механизм динамического перераспределения памяти между VM |
| Кто решает | Администратор при планировании (сколько VM разместить на хосте) | Гипервизор в реальном времени, на основе текущей нагрузки |
| Требует драйвер в госте | Нет — работает и без него (KSM, page cache, своп) | Да, обязательно |
| Что происходит при нехватке | Хост может уйти в своп или использовать KSM (Kernel Samepage Merging) | Гипервизор просит одну VM вернуть неиспользуемую память для другой |
| Риск | Если не хватает даже с учётом дедупликации — деградация всех VM сразу | Если гостю самому нечего отдать — балун не растёт, ballooning бессилен |
Подробно про пределы оверкоммита, как его планировать и где проходит грань разумного мы разбирали в статье «Оверкоммит CPU и памяти: где предел» — рекомендуем прочитать её как базу, если вы ещё не знакомы с темой, потому что ballooning без понимания оверкоммита выглядит как магия, а на деле — это просто более умный способ его реализовать.
Разница на практике: оверкоммит — это архитектурное решение «сколько VM я размещаю на этом железе», а ballooning — тактический инструмент, которым гипервизор сглаживает временные всплески внутри уже принятого решения об оверкоммите. Ballooning не увеличивает суммарный объём доступной физической памяти на хосте ни на байт — он лишь помогает эффективнее распределить то, что физически есть, между VM, чья потребность в моменте разная.
Когда ballooning не работает и чем это грозит
Здесь начинается самая важная для практики часть — честные ограничения.
1. Ballooning не может создать память из ничего. Если гостевая VM реально активно использует весь выделенный ей объём RAM — под базу данных, кеш приложения, JVM-хип — гипервизору попросту нечего забирать. Balloon-драйвер запросит у гостевого ядра страницы, а гостевое ядро, у которого нет свободного кеша и незанятых буферов, начнёт вытеснять страницы активных процессов в своп (если своп есть) или откажет в выделении (если своп исчерпан или отключён). В первом случае вы получите деградацию производительности именно той VM, у которой пытались «незаметно» забрать память — процессы внутри неё начнут страдать от свопинга, хотя администратор снаружи видел лишь «балун вырос, всё штатно». Мы подробно разбирали, почему своп внутри VM — это почти всегда симптом, а не решение, в статье «Антипаттерн: своп вместо памяти».
2. Требуется установленный и запущенный balloon-драйвер. Без гостевых дополнений (open-vm-tools, qemu-guest-agent с соответствующим virtio-устройством, Hyper-V Integration Services) механизм не работает вообще — гипервизор просто не может связаться с гостем. Это особенно важно для минимальных или кастомных образов, container-ориентированных дистрибутивов (например, урезанных Alpine-сборок без нужных модулей ядра) и legacy-систем, куда гостевые дополнения никогда не устанавливались.
3. Слишком агрессивная политика ballooning вредна сама по себе. Некоторые гипервизоры позволяют настраивать, насколько сильно давить на VM балуном (в Proxmox это разница между balloon и memory в конфиге VM). Если задать минимальный balloon слишком низким относительно реальных потребностей приложения внутри VM, гипервизор будет держать эту VM «на голодном пайке» постоянно, а не только в моменты пиковой нагрузки соседей — в таком случае у вас не временное сглаживание, а хронический недостаток памяти, замаскированный под нормальную работу.
4. Ballooning не отличает «горячие» страницы от «холодных» так же точно, как это делает гостевая ОС при родном управлении памятью. Гость освобождает то, что считает наименее ценным по своим внутренним эвристикам (обычно LRU-подобные алгоритмы для файлового кеша), но это оценка гостя, а не привилегированное знание гипервизора о будущей нагрузке. Если нагрузка резко меняется сразу после того, как гость «щедро» отдал кеш, восстановление балуна назад занимает время — гость должен заново запросить и получить страницы, а это уже не мгновенная операция.
5. Ballooning плохо сочетается с приложениями, которые сами агрессивно резервируют и блокируют память (например, база данных с mlock, JVM с зафиксированным хипом без возможности его уменьшить на лету, некоторые СУБД с shared_buffers, зафиксированными при старте). Такие процессы просто не отдадут страницы balloon-драйверу, потому что гостевое ядро не может их вытеснить — в результате баллон для этой VM практически не растёт, что бы ни просил гипервизор.
Как настроить и проверить ballooning на практике
Proxmox VE / QEMU-KVM. В настройках VM указываются два параметра: memory (максимум, до которого может расти VM) и balloon (минимум, ниже которого гипервизор не станет давить через балун). Если balloon меньше memory, ballooning активен; если равен memory — фактически выключен, VM всегда держит фиксированный объём.
# посмотреть текущую конфигурацию VM
qm config 101 | grep -E 'memory|balloon'
# включить ballooning: максимум 8192 МБ, минимум гарантированный 4096 МБ
qm set 101 --memory 8192 --balloon 4096
Убедиться, что балун реально работает и видеть его текущий размер:
qm monitor 101
(qemu) info balloon
Внутри Linux-гостя проверить нагрузку на память, чтобы понять, есть ли гостю что отдавать:
free -h
cat /proc/meminfo | grep -E 'MemFree|Cached|SwapFree'
Если MemFree и Cached малы, а SwapFree начинает падать после включения ballooning — это верный признак того, что гостю нечего было отдавать, и балун вытесняет активные данные в своп. В такой ситуации правильная реакция — уменьшить агрессивность балуна для этой VM (поднять balloon) или добавить физическую RAM на хост, а не пытаться «дожать» механизм дальше.
VMware ESXi. Аналогичная логика через параметры Reservation / Limit / Shares в настройках памяти VM. Проверить статистику балуна изнутри гостя (при установленных VMware Tools):
vmware-toolbox-cmd stat balloon
Общая рекомендация по мониторингу: если вы управляете несколькими VM на одном хосте, стоит регулярно смотреть не только на текущее потребление RAM каждой VM, но и на историю размера балуна — резкие скачки говорят о конкуренции за память между соседями, а стабильно раздутый балун на одной конкретной VM — сигнал, что её реальным нуждам эта VM тесна. Мы касались смежной темы — что происходит с памятью VM во время живой миграции (ballooning часто применяется гипервизором и в этом сценарии тоже) — в статье «Живая миграция виртуалок: что с памятью».
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверНужны сами нейросети для контента?
Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.
Частые вопросы
Ballooning приводит к потере данных внутри VM?
Нет, при штатной работе — гостевая ОС отдаёт только страницы, которые сама считает безопасным освободить (кеш, буферы), точно так же, как отдала бы их любому другому процессу. Данные приложений при этом не теряются, если только гость не уходит в своп настолько глубоко, что начинает сбоить сам (это уже отдельная, более серьёзная проблема нехватки ресурсов, а не следствие самого ballooning).
Можно ли увидеть, сколько памяти сейчас реально «отобрано» балуном?
Да — через qm monitor → info balloon в Proxmox/QEMU, через vmware-toolbox-cmd stat balloon в VMware, либо изнутри гостя по разнице между выделенным гипервизором объёмом и тем, что показывает free -h.
Ballooning работает для Windows-гостей так же, как для Linux?
Да, принцип идентичен, но реализация — через Hyper-V Dynamic Memory или соответствующий балун-драйвер в составе гостевых дополнений VMware/QEMU; без установленных Integration Services/Tools на Windows-госте ballooning так же не работает, как и на Linux без virtio_balloon.
Ballooning — это то же самое, что и thin provisioning диска?
Нет, это разные механизмы про разные ресурсы: thin provisioning — про то, как выделяется место на диске, ballooning — про оперативную память. Общая идея «выделять по факту использования, а не заранее» похожая, но реализация и риски разные.
Что произойдёт, если резко выключить balloon-драйвер (остановить гостевой агент) при раздутом балуне?
Гипервизор потеряет канал связи с гостем и не сможет управлять балуном дальше — обычно балун остаётся в последнем известном состоянии, а память, которую он держал, продолжает считаться занятой этой VM до перезагрузки гостя или повторного запуска агента. Это не аварийная ситуация, но и не то, что стоит делать намеренно на проде.
Нужно ли вручную настраивать ballooning на арендованном VPS, или это забота провайдера?
На типовом VPS с фиксированным тарифом ballooning либо не используется вовсе (ресурсы жёстко нарезаны), либо настраивается и контролируется провайдером на уровне хоста — обычному арендатору VPS вручную ничего трогать не нужно. Вопрос актуален в первую очередь для тех, кто сам администрирует гипервизор — например, на выделенном сервере с несколькими VM под свои задачи.
Обсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →