Резервное копирование хранилища изображений: стратегия 3-2-1 и практика MinIO, Ceph, ZFS, Restic и Borg | AdminWiki

Резервное копирование хранилища изображений: стратегия 3-2-1 и практика MinIO, Ceph, ZFS, Restic и Borg

11 сентября 2026 14 мин. чтения
Содержание статьи

Почему классическая стратегия 3-2-1 требует адаптации для больших объёмов изображений

Хранилище на 50 ТБ изображений, которое каждый день копируется целиком, за месяц создаёт около 1,5 ПБ копий и трафика. Ни сеть, ни дисковый массив, ни бюджет облачного хранилища такой график не выдерживают. Рабочая схема для медиаданных выглядит иначе: одна полная копия в неделю, ежедневные инкременты, immutability против шифровальщиков и обязательная проверка восстановления.

Правило 3-2-1 (три копии, два разных носителя, одна копия вне площадки) остаётся фундаментом, но в исходном виде оно рассчитано на базы данных и файловые серверы объёмом в сотни гигабайт. Для терабайтов картинок к нему добавляются четыре требования: неизменяемые копии, дедупликация на уровне блоков, длинные инкрементальные цепочки и разделение горячих и холодных копий. Разбор стратегии 3-2-1 с готовыми скриптами и расписаниями поможет сверить свою схему с проверенной.

Арифметика проста. Полный бэкап 50 ТБ раз в неделю плюс шесть ежедневных инкрементов по 200-500 ГБ дают около 55 ТБ в неделю, то есть примерно 230 ТБ в месяц против 1,5 ПБ при ежедневном полном копировании. Дедупликация и перенос только изменившихся блоков сокращают объём ещё в 2-4 раза: изображения редко меняются после загрузки, поэтому одинаковые чанки в репозитории хранятся один раз.

Как пересчитать 3-2-1 под медиахранилище: три копии, два типа носителей, одна вне площадки

Схема для хранилища изображений на десятки терабайт:

  • Копия 1, горячая: продакшн-кластер MinIO или Ceph RGW. Отвечает за отдачу контента и живёт на быстрых дисках.
  • Копия 2, тёплая: локальный репозиторий Restic или Borg на отдельном сервере либо снапшоты ZFS на втором пуле. Носитель отличается от продакшна: если прод на NVMe, вторая копия на HDD. Отказ партии SSD или ошибка прошивки контроллера не должны убивать обе копии сразу.
  • Копия 3, холодная и offsite: S3-совместимое хранилище в другом регионе с включённым Object Lock. Такую копию удобно держать в облаке: Timeweb Cloud даёт объектное хранилище, серверы и сеть в одном кабинете, что упрощает расчёты за трафик и место.

Изображения не существуют сами по себе. Рядом лежат метаданные EXIF, превью разных размеров, индексы поиска и база каталога с записями об объектах. Если снять снапшот файлов и базу в разные минуты, после восстановления получится библиотека картинок без записей в каталоге или каталог со ссылками на отсутствующие файлы. Практика: снапшот СУБД и снапшот файлов делают в одном окне, хранят в одном наборе и восстанавливают вместе.

Шифрование offsite-копий выполняют на клиенте до отправки: Restic и Borg шифруют данные до того, как они уйдут по сети, поэтому провайдер получает только шифротекст и не может прочитать библиотеку.

Immutable-бэкапы и Object Lock: защита от шифровальщиков и случайного удаления

Механизм WORM (write once, read many) не даёт удалить или перезаписать объект до истечения срока хранения. В MinIO Object Lock включается только при создании бакета, готовый бакет переключить нельзя:

mc mb --with-lock minio/backup-immutable
mc retention set --default COMPLIANCE 90d minio/backup-immutable

Режим COMPLIANCE запрещает снятие блокировки до истечения срока даже администратору кластера, GOVERNANCE позволяет обойти запрет при наличии права s3:BypassGovernanceRetention. Legal hold ставится и снимается отдельно от retention и не привязан к дате. Ceph RGW поддерживает те же настройки для бакетов с включённым versioning.

