Бэкап виртуальной машины на KVM/QEMU часто сводят к «сделали snapshot диска на хосте — и готово». На практике это может дать архив, который формально читается, но внутри содержит повреждённые журналы, частично записанные страницы БД или несогласованный набор файлов. Причина простая: гостевая ОС и приложения продолжают писать данные, а снапшот на уровне гипервизора фиксирует состояние диска ровно в тот момент, когда часть изменений ещё находится в кэше ядра или в буферах БД.
Чтобы получить consistent snapshot, нужно либо остановить записи (пусть и на секунды), либо добиться согласованной точки восстановления через механизмы ФС/приложений. На практике самый удобный компромисс для «vm backup» — связка qemu-guest-agent и fsfreeze (точнее, вызов заморозки через guest agent): гостевая ОС синхронизирует данные и временно блокирует запись на файловых системах, а вы быстро делаете snapshot на хосте.
Ниже — понятная схема: что именно даёт freeze, как включить агент, как выполнить freeze → snapshot → thaw, и где границы метода, если внутри ВМ живёт PostgreSQL/MySQL.
Какой уровень консистентности нужен: crash-consistent и filesystem-consistent
На практике для снапшотов ВМ чаще всего обсуждают два уровня:
- Crash-consistent — «как будто выдернули питание». ФС обычно поднимается за счёт journaling, но приложения (особенно БД) могут делать длительный recovery.
- Filesystem-consistent — файловая система в согласованном состоянии: грязные страницы сброшены на диск, а запись на время «окна» заблокирована. Именно это обычно и даёт
fsfreeze.
fsfreeze не делает «магически app-consistent» бэкап БД, но сильно снижает риск получить полу-записанные данные на уровне файлов. Для критичных баз отдельная стратегия бэкапа всё равно обязательна (PITR, реплика, специализированные инструменты), а снапшот ВМ — дополнительный слой защиты.
Практический ориентир: для статических файлов, конфигов, небольших сервисов и обычных веб-приложений filesystem-consistent снапшот часто достаточен. Для критичных БД рассчитывайте на recovery при старте и держите отдельные бэкапы на уровне СУБД.
Как работает qemu-guest-agent и почему без него freeze не получится
qemu-guest-agent — демон внутри гостевой ОС, который общается с гипервизором через virtio-serial канал. Через него хост может «вежливо попросить» гостя выполнить действия: ping, shutdown, получение сетевой информации, и ключевое для бэкапов — fsfreeze/fsthaw.
Важные моменты для продакшена:
- Если агент не установлен или не запущен, команды freeze/thaw с хоста не отработают.
- Freeze выполняется внутри гостя, поэтому всё упирается в состояние гостевой ОС, её файловых систем и текущую I/O-нагрузку.
- Окно freeze должно быть коротким: любые процессы, которые пишут на диск, будут ждать, и это легко превращается в таймауты на уровне приложений.
Если вы делаете бэкапы для проектов, которые крутятся на VDS или на собственном KVM-хосте, одинаково важно заранее отладить связь гипервизора с агентом и только потом автоматизировать снапшоты.

