Проверки перед восстановлением#

Перед восстановлением в производственной среде выполните следующие проверки. Большинство пунктов относится к обоим сценариям восстановления; отдельно отмечены пункты для ручной процедуры и оффлайн-экземпляров платформы.

Общие проверки#

Выполните следующие проверки:

  • Синхронизация времени на узлах кластера (обязательно). На всех узлах должна работать служба NTP (chrony). Вывод timedatectl содержит System clock synchronized: yes. Взаимное расхождение часов узлов составляет миллисекунды (chronyc tracking). Реестр Private Automation Hub выдает токены JWT с проверкой сроков действия без допуска. Если часы узла, выпустившего токен, опережают часы проверяющего узла хотя бы на доли секунды, периодически возникают ошибки 401 The provided Bearer token is invalid у задания импорта контента, а также при podman login / push / pull через реестр с несколькими репликами API. Без NTP дрейф накапливается и со временем делает ошибки массовыми. Для оффлайн-экземпляров платформы без доступа к публичным серверам NTP сделайте один из узлов локальным источником (local stratum 10 и allow <subnet> в конфигурации chrony), а остальные узлы – его клиентами.

  • Резервная копия создана до разрушительных действий, и каждый из пяти дампов доступен:

    pg_restore --list <component>.db
    

    Здесь:

    • <component>.db – дамп базы данных компонента (aa.db, ac.db, eda.db, pulp.db, dashboard.db).

  • Версия pg_dump в служебном поде не ниже мажорной версии сервера PostgreSQL (см. Резервное копирование).

  • Если компоненты работают с внешней СУБД, используйте ручную процедуру (см. Восстановление при внешней СУБД). Ресурс AstraAutomationRestore не применяется в этом случае.

  • Для ручного восстановления целевым сервером является Astra-PostgreSQL, то есть сервер PostgreSQL из состава Astra Automation (образ registry.astra.ru/aa/postgresql). Команда pg_restore выполняется от имени суперпользователя с параметром --disable-triggers (см. Типичные проблемы ручного восстановления).

  • Новое название узла зарезервировано в DNS и указано в поле hostname ресурса AstraAutomationRestore, секрет с сертификатом для него указан в поле ingress_tls_secret (см. Адрес восстановленного экземпляра).

  • Секреты доступа к репозиториям образов существуют в пространстве имен до создания ресурсов восстановления.

  • Секреты шифрования (db_fields_encryption_secret, secret_key_secret) те же, что у исходного экземпляра платформы. Этими ключами зашифрованы данные в базах. Замена сделает их нечитаемыми.

Ключ шифрования Event-Driven Automation при переносе на новый кластер#

Перед восстановлением на другой кластер дополнительно проверьте секрет ключа шифрования Event-Driven Automation. Значение секрета должно декодироваться как строка UTF-8, то есть не содержать недопустимых для UTF-8 байтов. В кластерах с containerd версии 2.x под Event-Driven Automation с двоичным значением ключа не запускается (CreateContainerError: string field contains invalid UTF-8), даже если на исходном кластере с containerd 1.7.x ошибка не проявлялась.

Диагностика (результат BINARY означает, что значение содержит недопустимые байты и его необходимо заменить):

kubectl -n <ns> get secret eda-encryption-secret -o jsonpath='{.data.secret_key}' \
  | base64 -d | iconv -f utf-8 -t utf-8 >/dev/null 2>&1 && echo OK || echo BINARY

Здесь:

  • <ns> – пространство имен экземпляра платформы.

При результате BINARY замените значение ключа до восстановления. Команды замены изменяют значение секрета, заменяя недопустимые байты символом U+FFFD. Замена является безопасной, так как ключ записывается в той форме, в которой его фактически использует Event-Driven Automation после чтения значения. Перед заменой сохраните прежнее значение секрета:

kubectl -n <ns> get secret eda-encryption-secret \
  -o jsonpath='{.data.secret_key}' > eda-secret-key.bak.b64

Затем замените значение ключа:

NEW_B64=$(kubectl -n <ns> get secret eda-encryption-secret -o jsonpath='{.data.secret_key}' \
  | base64 -d \
  | python3 -c "import sys,base64; print(base64.b64encode(sys.stdin.buffer.read().decode('utf-8','replace').encode()).decode())")
kubectl -n <ns> patch secret eda-encryption-secret --type merge -p "{\"data\":{\"secret_key\":\"$NEW_B64\"}}"
kubectl -n <ns> rollout restart deploy -l "app.kubernetes.io/managed-by=eda-operator,app.kubernetes.io/name=<eda-name>"

Здесь:

  • <eda-name> – название ресурса Event-Driven Automation исходного экземпляра платформы.

Емкость хранилища#

Выполните следующие проверки емкости хранилища:

  • Процедура восстановления создает новый экземпляр PostgreSQL и новые тома PVC (Persistent Volume Claim) компонентов. Проверьте запас емкости у поставщика хранилища. При использовании Longhorn заранее убедитесь, что параметр storage-over-provisioning-percentage не меньше 200, а storage-minimal-available-percentage не больше 10. Иначе новые тома не создаются или не монтируются, и компоненты остаются в состоянии Pending. При использовании драйверов CSI облачных провайдеров проверьте квоту дискового пространства.

  • Емкость тома PVC для копий контента реестра: не меньше, чем (объем контента в каталоге /var/lib/pulp/media/ + размер дампов) × число хранимых копий × 1,1. Размера по умолчанию (5Gi) для реестра с контентом недостаточно уже при двух копиях. Существующий том можно расширить только вручную:

    kubectl -n astra-automation patch pvc <hub-name>-backup-claim -p '{"spec":{"resources":{"requests":{"storage":"20Gi"}}}}'
    

    Здесь:

    • <hub-name> – название ресурса Private Automation Hub.

    Оператор не изменяет существующий том PVC, поэтому после ручного расширения резервное копирование продолжает работать штатно.

