Обновление ядра или systemd на рабочем сервере ломает загрузку чаще, чем ожидается: свежий initramfs собирается без модуля хранилища, сервис из нового пакета ждёт сокет, которого больше нет, зависимости тянут несовместимую библиотеку. Read-only снимок Btrfs, созданный за минуту до apt upgrade, возвращает машину в исходное состояние за 5-10 минут ручной работы.
Короткий ответ на главный вопрос: снимок фиксирует корневой subvolume целиком, вместе с /usr, /etc, /var и составом установленных пакетов, поэтому после отката сервер выглядит так, будто обновления не было. Схема целиком: убедиться, что корень на Btrfs, создать отдельный subvolume для снимков, сделать read-only snapshot, выгрузить его через btrfs send на внешний диск, обновиться, при сбое переключиться на снимок и пересобрать GRUB.
Зачем делать снимки Btrfs перед обновлением Linux-сервера
Btrfs построен на copy-on-write (CoW). Снимок subvolume в момент создания ссылается на те же экстенты, что и оригинал, поэтому копирования байтов не происходит. Снимок корня на 200 ГБ создаётся за доли секунды и в первый момент не занимает места вообще. Когда после обновления файл меняется, Btrfs пишет новые блоки, а старые остаются закреплёнными за снимком.
Отсюда практический вывод для дежурного админа: локальный откат обновления занимает меньше времени, чем переустановка одного пакета с зависимостями. Планирование окна обслуживания, коммуникацию с командой и общий порядок действий при релизах разбирают в отдельном руководстве по безопасному обновлению критических систем, здесь же разберём техническую часть до команд.
Чем read-only snapshot Btrfs отличается от обычного бэкапа
Снимок и резервная копия решают разные задачи, и путать их дорого.
- Снимок живёт в той же файловой системе и защищает от ошибок обновления: сломанных зависимостей, неудачного ядра, испорченного конфига.
- Резервная копия лежит на другом носителе и защищает от отказа диска, контроллера, ошибки файловой системы.
- Read-only снимок создаётся с флагом -r, ядро вернёт ошибку read-only file system при попытке записи в него. Случайно испортить снимок командой из истории не получится.
- Снимок занимает место только на разницу с оригиналом, бэкап копирует данные физически.
Правильная связка выглядит так: read-only снимок для быстрого локального отката, и btrfs send на внешний диск для восстановления с live-USB, если сам пул или загрузчик пострадали.
Когда снимок Btrfs не спасёт: ограничения подхода
Четыре сценария, в которых схема не сработает, лучше знать заранее.
- Отказ диска или контроллера. Снимки в том же пуле исчезнут вместе с оригиналом, спасает только копия на другом носителе.
- Повреждение метаданных Btrfs. Если btrfs check находит ошибки, переключение default subvolume не поможет, нужен live-USB и восстановление из send/receive-копии.
- Поломка GRUB или загрузчика. Откат без пересборки grub.cfg оставит сервер с меню, указывающим на старое ядро в удалённом subvolume.
- Переполнение пула. После обновления каждый изменённый файл оставляет в снимке уникальные блоки, и пять снимков корня на сервере с активными логами съедят десятки гигабайт.
Подготовка сервера: проверка Btrfs и создание subvolume
Шаги ниже выполняются один раз, дальше обновления будут занимать минуты вместо часов.
Проверка, что корень смонтирован на Btrfs
findmnt -no FSTYPE / btrfs filesystem show btrfs subvolume list /
Ожидаемый результат: первая команда печатает btrfs, вторая показывает устройства пула, метку и UUID, третья перечисляет subvolume с ID и путями. Если выводится ext4 или xfs, инструкция к этому серверу не подходит: либо миграция, либо снимки средствами LVM.
Создание и монтирование subvolume @ и @home
Раскладка ниже совпадает с той, что используют установщики Ubuntu, Debian, Fedora и openSUSE: top-level subvolume с ID 5 остаётся пустым контейнером, корень уезжает в @, пользовательские данные в @home, снимки в @snapshots.
mkfs.btrfs -L rootfs /dev/sda2 mount /dev/sda2 /mnt btrfs subvolume create /mnt/@ btrfs subvolume create /mnt/@home btrfs subvolume create /mnt/@snapshots btrfs subvolume list /mnt umount /mnt
Отдельный @snapshots нужен по важной причине: вложенные subvolume не попадают в снимок родителя. Снимки корня не будут раздувать сам снимок корня, а замена @ не утащит их за собой.
Строки для /etc/fstab:
UUID=ВАШ-UUID / btrfs subvol=@,compress=zstd,noatime,space_cache=v2 0 0 UUID=ВАШ-UUID /home btrfs subvol=@home,compress=zstd,noatime 0 0 UUID=ВАШ-UUID /snapshots btrfs subvol=@snapshots,compress=zstd,noatime 0 0
Проверка результата после перезагрузки:
findmnt -no SOURCE,FSTYPE,OPTIONS / btrfs subvolume show / btrfs subvolume show /snapshots
В выводе btrfs subvolume show для корня должно быть указано Path: @ и Flags без readonly.
Создание read-only snapshot Btrfs перед обновлением
Снимок делается строго до первого шага обновления, пока пакеты и ядро не тронуты.
Практическая команда создания read-only snapshot
uname -r dpkg -l | wc -l btrfs subvolume snapshot -r / /snapshots/root-$(date +%F-%H%M)
Флаг -r превращает снимок в read-only. Имя с датой и временем избавляет от ручного переименования, когда снимков станет десяток. Перед снимком полезно сохранить текущую версию ядра и количество пакетов: после отката эти значения должны совпасть.
Проверка результата: список снимков и их размер
btrfs subvolume list -r / btrfs subvolume show /snapshots/root-2026-09-11-0930 btrfs filesystem usage /
В списке появится новый subvolume с тем же ID, что указан в выводе show. Поле Flags: readonly подтверждает, что снимок защищён от записи, строка Snapshot(s) of показывает родителя. Колонка used в filesystem usage сразу после создания почти не изменится, это нормально.
Резервное копирование снимков через Btrfs send/receive
Локальный снимок не переживёт смерть диска, поэтому копию выносим на внешний носитель.
Полный send/receive снимка на внешний диск
mkfs.btrfs -L backup /dev/sdb1 mount /dev/sdb1 /mnt/backup btrfs send /snapshots/root-2026-09-11-0930 | btrfs receive /mnt/backup/
Отправлять можно только read-only subvolume, иначе btrfs send завершится ошибкой. После первой копии на приёмнике появится subvolume с тем же именем, пригодный для монтирования и восстановления.
Инкрементальный send/receive для экономии места и времени
btrfs send -p /snapshots/root-2026-09-10-0900 /snapshots/root-2026-09-11-0930 | btrfs receive /mnt/backup/ btrfs subvolume list -r /mnt/backup/
Ключ -p задаёт родительский снимок, и по сети или на диск уходят только изменённые блоки. Родитель обязан уже лежать на приёмнике, иначе btrfs receive ответит failed to receive subvolume. Для сервера с корнем на 40-60 ГБ инкремент после планового обновления обычно занимает сотни мегабайт вместо десятков гигабайт.
Если нужна полноценная стратегия с ротацией, дедупликацией и автотестами восстановления, смотрите руководство по резервному копированию сервера 2026 с rsync, Borg и Rclone: Btrfs-снимки хорошо закрывают быстрый локальный откат, а долговременное хранение удобнее строить на специализированных инструментах.
Обновление Linux-сервера и проверка после перезагрузки
Снимок лежит на диске, копия отправлена на внешний носитель. Теперь обновляемся.
apt update && apt full-upgrade -y systemctl reboot
Для RHEL-производных вместо первых двух команд используется dnf upgrade -y. Порядок действий, типовые окна обслуживания и автоматизация через Ansible и CI/CD разобраны в практическом руководстве по обновлению информационных систем.
Чек-лист проверки после обновления
uname -r systemctl list-units --state=failed journalctl -p err -b --no-pager | tail -n 40 dmesg --level=err,warn | tail -n 30 findmnt -no TARGET,SOURCE,FSTYPE | grep btrfs ss -tulpn | head -n 20
Если ядро сменилось и сервисы поднялись, а в journalctl нет ошибок уровня err, обновление прошло штатно. Появились failed-юниты, не поднимается сеть или база, переходим к откату: снимок даёт на это ровно то время, которое экономит локальная копия.
Откат обновления Linux с помощью снимка Btrfs
Если система не грузится, работаем с live-USB того же дистрибутива, что установлен на сервере.
Загрузка с live-USB и монтирование top-level subvolume
lsblk -f mount /dev/sda2 /mnt -o subvolid=5 ls /mnt btrfs subvolume list /mnt
Монтирование с subvolid=5 открывает top-level subvolume, в котором видны @, @home и snapshots. Дальше нужно выбрать целевой снимок, например snapshots/root-2026-09-11-0930.
Переключение default subvolume или замена @ снимком
Способ первый, через default subvolume:
btrfs subvolume list /mnt | grep root-2026-09-11 btrfs subvolume set-default 261 /mnt umount /mnt && reboot
Способ работает, только если в fstab не задан параметр subvol= или subvolid=. Явное указание subvolume в fstab перекрывает default, и сервер снова загрузится со сломанного корня. Второй способ лишён этого ограничения:
cd /mnt mv @ @broken-2026-09-11 btrfs subvolume snapshot /mnt/snapshots/root-2026-09-11-0930 /mnt/@
Снимок создаётся обычный, для записи, а испорченный @ остаётся в стороне до подтверждения, что система стабильна.
Обновление GRUB и перезагрузка после отката
mount --bind /proc /mnt/proc mount --bind /sys /mnt/sys mount --bind /dev /mnt/dev mount /dev/sda1 /mnt/boot/efi chroot /mnt grub-mkconfig -o /boot/grub/grub.cfg update-initramfs -u -k all exit umount -R /mnt reboot
Без пересборки grub.cfg и initramfs загрузчик продолжит искать ядро по старым путям и записям в меню. После перезагрузки проверяем findmnt /, uname -r, systemctl list-units --state=failed и сверяем версии пакетов с теми, что зафиксировали перед снимком.
Контроль свободного места при накоплении снимков Btrfs
Снимки делят экстенты с оригиналом, но после обновления каждый изменённый файл оставляет уникальные блоки. Без ротации пул заканчивается в самый неподходящий момент.
Как читать вывод btrfs filesystem usage и qgroup
btrfs filesystem usage / btrfs qgroup show -reF /
| Поле в выводе | Что показывает | На что смотреть |
|---|---|---|
| Device unallocated | Место, не отданное под Data, Metadata и System | Близко к нулю: скоро упрутся в лимит метаданные |
| Data | Занято под данные, с разбивкой used и free | used растёт после каждого обновления, free падает |
| Metadata | Занято под дерево subvolume и метаданные | Тысячи мелких файлов раздувают метаданные быстрее данных |
| Data ratio | Степень зеркалирования блоков | Для single всегда 1.00, для RAID1 равен 2.00 |
| qgroup exclusive | Уникальные блоки конкретного снимка | Показывает, сколько освободит удаление этого снимка |
Удаление старых снимков без потери данных
btrfs subvolume list -s / btrfs subvolume delete /snapshots/root-2026-09-01-0800
Read-only снимок удаляется без предварительного снятия флагов, отдельная команда для этого не нужна. Рабочая стратегия: держать на локальном диске 3-5 последних снимков корня, на внешнем носителе хранить один полный и цепочку инкрементов за 30 дней. Ротацию удобно повесить на systemd timer или cron той же командой btrfs subvolume delete. Освобождаются только уникальные блоки: если удаляемый снимок делит большинство экстентов с текущим корнем, места вернётся мало.
Диагностика ошибок при работе со снимками Btrfs
Типовые сообщения и их причины собраны в таблице, чтобы не искать смысл по форумам в момент инцидента.
Типовые ошибки и их решения
| Ошибка | Причина | Решение |
|---|---|---|
| ERROR: cannot find real path | Путь указан от корня смонтированной системы, а не от точки монтирования top-level | Сверьте путь с выводом btrfs subvolume list /mnt (live-USB) |
| ERROR: read-only file system | Попытка записи в снимок, созданный с флагом -r | Работайте с копией: btrfs subvolume snapshot /snapshots/root-X /mnt/@ |
| ERROR: failed to receive subvolume | Для инкремента с -p на приёмнике нет родительского снимка | Сначала выполните полный send, затем инкрементальный |
| ERROR: cannot delete: Device or resource busy | Subvolume смонтирован, например /snapshots | umount /snapshots или удаляйте снимки при загруженной системе через точку / |
| ERROR: not a subvolume | В пути обычный каталог внутри subvolume, а не сам subvolume | Делайте снимок корня subvolume, а не вложенного каталога |
| BTRFS error: ENOSPC в метаданных | Закончилось место под служебные деревья | Удалите старые снимки, проверьте Device unallocated, добавьте устройство |
Команды диагностики состояния Btrfs
dmesg | grep -i btrfs btrfs filesystem df / btrfs device stats / btrfs subvolume show / journalctl -b -p err | grep -i btrfs btrfs check --readonly /dev/sda2
btrfs check запускают только на размонтированной файловой системе, ключ --readonly безопасен и ничего не меняет, а --repair применяют последним шагом после копии данных. Команда btrfs device stats показывает счётчики ошибок чтения и записи по каждому устройству: ненулевые значения говорят о проблемах с диском или кабелем. Если journalctl выдаёт тысячи строк, разбор ускоряет прогон логов через API нейросетей: AiTunnel даёт единый доступ к GPT, Gemini и Claude с оплатой в рублях, но передавайте логи обезличенными.
Сравнение Btrfs snapshots с LVM и ZFS для отката обновлений
Все три технологии умеют откатывать обновления, выбор зависит от того, что уже стоит на сервере.
Когда выбрать Btrfs, а когда LVM или ZFS
| Критерий | Btrfs snapshot | LVM snapshot | ZFS snapshot |
|---|---|---|---|
| Скорость создания | Секунды, размер данных не влияет | Секунды, нужен свободный extent в volume group | Секунды, работает на уровне dataset |
| Расход места | Только изменённые блоки, экстенты общие | CoW-том, под изменения резервируется место | Общие блоки в пределах пула |
| Гранулярность | Корень и /home откатываются отдельно | Логический том целиком | Отдельный dataset |
| Откат системы | set-default или замена @ | lvconvert --merge с перезагрузкой | zfs rollback dataset |
| Отправка на другой хост | btrfs send / receive | Штатного механизма нет | zfs send / receive |
| Проверка целостности | Контрольные суммы данных и метаданных | Нет | Контрольные суммы и scrub |
Btrfs выбирают, когда корень уже на этой файловой системе и нужен откат за минуты без дополнительных слоёв. LVM подходит для серверов на ext4 и XFS, где том уже создан: снимок тома снимается одной командой, но объём под изменения нужно резервировать заранее, иначе snapshot становится невалидным. ZFS даёт контрольные суммы, scrub и send/receive на уровне пула, подробности и типовые ошибки проектирования собраны в разборе ZFS и OpenZFS. Если сервер работает под TrueNAS, автоматизацию снимков и их ротацию удобно строить по практике резервного копирования на ZFS-снимках в TrueNAS.
Итоговый чек-лист безопасного обновления Linux-сервера с Btrfs
- Проверить файловую систему: findmnt -no FSTYPE /. Ожидается btrfs.
- Убедиться, что /snapshots смонтирован отдельным subvolume @snapshots.
- Зафиксировать uname -r и dpkg -l | wc -l до обновления.
- Создать read-only снимок: btrfs subvolume snapshot -r / /snapshots/root-$(date +%F-%H%M).
- Проверить снимок: btrfs subvolume list -r / и btrfs filesystem usage /.
- Выгрузить полный снимок через btrfs send, затем держать инкременты с ключом -p.
- Обновить пакеты и перезагрузиться.
- Проверить systemctl list-units --state=failed, journalctl -p err -b, uname -r, состояние сервисов и монтирований.
- При сбое загрузиться с live-USB, смонтировать subvolid=5, откатиться через set-default или замену @, пересобрать GRUB.
- После подтверждения стабильности удалить старые снимки командой btrfs subvolume delete.
# минимальный набор команд перед обновлением findmnt -no FSTYPE / uname -r btrfs subvolume snapshot -r / /snapshots/root-$(date +%F-%H%M) btrfs subvolume list -r / btrfs filesystem usage /
Отрепетировать откат безопаснее на отдельном стенде, чем на боевом сервере: разверните VPS в Timeweb Cloud, повторите разметку с @ и @home, обновите ядро и прогоните полный цикл восстановления, включая chroot и grub-mkconfig. Один такой прогон на тестовой машине снимает большинство сомнений и заметно сокращает время простоя в реальный инцидент.