Установка и проверка qemu-guest-agent в гостевой ОС
Выполняйте команды внутри виртуальной машины.
Debian/Ubuntu
sudo apt update
sudo apt install -y qemu-guest-agent
sudo systemctl enable --now qemu-guest-agent
sudo systemctl status qemu-guest-agent
RHEL/AlmaLinux/Rocky/CentOS
sudo dnf install -y qemu-guest-agent
sudo systemctl enable --now qemu-guest-agent
sudo systemctl status qemu-guest-agent
Если агент не стартует: логи
sudo journalctl -u qemu-guest-agent --no-pager -n 200
Проверка с хоста (libvirt)
На хосте с libvirt проверьте, что агент отвечает:
virsh domstate VMNAME
virsh qemu-agent-command VMNAME '{"execute":"guest-ping"}'
Если видите ошибку наподобие «guest agent is not responding», сначала чините транспорт (virtio-serial channel в конфигурации ВМ), затем сервис в госте.
fsfreeze на практике: что замораживается и где бывают проблемы
Механика freeze простая: гостевая ОС сбрасывает грязные данные на диск и блокирует операции записи на поддерживаемых файловых системах. Важно учитывать нюансы, которые чаще всего ломают «красивую теорию»:
- Если данные важного приложения лежат на отдельном mountpoint (например,
/varили отдельный диск под/var/lib/postgresql), freeze должен покрывать все релевантные ФС. - Псевдо-ФС (
proc,sysfs,tmpfs) обычно не являются целью снапшота и ведут себя иначе — это нормально. - При высокой нагрузке flush перед freeze может занять заметное время. Чем дольше freeze, тем выше шанс таймаутов и «фризов» на уровне сервисов.
Freeze — это секундная операция для фиксации точки на диске. Если между freeze и thaw у вас минуты ожидания, нужно менять механизм: делайте мгновенный snapshot на хранилище, а копирование выполняйте уже из снапшота.
Базовый сценарий: freeze → snapshot → thaw (libvirt/virsh)
Типовой алгоритм одинаковый для любых бэкапов на уровне ВМ:
- Проверить, что агент отвечает.
- Заморозить файловые системы в госте.
- Быстро сделать snapshot на стороне хоста/СХД.
- Сразу разморозить файловые системы.
- Залогировать результат и длительность окна freeze.
Команды
Заморозить поддерживаемые ФС:
virsh domfsfreeze VMNAME
Разморозить:
virsh domfsthaw VMNAME
Посмотреть, какие ФС видит libvirt:
virsh domfsinfo VMNAME
Скелет скрипта с гарантированным thaw
Идея: даже если snapshot-команда упала, разморозка должна выполниться.
#!/usr/bin/env bash
set -euo pipefail
VM="VMNAME"
thaw() {
virsh domfsthaw "$VM" || true
}
trap thaw EXIT
virsh qemu-agent-command "$VM" '{"execute":"guest-ping"}'
echo "Freezing filesystems in guest..."
virsh domfsfreeze "$VM"
echo "Run snapshot on host/storage"
# Вставьте вашу команду snapshot (LVM/ZFS/СХД/панель)
echo "Thawing filesystems in guest..."
virsh domfsthaw "$VM"
trap - EXIT
Если внутри ВМ PostgreSQL/MySQL: что делать с database consistency
Частый вопрос: «Я сделал fsfreeze, значит бэкап базы “идеальный”?» Нет. Freeze улучшает консистентность файлов на диске, но не заменяет нативные механизмы СУБД (PITR, репликация, физические/логические бэкапы).
Что fsfreeze обычно даёт для БД:
- Гостевая ОС принудительно сбрасывает данные ФС на диск перед заморозкой.
- На короткое окно блокируются новые записи на уровне ФС.
Чего fsfreeze не гарантирует:
- Чёткой «точки во времени» на уровне транзакций приложения.
- Отсутствия crash-recovery при старте из снапшота (он обычно будет, и это нормальный сценарий).
Компромисс: подготовка БД перед freeze
Если вы делаете общий snapshot всей ВМ и хотите уменьшить время восстановления БД, можно мягко подготовить БД до freeze.
PostgreSQL: принудительный checkpoint (внутри ВМ):
sudo -u postgres psql -c "CHECKPOINT;"
Для MySQL/MariaDB конкретные команды зависят от движка и конфигурации. Если у вас важная MySQL и нужен гарантируемый PITR, держите отдельный процесс бэкапа по binlog/GTID и регулярно проверяйте восстановление. Практический разбор подхода: PITR для MySQL/MariaDB через binlog и GTID.
Для PostgreSQL аналогично полезно иметь отдельную стратегию WAL/PITR: PITR PostgreSQL через WAL: бэкап и восстановление.
Диагностика: почему freeze не срабатывает или «висит»
1) Агент не отвечает
Проверьте по цепочке:
- Сервис
qemu-guest-agentзапущен в госте. - Virtio-serial channel подключён в конфигурации ВМ.
- SELinux/AppArmor не блокирует работу агента (смотрите логи в госте).
2) Freeze выполняется слишком долго
Почти всегда причина — активная запись и длительный flush. Рабочие меры:
- Делать мгновенный snapshot на хранилище, а «долгую» копию бэкапа — уже из снапшота.
- Не ставить бэкап в пик нагрузки (batch job, вакуум БД, ротации логов).
- Отделять тяжёлые данные на отдельные тома и выбирать стратегию точечно.
3) После восстановления БД долго поднимается
Для crash/filesystem-consistent снапшотов это ожидаемо: БД проигрывает журналы и приводит данные в порядок. «Лечится» это не настройкой freeze, а наличием нормальной стратегии резервного копирования на уровне СУБД и регулярными тестами восстановления.
Проверка бэкапов: как убедиться, что снапшот действительно восстанавливается
Бэкап считается существующим только после успешного тестового восстановления. Минимальный набор проверок:
- Регулярный restore в изолированную ВМ/стенд.
- Проверка загрузки ОС и журналов.
- Проверка старта и базовых запросов к БД.
- Контроль длительности окна freeze и алертинг при отклонениях.
Быстрая проверка PostgreSQL после restore
sudo -u postgres psql -c "SELECT now();"
sudo -u postgres psql -c "SELECT pg_is_in_recovery();"
Если восстановление заметно дольше обычного — смотрите логи PostgreSQL, I/O и объём WAL.
Итог
Связка qemu-guest-agent + fsfreeze — простой способ перевести «слепой» снапшот диска ВМ в предсказуемый filesystem-consistent snapshot: ядро гостя синхронизирует данные и на короткое окно блокирует запись, а вы делаете быстрый snapshot на хосте.
Для критичных баз данных это всё ещё не «идеальная консистентность приложения», поэтому держите отдельные бэкапы на уровне СУБД (WAL/binlog/PITR, логические/физические инструменты) и регулярно тестируйте восстановление. Тогда vm snapshot станет надёжным дополнительным уровнем защиты, а не лотереей.



