В первой части мы рассмотрели подходы к созданию резервных копий контейнеров в кластере Kubernetes с использованием restic над каталогом данных и относительно новых возможностей CSI для создания и восстановления мгновенных снимков. Пришло время поговорить о возможностях автоматизации управления резервными копиями, о мониторинге процесса и иных важных DevOps-задачах. Прежде всего для автоматизации нужно решить вопрос с доступом к данным и исключить необходимость установки дополнительных приложений (например. restic) на управляющий узел. В основном сценарии развертывания сервисы предполагается, что мы используем возможности Kubernetes по выделению емкости системы хранения через PersistentVoIumeClaim с режимом доступа ReadWriteOnce, который допускает монтирование раздела для записи только на один контейнер, что затрудняет восстановление данных из резервной копии. Также для создания резервной копии было бы желательно, чтобы доступ к данным был также у специального контейнера, содержащего все необходимые инструменты (например, Restic). Попробуем разобраться как это может быть реализовано и поговорим о концепции sidecar-контейнеров. Прежде всего посмотрим на конфигурацию развертывания контейнера (может быть Deployment, DaemonSet или StatefulSet) и обнаружим, что в спецификации шаблона развертывания определение контейнеров перечисляется в списке containers. Такая схема определения позволяет запускать несколько контейнеров внутри одного Pod и все контейнеры будут разделять общий набор PersistentVolumeClaim и иметь доступ к опубликованным сетевым сервисам через localhost (все контейнеры в Pod разделяют общий  ip-адрес). Таким образом можно добавить дополнительный контейнер с restic в развертывание и примонтировать к нему именованный раздел (в соответствии с названием в volumes или volumeClaimTemplates) и использовать его для получением доступа на чтение к данным из хранилища основного контейнера. Такой подход получил название "sideсаг-контейнер" и позволяет расширить функциональность основного контейнера без влияния на его доступность и конфигурацию. Так, мы можем добавить запуск образа контейнера, содержащего restic и подключить раздел с данными дополнительно к нему. Основная проблема состоит в том, что контейнер из образа restic/restic указывает точку входа в консольную утилиту restic и будет непрерывно перезапускаться. Чтобы этого избежать, можно поменять точку входа и отметить, что контейнер должен выполниться в режиме ожидания и мы в дальнейшем сможем подключиться к нему через kubectl ехес и выполнить команду restic backup когда наступит время для создания резервной копии. Также необходимо примонтировать раздел для хранения данных restic из системы хранения к соответствующему контейнеру, а также передать пароль для шифрования резервной копии через переменные окружения контейнера (может быть получен из Secret). После применения конфигурации можно обнаружить, что теперь Pod запущен с двумя контейнерами: И теперь мы можем выполнить инициализацию каталога для управления резервными копиями (однократно) и создать мгновенный снимок данных с использованием sidecar-контейнера restic: Для восстановления можно указать в target непосредственно каталог, куда примонтирован раздел оригинального контейнера (для sidecar ограничений на запись нет, поскольку все контейнеры разделяют единый PVC-раздел): Для создания снимка (как и в первой части статьи) лучше, разумеется, использовать собственные инструменты исходного сервиса (например, pg_dump) и это также может быть предусмотрено в sidecar-контейнере. Образ для выгрузки состояния сервиса и восстановления может быть создан самостоятельно, например для PostgreSQL Dockerfile может выглядеть следующим образом: Созданный контейнер также может быть добавлен как sidecar к основному процессу PostgreSQL и предусматривает инициализацию репозитория (kubectl exec -it -n postgres postgres-0 -c restic /opt/init.sh), создание резервной копии из дампа базы (kubectl exec -it -n postgres postgres-0 -c restic /opt/backup.sh) и восстановление из последнего доступного дампа из репозитория (kubectl exec -it -n postgres postgres-0 -c restic /opt/restore.sh). Аналогично могут быть созданы контейнеры для других сервисов, либо можно воспользоваться существующими на Docker Hub: PostgreSQL   MySQL   MariaDB  MongoDB  Основной недостаток рассмотренного выше решения - необходимость ручного изменения конфигурации развертывания сервисов, запуска сценариев создания резервной копии и восстановления, подключения дополнительных контейнеров с монтированием PersistentVolumeClaim к соответствующим каталогам, где ожидается получить данные в сценарии резервного копирования. Можно ли как-то автоматизировать этот процесс? Да, и в этом нам поможет Dynamic Admission Control (а именно использование Mutating Webhooks). Регистрация ресурсов ValidatingWebhooks (admissionregistration.k8s.io/v1/ValidatingWebhookConfiguration) и MutatingWebhooks (admissionregistration.k8s.io/v1/MutatingWebhookConfiguration) позволяют добавить дополнительную обработку при создании/изменении/удалению ресурсов (например, Deployment) и добавляют возможности для дополнительных проверок конфигурации (при валидации) или изменения создаваемого ресурса "на лету" (при мутации). Конфигурация мутации определяет адрес API для вызова при возникновении подходящих условий и набор правил (rules), описывающих на какие группы и версии API применяется правило (apiGroups, apiVersions), какие операции отслеживаются (например, CREATE, UPDATE), какие типы ресурсов будут наблюдаться (resources). Часто установка вебхуков выполняется при установке операторов - контейнеров, самостоятельно управляющих ресурсами для развертывания управляемого сервиса и регистрирующих точки подключения к службам, а также дополнительные версии API и типы ресурсов (используется механизмы CRD - Custom Resource Definition). Кроме возможностей встраивания дополнительных действий в процесс развертывания ресурсов такой подход позволяет создавать предметно-специфические типы и метаданные для ресурсов (например, для описания расписания резервного копирования).  Рассмотрим несколько операторов, представляющих возможности для управления резервным копированием: Продукт с открытым исходным кодом (ранее назывался Haptio Ark), позволяет выполнять резервное копирование ресурсов кластера Kubernetes и управлять резервными копиями PersistentVolume через утилиту командной строки velero. Для настройки процесса копирования (например, добавления pre- и post-сценариев для подготовки и очистки дампов) используются аннотации в метаданных развертывания. Поддерживаются также возможности CSI Snapshotting.  Для создания резервной копии используется restic и внешние хранилища, которые могут быть подключены через плагины. Создание резервной копии выполняется командой velero backup. velero backup create postgres --ordered-resources 'statefulsets=postgres/postgres' --include-namespaces=postgres Также можно запланировать резервное копирование по расписанию: velero schedule create postgres --schedule="* * * * *"  Расписание задается в синтаксисе Cron (минуты часы день месяц день_недели). Оператор для управления ресурсами резервного копирования. Позволяет работать с PV-разделами с типом доступа ReadWriteMany.  Установка может быть выполнена через helm: После установки регистрируется версия API k8up.io/v1 и дополнительные ресурсы: Backup - задает конфигурацию репозитория для restic PreBackupPod - описание sidecar-контейнера и команды для запуска для подготовки дампа системы (также может быть задано в аннотации k8up.io/backupcommand  у любого развертывания). Schedule - определить расписание резервного копирования (в синтаксисе Cron). Archive - создание холодной копии restic-репозитория для долговременного хранения. Оператор использует механизмы Mutating Webhooks для установки sidecar-контейнеров с поддержкой restic в существующие/новые/изменяемые развертывания. Stash позволяет настраивать резервное копирование для PVC-разделов с режимом доступа ReadWriteOnce, поскольку управляющий контейнер добавляется к существующим подам и разделяет с ними общий доступ к хранилищам и ip-адрес.  Файл opensource лицензии запрашивается на сайте проекта. После установки регистрируется новая версия API stash.appscode.com/v1alpha1 и stash.appscode.com/v1beta1  и дополнительные ресурсы: Repository - описание расположения репозитория для Restic (может быть один на все развертывания или отдельный под каждое из них), поддерживается S3, Google Cloud Storage, Microsoft Azure Storage, а также REST для отправки в произвольный веб-ресурс. Snapshot  - обертка вокруг возможностей управления снимками Kubernetes. BackupConfiguration - конфигурация резервного копирования (также может включать в себя hooks для подготовки данных и их очистки после завершения процесса). BackupBlueprint - создание шаблона для описания резервного копирования, на него можно ссылаться в развертываниях через аннотации: stash.appscode.com/backup-blueprint - название шаблона;  stash.appscode.com/schedule - расписание резервного копирования. Function - шаг подготовки резервной копии, может включать в себя создание дампа базы данных или иные операции, необходимые для создания согласованной выгрузки. Функция определяется со ссылкой на образ sidecar-контейнера (для PostgreSQL можно использовать stashed/postgres-stash) и командную строку для запуска действия. Также функция может использоваться для отправки метрик по резервному копированию в Prometheus (образ appscode/stash:0.10.0, команда update-status). При описании аргументов команды можно использовать переменные окружения, предоставленные Stash (в том числе, информация о расположении ресурса). Task - объединение последовательности функций (перечисляются как step) с параметрами. Task может быть указан для исполнения в описании конфигурации BackupConfiguration или BackupBlueprint. RestoreSession - выполнение восстановления из указанного репозитория в каталог (обычно связывается с PVC по имени, в соответствии с названием в volumes/persistentVolumeClaims развертывании). Пример конфигурации для настройки резервного копирования базы данных: При выполнении резервной копии создается ресурс BackupSession, из которого можно получить информацию о состоянии. При успешном применении можно увидеть, что к развертыванию, которое указано в .spec.target.ref присоединяется sidecar-контейнер stashed/stash с запуском команды run-backup. По умолчанию доступны 3 функции: update-status (отправка метрик в Prometheus), pvc-backup (сохранение данных из автономного Read-Write-Many PVC), pvc-restore (восстановление в автономный PVC). Для создания своей функции можно реализовать образ контейнера с точкой входа для создания дампа базы данных и отправки в restic-репозиторий, для настройки можно использовать переменные окружения: REPOSITORY_PROVIDER  - провайдер для репозитория (например, S3); REPOSITORY_BUCKET - название S3 Bucket; REPOSITORY_ENDPOINT - адрес для подключения к S3 (или другому хранилищу); REPOSITORY_PREFIX  - префикс пути в репозитории; REPOSITORY_SECRET_NAME  - название секрета, содержащего пароль к репозиторию; REPOSITORY_SECRET_NAMESPACE  - пространство имен, где хранится секрет репозитория; RETENTION_KEEP_LAST  - количество резервных копий для сохранения и ротации. Пример определения функции можно посмотреть здесь. Далее полученная функция интегрируется в задачу: И далее задача может быть добавлена к конфигурации резервного копирования: Оператор Stash поддерживает присоединение sidecar-контейнеров к DaemonSet (добавляется к каждому запущенному Pod на всех допустимых узлах), StatefulSet (развертывание пересоздается с подключением дополнительного контейнера для каждой реплики сервиса), Deployment (дополнительный контейнер добавляется к существующему развертыванию без перезапуска).  Итак мы рассмотрели различные подходы к управлению резервным копированием, включая автоматическое управление через CRD-ресурсы в операторах Stash и k8up. Сейчас нет общепринятого решения для управления резервными копиями и появляется большое количество инструментов, основанных на CSI Snapshotting (например, Gemini или TrilioVault), но мы рассмотрели наиболее популярные и функциональные продукты, которые могут помочь вам настроить предсказуемое и надежное резервное копирование и избавить от переживаний о возможной потере данных. Так;е хочу напомнить о том, что уже 2 июня мои коллеги из OTUS проведут бесплатный урок по теме: "Контроллеры репликации, сеты репликации и балансировка нагрузки". Регистрация на урок доступна по ссылке ниже. Зарегистрироваться на бесплатный урок.  Flutter Developer@YandexPro, DevOps, IT Architect