ПО «Береста» – отечественный флагман в мире систем резервного копирования и восстановления данных (РКиВД) корпоративного уровня. Мы активно развиваемся и уже работаем во многих высоконагруженных инфраструктурах. Однако наши заказчики всё чаще сталкиваются с вызовом: им нужна единая платформа для бэкапа самых разных типов данных – от файловых массивов и СУБД до облачных сервисов и Kubernetes-приложений. Сегодня один из самых востребованных и перспективных источников — это приложения и сервисы на базе Kubernetes.
Проблема в том, что альтернативные решения либо не соответствуют требованиям безопасности, либо предлагают отдельные «островные» решения, никак не связанные с общей экосистемой РКиВД, либо в целом не имеют поддержки сред контейнеризации. Для решения этой задачи мы интегрируем в Бересту функционал для резервного копирования и восстановления систем, развернутых на базе Kubernetes.
В этой статье расскажем, как устроена эта интеграция: от создания источника данных и обнаружения подов до процесса бэкапа и восстановления.
Создание источника данных и обнаружение подов

Система резервного копирования и восстановления источников данных типа K8S, выглядит следующим образом: сначала создается источник данных, сейчас он находится в разделе «Источники данных» — «Безагентские» — тип K8S.
После создания источник появляется в списке доступных безагентских источников.

Далее выполняется обнаружение (discover) целей резервного копирования – подов (и связанных с ними сущностей) – либо по команде пользователя, либо по расписанию. Результат сканирования – список всех доступных подов со следующей информацией: узел (нода), на котором находится под; статус пода; суммарный объём выделенного хранилища (если PV несколько, объём суммируется) и служебные настройки Бересты: тенанты, целевые хранилища, настройки сроков хранения и т.д.

На данный момент система такова, что она выводит все доступные поды в статусе «Running» из всех доступных namespace. Из особенностей: объём хранилища для пода определяется на основе выделенных PersistentVolume. Фактически занятый объем считается только в процессе бэкапа, когда данные реально записываются на удалённое хранилище.
Резервное копирование (Backup)
Когда пользователь выбирает под для резервного копирования и тип бэкапа, система запускает следующий алгоритм:
1) Выполняются служебные проверки;
2) Определяются ресурсы, которые будут бэкапиться;
3) Запускается процедура резервного копирования.
Под капотом мы используем open source решение – Velero, оборачивая его в собственную оболочку для управления в составе общего продукта. Нопрежде чем запускаться, мы производим ряд проверок состояния системы на текущей ноде:
1) Существует и работает ли Node Agent?
2) Задан и находится ли в активном статусе BackupStorageLocation?
3) Поддерживается ли CSI Driver для конкретного типа хранилища?
4) Выданы ли необходимые права доступа для Velero в соответствии с PSS?
5) Настроен ли VolumeSnapshotClass?
После проверок автоматически выбирается стратегия бэкапа. Сейчас их три:
1) CSI + Data Mover. Создаёт атомарный снепшот LVM тома, затем через Velero Data Mover копирует данные в S3 хранилище. Cтратегия применяется, когда StorageClass поддерживает CSI снепшоты. Поддерживаемые CSI provisioner’ы: topolvm.io, ebs.csi.aws.com, disk.csi.azure.com, pd.csi.storage.gke.io, replicated.csi.storage.deckhouse.io;
2) Hooks (для баз данных) – механизм, применяемый, когда по результатам предварительных проверок выяснено, что в данный момент CSI драйвер отсутствует или работает некорректно, или когда PVC использует не CSI StorageClass. Используется, если система определяет, что в поде крутится база данных. Тип СУБД определяется автоматически, после чего выполняется консистентное сохранение состояния, которое затем копируется на хранилище резервных копий;
3) FS-Backup (файловая система) – в большей степени резервный вариант, когда в системе не поддерживаются CSI снепшоты, тип приложения в поде определить не удалось или это не база данных. В этом случае запускается механизм последовательного копирования файлов тома через Velero Node Agent. Данный подход оптимален только для stateless-приложений.
Выбор уровня изоляции: namespace или pod
На данном этапе разработки пользователь выбирает охват ресурсов для резервного копирования.
В идеале, если следовать принципам изоляции, в одном namespace должно находиться одно приложение (или группа связанных микросервисов), но на практике в одном namespace могут работать несколько независимых проектов. Из-за этого требуется бэкапить Workload Resources конкретного пода, а не весь namespace. Такая избирательность оказалась нужна, чтобы излишне не раздувать размеры бэкапа.
Поэтому был предусмотрен выбор уровня изоляции: namespace-scoped (бэкапится весь namespace целиком) или pod-scoped (бэкапятся только ресурсы, относящиеся к конкретному поду).

Как это работает?
В первом варианте стандартно делается снепшот всего namespace, во втором – идет более точечная работа, анализируются отдельные манифесты, метки (labels) (если разработчик позаботился о разметке), spec и т.д. Затем ресурсы помечаются специальной меткой для явного выделения системе РК и затем запускается backup create с селектором.
Согласно архитектуре Бересты, процесс бэкапа попадает в список заданий, пользователь отслеживает процесс, логи, скорость и т.д.



По завершении бэкап отображается в каталоге резервных копий.

Восстановление (Restore)
Процесс восстановления из резервной копии несколько сложнее, чем бэкап. Главная задача: не сломать то, что работает.
Когда пользователь запускает восстановление, система проверяет бэкап на наличие конфликтов с текущей конфигурацией.


Если при ресторе пользователь указал новое namespace и такого namespace на ноде нет, конфликтов не возникает – ресурсы разворачиваются в чистом пространстве. Если же новое пространство указано не было, то namespace берется из данных resource list бэкапа, и, если в системе такое имя уже есть, запускается второй этап проверок – проверок содержимого namespace.
Для pod-scoped при обнаружении конфликтов процесс останавливается с указанием ресурсов, которые требуется удалить вручную.


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



Резервное копирование и восстановление для Kubernetes в Бересте на данный момент находятся в стадии активной доработки и расширения функционала.
В ближайших планах:
1) Межкластерное восстановление – возможность восстановить бэкап с одного Kubernetes-кластера на другой. Это особенно актуально для сценариев аварийного переключения (DR) и миграции между средами (dev — staging — production).
2) Бэкап всего кластера, включая etcd – сейчас мы бэкапим прикладные ресурсы (поды, сервисы, PVC), но чтобы полностью восстановить кластер «с нуля», нужны данные etcd. Мы изучаем потребность резервирования данного типа данных в реальных сценариях.
3) Принудительное восстановление с перезаписью (force) – сегодня мы останавливаем восстановление при конфликтах, чтобы не сломать работающие приложения. Однако в некоторых сценариях (например, при развороте стенда или откате на продакшене) требуется безусловная перезапись ресурсов. Такой режим появится в следующих версиях.
Мы открыты к обратной связи и предложениям. Если Вы используете Kubernetes в своих проектах и сталкиваетесь с задачами резервного копирования – опишите кейсы, которые Вы хотели бы видеть в Бересте. Ваши идеи помогут нам сделать продукт ещё лучше.
ссылка на оригинал статьи https://habr.com/ru/articles/1065998/