Срок хранения выбирают под требования бизнеса: типичные значения 30, 90 или 365 дней. Держите в голове цену решения: неизменяемый объект занимает место до конца срока, поэтому 100 ТБ ежедневных копий при retention 365 дней превратятся в петабайты, которые нельзя удалить досрочно.

У клиентских инструментов есть свой аналог WORM. Restic работает с rest-server в режиме --append-only: новые снапшоты пишутся, старые не удаляются. Borg включает append-only через borg serve --append-only в authorized_keys на стороне сервера. В обоих случаях для обслуживания репозитория нужен второй ключ или отдельный доступ, иначе prune и forget не выполнятся.

Репликация MinIO: настройка межкластерного копирования изображений

MinIO реплицирует объекты на уровне бакета или целого сайта и поддерживает версионирование, Object Lock и правила фильтрации по префиксу. Репликация асинхронная: объект сначала фиксируется на источнике, затем уходит на приёмник.

Подготовка кластеров и прав доступа для репликации

Версии MinIO на обоих кластерах должны совпадать. Расхождение версий ломает служебные вызовы, а для репликации сайта совпадение обязательно. Второе условие: синхронизированное время по NTP, потому что подпись AWS Signature V4 привязана ко времени запроса.

Дальше включают версионирование и создают отдельного пользователя для репликации:

mc version enable minio-a/images
mc admin user add minio-a replication-user S3cretKey
mc admin policy create minio-a replication-policy replication-policy.json
mc admin policy attach minio-a replication-policy --user replication-user

Политика в JSON перечисляет действия: s3:GetObject, s3:GetObjectVersion, s3:PutObject, s3:DeleteObject, s3:DeleteObjectVersion, s3:ListBucket, s3:GetBucketVersioning, s3:GetBucketLocation, s3:GetReplicationConfiguration, s3:PutReplicationConfiguration, s3:ReplicateObject, s3:ReplicateDelete. Отдельный пользователь с узкой политикой надёжнее root-ключа: утечка ключа репликации не даст доступа к удалению бакетов и настройкам кластера.

Команды mc replicate add и проверка статуса

Сначала настраивают алиасы на оба кластера:

mc alias set minio-a https://minio-a.example.com ACCESS SECRET
mc alias set minio-b https://minio-b.example.com ACCESS SECRET

Репликация сайта одной командой накрывает оба направления, включая пользователей, политики и настройки ILM:

mc admin replicate add minio-a minio-b

Для репликации одного бакета правило добавляют точечно, с фильтром по префиксу и переносом удалений:

mc replicate add minio-a/images --remote-bucket https://minio-b.example.com/images --arn arn:minio:replication::a1b2c3d4:images --replicate delete,delete-marker,existing-objects --priority 1 --prefix 2026/

Флаг --replicate delete,delete-marker синхронизирует удаления и маркеры версий, existing-objects запускает первичную репликацию уже лежащих объектов, --priority задаёт порядок применения правил, --prefix ограничивает область. Статус смотрят командой mc replicate status minio-a/images: она показывает число объектов в очереди, ошибки и отставание. Сайт целиком проверяют через mc admin replicate status minio-a, а причину сбоев ищут в трассировке mc admin trace -v --errors minio-a.

Репликация не заменяет бэкап. Она защищает от отказа узла и площадки, но не от логической ошибки: случайный mc rm --recursive попадает и на приёмник. Спасение дают версионирование на обоих кластерах и отдельный бакет с Object Lock, куда пишет Restic.

Ceph RGW: репликация и резервное копирование объектного хранилища

Ceph RGW хранит объекты в RADOS-пулах и синхронизирует их между зонами через multisite. Для библиотеки изображений это означает отдельный кластер Ceph: держать обе зоны на одном кворуме MON бессмысленно, один сбой уносит и прод, и копию.