Оффлайн-экземпляры платформы#

Для экземпляров платформы без доступа к репозиториям образов (образы предварительно загружены на узлы) выполните следующие проверки:

  • containerd не ниже 1.7: защита предварительно загруженных образов от сборщика мусора kubelet (метка pinned) работает только начиная с containerd 1.7. На более старых версиях образы уязвимы к удалению при заполнении диска; в этом случае строго соблюдайте пункты о свободном месте.

  • Запас диска на узлах. Процесс восстановления создает новые тома. Longhorn размещает реплики в /var/lib/longhorn на корневом диске узлов, то есть там, где containerd хранит десятки гигабайт предварительно загруженных образов. Корневой диск – это диск с корневой файловой системой /. При заполнении диска выше 85% (или нехватке ephemeral-storage) сборщик мусора kubelet удаляет предварительно загруженные образы. Репозиторий такому экземпляру недоступен, и поды переходят в ImagePullBackOff. Первыми удаляются самые крупные «неиспользуемые» образы. Перед восстановлением выполните на каждом узле команду df -h /var/lib/containerd и убедитесь, что занятость не превышает ~70%.

  • Очистите каталог /tmp/images (архивы предварительной загрузки образов, десятки гигабайт на узел), если он остался после установки.

  • Рекомендуемый размер корневого диска узла составляет 120–150 ГБ. Можно также выделить отдельный диск или раздел под /var/lib/longhorn, чтобы данные Longhorn хранились отдельно от containerd.

Хранилище Private Automation Hub#

Подготовьтесь к восстановлению хранилища реестра:

  • Хранилище S3 (storage_type: S3): объекты хранилища (bucket) не входят в резервную копию. Перед восстановлением скопируйте bucket исходного экземпляра платформы в отдельный новый bucket (aws s3 sync или rclone sync) и укажите его в секрете S3 нового экземпляра платформы.

    Предупреждение

    Нельзя указывать один и тот же bucket двум работающим экземплярам Private Automation Hub. Задача очистки «осиротевших» файлов любого из них удаляет из bucket файлы, отсутствующие в его собственной базе данных. Тем самым она уничтожает контент второго экземпляра. Общий bucket допускается, только если исходный экземпляр платформы остановлен и выводится из эксплуатации.

  • Файловое хранилище (storage_type: File): после восстановления проверьте, что файлы контента восстановлены. Количество файлов в каталоге /var/lib/pulp/media/artifact/ (в поде API Private Automation Hub) должно соответствовать результату запроса SELECT count(*) FROM core_artifact; в базе данных Private Automation Hub. Расхождение означает, что контент не восстановлен; ручной перенос контента описан в инструкции.

Ресурсы кластера#

Процедура восстановления развертывает полную вторую копию платформы, а не облегченный снимок. Восстановленный экземпляр платформы состоит примерно из 22 подов (шлюз, Automation Controller, Private Automation Hub, Event-Driven Automation, внутренняя PostgreSQL, Redis) с суммарными запросами памяти около 9 ГБ. При использовании компонента Automation Dashboard (панель аналитики) количество подов возрастает примерно до 25 (добавляются Automation Dashboard, его Redis и, при использовании внутренней базы данных, собственный PostgreSQL). Фактическое потребление будет выше запрошенного. Предусмотрите под восстановленный экземпляр платформы запас, сопоставимый с реальным потреблением исходного.

Из этого вытекают следующие практические следствия:

  • кластер, рассчитанный на один экземпляр платформы, может не вместить второй, и поды останутся в состоянии Pending или начнется вытеснение подов;

  • восстановленный экземпляр платформы временный, поэтому удалите его сразу после проверки (см. Удаление восстановленной платформы), не накапливайте копии;

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

Проверки после восстановления#

После восстановления платформы выполните следующие проверки:

  • Выполнена изоляция ресурсов. Для экземпляров платформы с внешними узлами плоскости исполнения внешние узлы отключены до запуска пробного задания.

  • Вход под пользователем admin работает. Присутствуют пользователи, организации, проекты, шаблоны заданий и инвентарные списки (последние первыми теряют данные из-за нарушений внешних ключей при ручном восстановлении).

  • Пробное задание выполняется успешно в контейнерной группе кластера (default).

  • Поды Automation Dashboard и (при использовании внутренней базы данных) его PostgreSQL запущены. Интерфейс Automation Dashboard открывается по адресу из поля public_base_url восстановленного экземпляра платформы. Выделенное название узла Automation Dashboard при восстановлении сброшено; при необходимости задайте новое (см. Запись кластера в базе данных Automation Dashboard).

  • Синхронизация активна только у записи Cluster восстановленного кластера (запись экземпляра платформы в базе данных Automation Dashboard); запись исходного экземпляра платформы отключена или удалена (см. Запись кластера в базе данных Automation Dashboard).

  • Если компоненты завершаются ошибкой relation ... already exists, синхронизируйте состояние миграций и перезапустите поды (см. Рассинхронизация состояния миграций).