Btrfs-снапшоты и откат Linux-сервера: полноценный аналог System Restore
Меня зовут Семёнов Евгений Сергеевич, я директор АйТи Фреш. За 15+ лет работы с Linux-серверами одна из самых частых проблем — это неудачное обновление пакетов, после которого сервис перестаёт работать, а инженер сидит и судорожно вспоминает, какие именно библиотеки нужно откатить. Btrfs-снапшоты с snapper решают это элегантно: три команды — и система вернулась в состояние «до update». У меня на практике именно такая схема спасает серверы клиентов от крупных простоев.
Почему именно Btrfs, а не LVM-снапшоты
LVM-снапшоты существуют с начала 2000-х, и они работают, но плохо масштабируются. Каждый LVM snapshot требует выделения места заранее, и если вы сделали пять снимков за день, их хранение становится дорогим удовольствием. Плюс LVM snapshot блокирующий — запись в оригинальный том замедляется пропорционально количеству снимков.
Btrfs использует copy-on-write на уровне файловой системы. Снапшот — это просто новая ссылка на те же блоки данных. Создаётся мгновенно, занимает 0 байт на момент создания, растёт только по мере изменения файлов. На сервере с 500 ГБ данных и 60 снапшотами я обычно вижу оверхед 20-40 ГБ — в зависимости от того, насколько активно меняются файлы.
Разметка диска под Btrfs с субтомами
Правильная схема разметки — половина успеха. Я всегда использую раздельные субтомa для корня, /home и /var/log. Это даёт три вещи: откатить систему, не затронув пользовательские данные; исключить /var/log из снапшотов, чтобы не раздувать их; точный контроль над политикой хранения для каждой категории.
# На чистом SSD (допустим /dev/nvme0n1p2 — корневой раздел)
mkfs.btrfs -L system /dev/nvme0n1p2
mount /dev/nvme0n1p2 /mnt
# Создаём субтомa
btrfs subvolume create /mnt/@
btrfs subvolume create /mnt/@home
btrfs subvolume create /mnt/@var_log
btrfs subvolume create /mnt/@snapshots
# Отдельно для кеша и кэш-директорий, которые не нужны в снапшотах
btrfs subvolume create /mnt/@var_cache
btrfs subvolume create /mnt/@tmp
В /etc/fstab каждый субтом монтируется отдельной строкой с опцией subvol=@.... Важно: опция compress=zstd:3 даёт бесплатное сжатие 1.5-2x на текстовых данных, noatime убирает лишние записи времени доступа.
UUID=xxx / btrfs subvol=@,compress=zstd:3,noatime,ssd 0 0
UUID=xxx /home btrfs subvol=@home,compress=zstd:3,noatime,ssd 0 0
UUID=xxx /var/log btrfs subvol=@var_log,compress=zstd:3,noatime,ssd 0 0
UUID=xxx /.snapshots btrfs subvol=@snapshots,noatime,ssd 0 0
UUID=xxx /var/cache btrfs subvol=@var_cache,noatime,ssd 0 0
Установка и настройка snapper
Snapper — это демон, который управляет снапшотами по расписанию и по событиям. Автоматически делает pre/post снимки при запусках apt/dnf через хуки пакетного менеджера.
# Ubuntu/Debian
sudo apt install snapper
# Создаём конфиг для корня (важно: root subvolume должен быть Btrfs)
sudo snapper -c root create-config /
sudo snapper -c home create-config /home
# Смотрим список
sudo snapper -c root list-configs
Редактируем /etc/snapper/configs/root. Типовые параметры, которые я всегда правлю:
TIMELINE_CREATE="yes"
TIMELINE_CLEANUP="yes"
TIMELINE_LIMIT_HOURLY="10"
TIMELINE_LIMIT_DAILY="10"
TIMELINE_LIMIT_WEEKLY="8"
TIMELINE_LIMIT_MONTHLY="6"
TIMELINE_LIMIT_YEARLY="0"
NUMBER_CLEANUP="yes"
NUMBER_LIMIT="50"
NUMBER_LIMIT_IMPORTANT="20"
Хуки APT для автоматических снимков
Ключевой сценарий: перед apt upgrade делаем pre-снапшот, после — post. Если обновление сломало систему, откатываемся на pre. В Debian/Ubuntu для этого есть пакет snapper-gui и btrfs-progs, плюс скрипт в APT-хуках.
sudo apt install apt-btrfs-snapshot
Теперь каждая операция apt создаёт снимок автоматически. В Fedora/openSUSE snapper из коробки интегрирован с dnf/zypper.
Смотрим список снимков:
sudo snapper -c root list
# | Type | Pre # | Date | User | Cleanup | Description
---+--------+-------+--------------------------+------+---------+-----------------
0 | single | | | root | | current
42 | pre | | Wed Jun 04 08:15:12 2025 | root | number | apt
43 | post | 42 | Wed Jun 04 08:17:44 2025 | root | number |
44 | single | | Wed Jun 04 09:00:02 2025 | root | timeline| timeline
Откат после неудачного обновления
Допустим, после обновления сервер потерял сеть или сервис перестал стартовать. Алгоритм отката:
# Смотрим недавние pre-снапшоты
sudo snapper -c root list --type pre-post | tail
# Откатываемся на состояние ДО снапшота 42
sudo snapper -c root rollback 42
# Либо через diff смотрим, что изменилось
sudo snapper -c root status 42..43
# Для файлового отката отдельных файлов
sudo snapper -c root -v undochange 42..0 /etc/nginx/nginx.conf
Команда rollback создаёт новый субтом из указанного снапшота и делает его default. После перезагрузки сервер грузится с состояния на момент pre-снапшота. Важно: изменения в /home и /var/log не затрагиваются (если они отдельные субтома), то есть пользовательские данные и логи сохраняются.
Что именно восстанавливается — сравнение
| Субтом | Восстанавливается при rollback | Хранит снапшоты |
|---|---|---|
| @ (корень) | Да, полностью | Да |
| @home | Нет | Отдельно (home-конфиг snapper) |
| @var_log | Нет | Нет (исключён) |
| @var_cache | Нет | Нет |
| @tmp | Нет | Нет |
| @snapshots | Особый — хранит сами снимки | Нет |
Восстановление отдельных файлов
Не всегда нужен полный откат. Часто требуется вытащить один файл из вчерашнего состояния — например, испорченный конфиг nginx. Каждый снапшот монтируется в /.snapshots/N/snapshot, откуда можно обычным cp скопировать что нужно:
# Список снапшотов
ls /.snapshots/
# Достаём конфиг из снапшота 44
sudo cp /.snapshots/44/snapshot/etc/nginx/sites-available/example.conf \
/etc/nginx/sites-available/example.conf
sudo systemctl reload nginx
Отправка снапшотов на удалённый сервер
Btrfs поддерживает btrfs send/receive — инкрементальную репликацию снимков по SSH. Это мощная замена rsync для крупных FS.
# Первый (полный) бэкап
sudo btrfs send /.snapshots/100/snapshot | \
ssh backup@storage "btrfs receive /backup/server1/"
# Инкрементальный
sudo btrfs send -p /.snapshots/100/snapshot /.snapshots/101/snapshot | \
ssh backup@storage "btrfs receive /backup/server1/"
У нас на практике такая схема работает на клиентских серверах с еженощной репликацией на NAS в дата-центре МТС. Передача 500 ГБ базы данных инкрементально занимает 2-4 минуты, потому что отправляются только изменившиеся блоки.
Кейс: откат после обновления PHP
В апреле 2025 один из клиентов — интернет-магазин мебели на Bitrix — попросил нас обновить PHP с 8.1 на 8.2. После apt-upgrade на staging-сервере несколько кастомных расширений Bitrix перестали работать, сайт возвращал 500-е ошибки. Обычно в такой ситуации инженер тратит 1-2 часа на восстановление вручную: apt-history, удаление новых пакетов, установка старых версий.
У нас snapper сделал pre-snapshot автоматически перед обновлением. Команда snapper -c root rollback 187 и перезагрузка заняли три минуты. Сайт снова работал на PHP 8.1. Дальше мы на тест-контуре развернули обновление правильно — с предварительной подготовкой модулей — и повторили его в проде. Сервер — Dell PowerEdge R640 с Xeon Silver 4210, 64 ГБ RAM, NVMe RAID-1, стоит в дата-центре МТС.
Грабли, о которых нужно знать
У Btrfs есть особенности, на которых легко обжечься:
- RAID-5/6 в Btrfs нестабилен. Не используйте в проде. Для избыточности — mdadm RAID-10 или RAID-1 под Btrfs.
- qgroup замедляет запись. Не включайте квоты субтомов на нагруженных серверах — производительность падает в 2-3 раза.
- Балансировка нужна раз в квартал.
btrfs balance start -dusage=50 /— освобождает фрагментированные экстенты. - Сжатие zstd не лечит заполненность. Файловая система всё равно должна видеть свободные блоки.
- Докер любит раздувать субтома. Для Docker используйте отдельный субтом и overlay2, а не btrfs storage driver.
Настроим Btrfs + snapper на ваших серверах
Развернём Btrfs с правильной разметкой, snapper с автоснимками и репликацией на удалённое хранилище. Обучим администратора делать откаты и восстанавливать файлы. Работаем с Ubuntu LTS, Debian, openSUSE, Rocky Linux.
Телефон: +7 903 729-62-41
Telegram: @ITfresh_Boss
Семёнов Евгений Сергеевич, директор АйТи Фреш
FAQ — частые вопросы по Btrfs
- Btrfs или ZFS — что выбрать в 2025?
- ZFS стабильнее для нагруженного storage. Btrfs удобнее для rolling-release с откатом через snapper. Оба готовы к проду в своих нишах.
- Можно ли использовать Btrfs на RAID-5/6?
- Не рекомендуется из-за write hole. Используйте mdadm RAID-10 или hardware RAID как основу, а Btrfs поверх.
- Как snapper делает снапшот?
- Создаёт Btrfs subvolume snapshot через CoW — мгновенно и без дублирования данных.
- Что если откат сломал загрузку?
- Грузимся с live-USB, btrfs subvolume set-default на рабочий снимок, обновляем GRUB.
- Сколько снапшотов хранить?
- Стандартная политика: 10 hourly + 10 daily + 8 weekly + 6 monthly. Корректируйте под свободное место на диске.