Настройка multisite: realm, zonegroup, zone

На первом кластере создают realm, zonegroup и мастер-зону:

radosgw-admin realm create --rgw-realm=media --default
radosgw-admin zonegroup create --rgw-zonegroup=us --endpoints=http://rgw-a:7480 --master --default
radosgw-admin zone create --rgw-zone=us-east --rgw-zonegroup=us --endpoints=http://rgw-a:7480 --master --default
radosgw-admin period update --commit

На втором кластере сначала подтягивают realm и ключи доступа, затем создают вторую зону:

radosgw-admin realm pull --url=http://rgw-a:7480 --access-key=... --secret=...
radosgw-admin zonegroup create --rgw-zonegroup=eu --endpoints=http://rgw-b:7480 --default
radosgw-admin zone create --rgw-zone=eu-west --rgw-zonegroup=eu --endpoints=http://rgw-b:7480 --access-key=... --secret=...
radosgw-admin period update --commit
systemctl restart ceph-radosgw@rgw.eu-west

Периоды синхронизируют конфигурацию между зонами, поэтому после каждого изменения нужны period update --commit и перезапуск radosgw. Время на всех узлах должно идти без расхождений: chrony или systemd-timesyncd с контролем смещения. Рассинхронизация часов ломает подписи и останавливает передачу объектов. Первичная синхронизация медиабиблиотеки на десятки терабайт занимает дни, и это нормальный режим, а не сбой.

Мониторинг и устранение неполадок репликации Ceph

radosgw-admin sync status
radosgw-admin data sync status --source-zone=us-east
radosgw-admin metadata sync status
radosgw-admin bucket sync status --bucket=images
radosgw-admin sync error list

Ключевой показатель в выводе sync status - число шардов, отстающих от источника. Типовые причины отставания: расхождение часов, несовпадающие access key и secret key между зонами, ошибки 403 из-за политики бакета, обрыв канала между площадками. Алерты ставят не только на ошибки, но и на отставание: рост числа шардов в статусе behind означает, что копия устаревает.

Снапшоты RADOS для RGW дают несогласованную картину: часть объектов и метаданных может попасть в снимок, часть нет. Для объектного уровня рабочий путь один: multisite sync плюс отдельная выгрузка критичных бакетов через Restic в immutable-хранилище.

Снапшоты ZFS в TrueNAS: быстрый откат и репликация на второй сервер

Снапшот ZFS создаётся мгновенно и не копирует блоки: он фиксирует их состояние на момент снятия. Занимает он немного, пока данные не меняются, поэтому ежечасные снимки для библиотеки изображений стоят копейки рядом с полной копией.

Настройка периодических снапшотов и политики хранения

Рабочая политика для медиаданных: ежечасные снапшоты с хранением 24 часов, ежедневные 30 дней, еженедельные 12 недель. В TrueNAS это настраивается в Data Protection > Periodic Snapshot Tasks, где указывают датасет, рекурсивность, расписание и срок хранения.

zfs snapshot pool/images@auto-2026-09-11-0300
zfs list -t snapshot -o name,used,creation -r pool/images

Снапшоты не заменяют бэкап: при потере пула исчезают и данные, и снимки. Зато они закрывают случайное удаление и неудачное обновление каталога за секунды. Следите за заполнением пула: снапшоты удерживают блоки, изменённые после снятия, и при 90% занятости новые записи начинают упираться в отсутствие места. Алерт на 80% даёт время разобраться без остановки сервиса.

Репликация снапшотов на удалённый сервер TrueNAS

Для отправки копий на второй сервер в TrueNAS создают Replication Task: указывают источник, приёмник, расписание и политику удержания, при необходимости включают шифрование и рекурсивную передачу. Перед этим настраивают SSH-ключи между машинами. Второй сервер может стоять в другой стойке, другом здании или у другого провайдера, и это уже полноценная вторая копия.

Ручной вариант ничем не отличается по механике:

zfs snapshot pool/images@snap1
zfs send -R pool/images@snap1 | ssh backup@nas2 zfs recv pool/images-backup
zfs snapshot pool/images@snap2
zfs send -i pool/images@snap1 pool/images@snap2 | ssh backup@nas2 zfs recv pool/images-backup

Флаг -R передаёт датасет со всеми потомками, -i отправляет только разницу между двумя снапшотами. Для шифрованных датасетов добавляют -w, чтобы данные не расшифровывались на промежуточной машине. Сжатие канала смысла не имеет: JPEG и WebP уже сжаты, выигрыш будет в пределах пары процентов, а процессор займётся впустую. Первая передача десятков терабайт по WAN идёт часами и сутками, поэтому пропускную способность и задержку стоит измерить заранее. Пошаговая логика с проверкой каждой стадии разобрана в руководстве по репликации в TrueNAS, а альтернативные схемы с rsync и облаком собраны в сравнении методов бэкапа в TrueNAS.

Инкрементальные бэкапы Restic и Borg: сравнение и практическая настройка

Оба инструмента дедуплицируют данные на уровне блоков, шифруют их на клиенте и хранят снапшоты с независимым сроком жизни. Разница в транспорте и модели чанков. Restic режет поток на блоки переменной длины (content-defined chunking), поэтому переживает сдвиги данных внутри файлов, и работает с S3, SFTP, локальными каталогами и REST-сервером. Borg использует блоки фиксированного размера и требует локальный репозиторий или доступ по SSH через borg serve.

Для медиахранилища в облаке это решающее отличие: Restic пишет напрямую в S3-совместимое хранилище, Borg такой возможности не даёт. Зато Borg быстрее на локальных репозиториях и лучше экономит место на однотипных данных.

Restic: настройка репозитория и расписания бэкапов

export AWS_ACCESS_KEY_ID=...
export AWS_SECRET_ACCESS_KEY=...
export RESTIC_PASSWORD_FILE=/etc/restic/pass
restic init --repo s3:https://s3.example.com/images-backup
restic -r s3:https://s3.example.com/images-backup backup /mnt/images --exclude '*.tmp' --exclude-caches --tag daily
restic snapshots
restic forget --keep-daily 7 --keep-weekly 4 --keep-monthly 6 --prune

Пароль репозитория держат в файле с правами 600, а не в переменной окружения командной строки: переменные видны в списке процессов. Расписание оформляют через cron или systemd timer, ограничивая полосу флагом --limit-upload, если ночная копия конкурирует с трафиком отдачи картинок. Для репозиториев на миллионы мелких файлов в свежих версиях увеличивают размер пакетов через -o pack-size=64, это заметно ускоряет и бэкап, и проверки. Prune переписывает пакеты и грузит диски, поэтому его запускают реже бэкапа, например раз в неделю, и ограничивают объём перепаковки флагом --max-repack-size.

Borg: создание репозитория и инкрементальные бэкапы

borg init --encryption=repokey-blake2 /mnt/backup/borg
borg create --stats --progress --compression zstd,3 /mnt/backup/borg::images-2026-09-11 /mnt/images
borg list /mnt/backup/borg
borg prune --keep-daily 7 --keep-weekly 4 --keep-monthly 6 /mnt/backup/borg
borg compact /mnt/backup/borg

Команда borg compact возвращает место после prune, без неё репозиторий остаётся раздутым. Для offsite-копии репозиторий держат на удалённом сервере и подключаются к нему по SSH, ключ ограничивают командой borg serve --append-only, чтобы клиент не мог удалить архивы. Сжатие zstd на JPEG даёт считаные проценты выигрыша, основной эффект приносит дедупликация: каждая уникальная картинка хранится один раз, даже если лежит в трёх папках.

Проверка целостности копий и тестовое восстановление

Копия, из которой ни разу не восстанавливали данные, считается несуществующей. Проверки делят на два уровня: быстрые (структура индексов, наличие чанков) и полные (пересчёт контрольных сумм по всем данным).

restic check
restic check --read-data-subset=1/7
borg check
borg check --verify-data
zfs scrub pool/images
mc admin heal -r minio-a

Полный restic check --read-data скачивает весь репозиторий, для 50 ТБ это сутки и больше. Компромисс: ежедневно проверять одну седьмую часть через --read-data-subset=1/7, за неделю репозиторий проходит проверку целиком без пиковой нагрузки. В ZFS контрольные суммы считаются при каждой записи, поэтому scrub раз в месяц ловит деградацию дисков, а не только повреждение файлов. В MinIO команда mc admin heal -r восстанавливает объекты по erasure-кодам, а режим глубокого сканирования проверяет все блоки, а не только метаданные.

Автоматизация проверок и мониторинг

Проверку запускают по расписанию, результат складывают в лог, а на ошибку отправляют уведомление. Скрипт из шести строк: запустить restic check, сохранить вывод в /var/log/restic-check.log, при ненулевом коде возврата отправить curl-запрос в вебхук мессенджера с текстом ошибки. В systemd это оформляют таймером с OnCalendar=Sun 04:00 и RandomizedDelaySec=30m, чтобы проверка не совпала с утренним пиком.

Мониторить стоит четыре вещи: дату последнего успешного бэкапа, дату последней успешной проверки, размер репозитория и отставание репликации. Алерт на отсутствие снапшота старше 25 часов ловит сломанное расписание, которое иначе остаётся незамеченным месяцами.

Тестовое восстановление: сценарии и чек-лист

Порядок ежемесячной проверки:

  1. Выбрать случайные 20-50 файлов из разных коллекций, включая свежие и старые.
  2. Восстановить их в отдельный каталог или бакет, не затрагивая продакшн.
  3. Сравнить sha256sum восстановленных файлов с оригиналами, а также размеры и даты.
  4. Проверить метаданные: EXIF, превью, записи в каталоге для восстановленных объектов.
  5. Зафиксировать время от начала восстановления до готовности: это реальный RTO, а не оценка из документа.

Для объектного хранилища выборку копируют командой mc cp --recursive в отдельный тестовый бакет. Журнал проверок с датами, объёмом и результатом стоит вести: он показывает, что регламент выполняется, и помогает разбирать инциденты.

Восстановление после сбоев: пошаговые сценарии

Три сценария закрывают большинство аварий в медиахранилище. Для каждого заранее известны источник копии, порядок действий и целевые показатели потери и времени восстановления.

СценарийИсточникRPORTO
Отказ узла или площадкиРеплика MinIO или зона Cephсекунды, реже минуты10-30 минут
Случайное удалениеСнапшот ZFS, Restic, Borgдо 1 часа15 минут - 2 часа
Повреждение или шифровальщикOffsite-копия с Object Lockдо 24 часовчасы - сутки

Восстановление из снапшота ZFS

Самый быстрый путь: данные видны в скрытом каталоге .zfs/snapshot внутри датасета, и их можно скопировать без отката всего пула.

ls /pool/images/.zfs/snapshot/
cp -a /pool/images/.zfs/snapshot/auto-2026-09-11-0300/2026/09/ /mnt/restore/
zfs clone pool/images@auto-2026-09-11-0300 pool/images-restore

Команда zfs rollback возвращает датасет к состоянию снимка и уничтожает все изменения после него, поэтому для точечного восстановления её применяют редко. Клон датасета даёт отдельную копию, с которой можно работать без риска. В TrueNAS те же действия доступны из интерфейса в разделе Datasets.

Восстановление из Restic и Borg

restic restore latest --target /restore --include /mnt/images/2026/09
borg extract /mnt/backup/borg::images-2026-09-11 mnt/images/2026/09/photo.webp

Restic восстанавливает по префиксу пути, Borg принимает пути без ведущего слэша. Перед переключением трафика на восстановленные данные проверяют контрольные суммы и каталог: восстановленные файлы должны совпасть с записями базы. Полный порядок действий при потере сервера, включая проверку реплик и переключение сервисов, описан в плане аварийного восстановления TrueNAS.

Runbook на одну страницу экономит часы в момент аварии: где лежат ключи и пароли репозиториев, какой бакет immutable, кто принимает решение о переключении, в каком порядке поднимать сервисы. Без него восстановление превращается в поиск пароля от репозитория под давлением.

Типовые ошибки при бэкапе больших объёмов изображений и как их избежать

  1. Ежедневный полный бэкап. Для 50 ТБ это 1,5 ПБ в месяц и постоянная загрузка канала. Решение: недельный полный плюс ежедневные инкременты.
  2. Отсутствие мониторинга. Задание может падать неделями, пока места на диске хватает. Решение: алерт на отсутствие успешного запуска за 25 часов.
  3. Все копии в одном месте. Один массив, одна стойка, один аккаунт провайдера означают общую точку отказа. Решение: offsite-копия в другом регионе с Object Lock.
  4. Непроверенные бэкапы. Восстановление падает из-за забытого пароля или битых чанков. Решение: ежемесячное тестовое восстановление со сверкой хэшей.
  5. Игнорирование retention. Репозиторий растёт, prune не запускается, место кончается. Решение: политика forget и prune плюс контроль размера репозитория.
  6. Один репозиторий на всю библиотеку. Восстановление одного файла требует загрузки индекса в десятки гигабайт. Решение: делить по годам или коллекциям.
  7. Открытые offsite-копии. Картинки уезжают в чужое облако без шифрования. Решение: клиентское шифрование до отправки.
  8. Единый пароль для продакшена и бэкапа, который знает один человек. Решение: менеджер секретов и резервная копия ключей в сейфе.

Стратегию пересматривают раз в год и после каждого крупного изменения инфраструктуры: объём библиотеки растёт, цены на хранилище меняются, появляются новые версии инструментов.

Как выбрать инструмент под задачу: сравнение MinIO, Ceph, ZFS, Restic и Borg

Инструменты решают разные задачи, поэтому их редко выбирают по принципу одно вместо другого. Хранилище отдаёт данные, репликация ускоряет восстановление, бэкап защищает от логических ошибок.

ИнструментТипРепликацияИнкременты и дедупликацияСложностьКогда выбирать
MinIOОбъектное, S3Бакетная и сайтоваяВерсионирование, правила ILMНизкаяS3-хранилище на десятки и сотни терабайт
Ceph RGWОбъектное, блочное, файловоеMultisite по зонамВерсионирование, Object LockВысокаяПетабайты, одна платформа для ВМ и объектов
ZFS и TrueNASФайловое, блочноеzfs send и recv, Replication TaskСнапшоты, удержание по расписаниюНизкая и средняяЛокальное и гибридное хранилище, нужен мгновенный откат
ResticКлиент бэкапаНетCDC-дедупликация, шифрованиеНизкаяOffsite в S3, миллионы мелких файлов
BorgКлиент бэкапаНетБлочная дедупликация, compactСредняяЛокальный или SSH-репозиторий, максимальная экономия места

Практичные связки: облачное хранилище изображений на MinIO или Ceph с репликой в другой зоне плюс Restic в immutable-бакет; локальный NAS на TrueNAS со снапшотами и zfs send плюс Borg на второй сервер; гибрид, где снапшоты закрывают быстрые откаты, а Restic отвечает за offsite. Логика защиты данных в хранилищах с миллионами мелких объектов разобрана в материале про резервное копирование хранилища артефактов: те же принципы immutability, дедупликации и проверки восстановления.

Начните с замера: сколько гигабайт данных меняется за сутки в вашей библиотеке изображений. Эта цифра определяет размер инкремента, частоту полного копирования и требуемую полосу канала, а значит и всю остальную схему.

Поделиться:
Сохранить гайд? В закладки браузера