Восстановление при внешней СУБД#
Восстановление платформы, базы данных которой размещены во внешней СУБД PostgreSQL вне кластера, имеет несколько особенностей.
Признаком такой конфигурации является то, что секрет конфигурации базы данных шлюза платформы содержит type: unmanaged и адрес внешнего сервера.
Примечание
При внутренней PostgreSQL секреты дочерних компонентов тоже могут содержать type: unmanaged, но признаком внешней СУБД это не является.
Ориентируйтесь на секрет шлюза платформы и фактическое расположение сервера баз данных.
Предупреждение
Для платформы с внешней СУБД ресурс AstraAutomationRestore применять нельзя.
Секреты восстанавливаются с использованием адресов исходных баз данных.
Восстановление командой pg_restore --clean выполняется прямо в базы данных работающего исходного экземпляра платформы с удалением существующих данных.
Поэтому используйте приведенную здесь ручную процедуру.
Отличия от восстановления при внутренней PostgreSQL#
Автоматическое восстановление рассчитано на применение внутренней СУБД PostgreSQL, которой управляет оператор. При использовании внешней СУБД имеются следующие особенности:
Подмена адресов баз данных в восстановленных секретах выполняется только для внутренней PostgreSQL. Секреты, указывающие на внешнюю СУБД, сохраняют адрес исходных баз данных. Оператор не может направить восстановление в другое расположение. Восстановление дампа разрушило бы данные исходного экземпляра платформы.
Оператор не создает ресурсы во внешней СУБД, то есть новый сервер, базы данных, роли и привилегии готовятся вручную.
Дампы содержат специфику PostgreSQL из состава Astra Automation (образ
registry.astra.ru/aa/postgresql; далее – Astra-PostgreSQL): параметр таблицWITH (MACS=FALSE)и команды мандатного контроля доступаMAC LABEL/MAC CCR. Они корректно применяются только в Astra-PostgreSQL, а привилегированные команды выполняются только от имени суперпользователя (см. Типичные проблемы ручного восстановления).После переноса базы данных между экземплярами состояние миграций приложений (таблица
django_migrations, миграцииpulpcore) теряет синхронизацию и требует восстановления синхронизации вручную.
Резервное копирование#
Резервное копирование при внешней СУБД не отличается от обычного (см. Создание резервной копии).
pg_dump подключается по адресу и порту, содержащимся в секрете конфигурации базы данных независимо от значения type.
Служебный под запускается на узле кластера и записывает дамп в том PVC (Persistent Volume Claim).
Должны выполняться следующие условия:
Версия клиента
pg_dumpв служебном поде должна быть не ниже мажорной версии сервера PostgreSQL. Образ служебного пода задается полямиpostgres_image/postgres_image_version(см. Справочник ресурсов резервного копирования). Несовпадение версий приводит к ошибкеpg_dump: error: aborting because of server version mismatch.Узлы кластера должны иметь сетевой доступ к адресу и порту внешней СУБД. Правила межсетевых экранов или групп безопасности должны разрешать подключения из сети кластера.
Ручное восстановление#
Дампы необходимо применять к новому серверу PostgreSQL с новыми базами данных и ролями.
Затем создаются собственные секреты конфигурации баз данных и новый ресурс AstraAutomation, ссылающийся на них.
Ресурс AstraAutomationRestore не используется.
Целью восстановления может быть и внешний сервер.
pg_restore подключается по сети.
Вместо сервера, развернутого в кластере Kubernetes, как в примерах ниже, подходит любой достижимый экземпляр PostgreSQL.
Необходимо, чтобы это была новая база данных, а не та, из которой создавалась копия.
Для внешней целевой СУБД должны выполняться следующие условия:
целевые базы данных, роли и привилегии создаются вручную, так как оператор внешние ресурсы не создает;
на целевом сервере необходим суперпользователь, так как параметр
--disable-triggersи командыMAC LABEL/MAC CCRвыполняются только от его имени;сервер должен поддерживать параметр таблиц
WITH (MACS=FALSE), то есть быть Astra-PostgreSQL; для другого сервера потребуется преобразование дампа (см. Параметр WITH (MACS=FALSE) на сервере без поддержки мандатного контроля).
Примечание
В управляемых облачных сервисах СУБД полноценного суперпользователя обычно нет, поэтому --disable-triggers и команды мандатного контроля там не выполнятся.
В этом случае восстанавливайте в экземпляр Astra-PostgreSQL с административной ролью.
Подходит, например, экземпляр, развернутый в кластере Kubernetes, как в примерах ниже.
Для собственных серверов, где доступна роль postgres, ограничений нет.
Шаг 1. Подготовка целевого сервера#
В примере целевой сервер развертывается в кластере из образа Astra-PostgreSQL. Для внешней цели те же действия выполняются на внешнем сервере.
Создайте секрет с паролем административной роли:
kubectl -n astra-automation create secret generic restore-pg-superuser \
--from-literal=POSTGRESQL_ADMIN_PASSWORD=<superuser-password>
Здесь:
<superuser-password>– пароль административной ролиpostgresцелевого сервера.
Разверните сервер:
apiVersion: apps/v1
kind: StatefulSet
metadata: { name: restore-pg, namespace: astra-automation }
spec:
serviceName: restore-pg
replicas: 1
selector: { matchLabels: { app: restore-pg } }
template:
metadata: { labels: { app: restore-pg } }
spec:
imagePullSecrets: [ { name: aa-operators-pull-secret } ]
containers:
- name: postgres
image: registry.astra.ru/aa/postgresql:<version>
env:
- { name: POSTGRESQL_ADMIN_PASSWORD, valueFrom: { secretKeyRef: { name: restore-pg-superuser, key: POSTGRESQL_ADMIN_PASSWORD } } }
- { name: PGDATA, value: /var/lib/postgresql/data/pgdata }
ports: [ { containerPort: 5432 } ]
readinessProbe: { exec: { command: [ pg_isready, -U, postgres ] }, initialDelaySeconds: 5 }
volumeMounts: [ { name: data, mountPath: /var/lib/postgresql/data } ]
volumeClaimTemplates:
- metadata: { name: data }
spec: { accessModes: [ ReadWriteOnce ], resources: { requests: { storage: 10Gi } } }
---
apiVersion: v1
kind: Service
metadata: { name: restore-pg, namespace: astra-automation }
spec: { clusterIP: None, selector: { app: restore-pg }, ports: [ { port: 5432, targetPort: 5432 } ] }
Здесь:
<version>– версия Astra Automation, например2.1.
Важно
Используйте образ Astra-PostgreSQL (registry.astra.ru/aa/postgresql), а не docker.io/postgres.
Дампы содержат параметр таблиц WITH (MACS=FALSE), который другой сервер не поддерживает (см. Параметр WITH (MACS=FALSE) на сервере без поддержки мандатного контроля).
Образ Astra-PostgreSQL ожидает переменную окружения POSTGRESQL_ADMIN_PASSWORD, а не POSTGRES_PASSWORD.
С переменной POSTGRES_PASSWORD контейнер завершает работу с сообщением об ошибке при запуске.
Создайте базы данных и роли компонентов.
Названия ролей должны совпадать с названиями ролей исходного экземпляра платформы (поле username в его секретах конфигурации баз данных; для внутренней PostgreSQL это gateway, automationcontroller, eda, pah).
Тогда владение объектами при восстановлении дампов перейдет к этим ролям:
PG=restore-pg-0
kubectl -n astra-automation exec $PG -- bash -c '
export PGPASSWORD=<superuser-password>
for u in gateway automationcontroller eda pah; do
psql -U postgres -h localhost -c "CREATE USER $u WITH PASSWORD '\''<password>'\''"
done
for d in gateway automationcontroller eda pah; do
psql -U postgres -h localhost -c "CREATE DATABASE $d OWNER $d"
done
'
Здесь:
<superuser-password>– пароль административной ролиpostgresиз секретаrestore-pg-superuser;<password>– назначаемый пароль прикладных ролей; он же указывается в секретах конфигурации баз данных (см. шаг 3).
Привилегии суперпользователя не выдаются прикладным ролям и не требуются им.
Привилегированные шаги восстановления выполняются от имени административной роли postgres.
После восстановления роли работают с обычными привилегиями владельца своей базы данных.
Шаг 2. Восстановление из дампов#
Создайте под, монтирующий тома PVC с резервными копиями всех пяти компонентов:
apiVersion: v1
kind: Pod
metadata: { name: restore-runner, namespace: astra-automation }
spec:
restartPolicy: Never
securityContext:
runAsUser: 1000
runAsGroup: 1000
imagePullSecrets: [ { name: aa-operators-pull-secret } ]
containers:
- name: pg
image: registry.astra.ru/aa/postgresql:<version>
command: [ sleep, infinity ]
volumeMounts:
- { name: aa, mountPath: /backups/aa }
- { name: ac, mountPath: /backups/ac }
- { name: eda, mountPath: /backups/eda }
- { name: pah, mountPath: /backups/pah }
- { name: dashboard, mountPath: /backups/dashboard }
volumes:
- { name: aa, persistentVolumeClaim: { claimName: aa-demo-backup-claim } }
- { name: ac, persistentVolumeClaim: { claimName: ac-demo-backup-claim } }
- { name: eda, persistentVolumeClaim: { claimName: eda-demo-backup-claim } }
- { name: pah, persistentVolumeClaim: { claimName: pah-demo-backup-claim } }
- { name: dashboard, persistentVolumeClaim: { claimName: dashboard-demo-backup-claim } }
Названия томов PVC в примере соответствуют компонентам исходного экземпляра платформы.
Секция securityContext необходима для чтения дампов, так как операторы записывают файлы копий от имени пользователя с идентификатором 1000 без доступа для остальных.
Тот же образ Astra-PostgreSQL гарантирует совместимость pg_restore с форматом дампов.
Определите каталоги восстанавливаемой копии по полю status.backupDirectory ресурсов *Backup (выбор копии однозначен и проверяется до запуска):
B=backup-20260716-1430 # Название ресурса AstraAutomationBackup
AA_DIR=$(basename "$(kubectl -n astra-automation get aabackup $B -o jsonpath='{.status.backupDirectory}')")
AC_DIR=$(basename "$(kubectl -n astra-automation get acbackup $B-controller -o jsonpath='{.status.backupDirectory}')")
EDA_DIR=$(basename "$(kubectl -n astra-automation get edabackup $B-eda -o jsonpath='{.status.backupDirectory}')")
PAH_DIR=$(basename "$(kubectl -n astra-automation get pahbackup $B-hub -o jsonpath='{.status.backupDirectory}')")
echo "$AA_DIR $AC_DIR $EDA_DIR $PAH_DIR"
Если ресурсы *Backup уже удалены, подставьте названия каталогов вручную по меткам времени в их названиях (см. Структура файлов резервной копии).
Восстановите базы данных из дампов, пользуясь привилегиями суперпользователя, с параметром --disable-triggers, сохраняя вывод в журнал:
kubectl -n astra-automation exec restore-runner -- \
env AA_DIR="$AA_DIR" AC_DIR="$AC_DIR" EDA_DIR="$EDA_DIR" PAH_DIR="$PAH_DIR" \
PGPASSWORD=<superuser-password> bash -c '
H=restore-pg-0.restore-pg.astra-automation.svc.cluster.local
FLAGS="--no-acl --no-comments --no-security-labels --disable-triggers -U postgres -h $H -p 5432"
pg_restore $FLAGS -d gateway /backups/aa/$AA_DIR/aa.db
# В копиях версии 2.0 платформы дамп контроллера называется tower.db
pg_restore $FLAGS -d automationcontroller /backups/ac/$AC_DIR/ac.db
pg_restore $FLAGS -d eda /backups/eda/$EDA_DIR/eda.db
pg_restore $FLAGS -d pah /backups/pah/$PAH_DIR/pulp.db
' 2>&1 | tee /tmp/pg_restore.log
Параметры имеют следующее назначение:
--no-acl --no-comments– пропуск командGRANTиCOMMENT. Команды владения объектами при этом выполняются, так как роли с названиями исходного экземпляра платформы созданы на шаге 1, и владение восстанавливается на них;--no-security-labels– пропуск стандартных меток безопасности PostgreSQL;--disable-triggers– отключение триггеров, включая проверки внешних ключей, на время загрузки данных (см. Потеря данных из-за нарушений внешних ключей); выполняется только от имени суперпользователя.
Проверьте результат восстановления до перехода к следующим шагам:
Убедитесь, что в журнале нет ошибок, кроме ошибок мандатного контроля доступа. Допустимы только ошибки с текстами
MAC LABEL,MAC CCRиinsufficient privilege or MAC capabilities. Те же ошибки считают допустимыми и операторы при автоматическом восстановлении. Любые другие ошибки означают неполное восстановление:grep -E '^pg_restore: (error|ошибка):' /tmp/pg_restore.log \ | grep -vcE 'MAC LABEL|MAC CCR|insufficient privilege or MAC'
Ожидаемый результат:
0.Убедитесь, что схема каждой базы данных не пуста:
for d in gateway automationcontroller eda pah; do kubectl -n astra-automation exec restore-runner -- \ env PGPASSWORD=<superuser-password> psql -U postgres \ -h restore-pg-0.restore-pg.astra-automation.svc.cluster.local \ -d $d -t -c "SELECT count(*) FROM pg_stat_user_tables;" done
Ожидаемый результат: ненулевое количество таблиц в каждой базе данных.
Строка errors ignored on restore: N в выводе pg_restore сама по себе не является признаком успешного или неуспешного восстановления.
Значение имеют только виды ошибок в журнале.
Пароль суперпользователя внутреннего Astra-PostgreSQL находится в секрете, на который ссылался исходный экземпляр платформы, либо в созданном на шаге 1 секрете restore-pg-superuser.
У внешнего сервера это пароль его административной роли.
Шаг 3. Секреты конфигурации баз данных#
Создайте новые секреты, указывающие на целевой сервер (см. описание формата секретов):
apiVersion: v1
kind: Secret
metadata: { name: aa-restored-pg-secret, namespace: astra-automation }
type: Opaque
stringData:
host: restore-pg-0.restore-pg.astra-automation.svc.cluster.local
port: "5432"
database: gateway
username: gateway
password: "<password>"
sslmode: disable
type: unmanaged
Аналогичные секреты создайте для Automation Controller, Event-Driven Automation и Private Automation Hub.
Шаг 4. Секреты паролей администраторов#
Операторы применяют пароль администратора из секрета к базе данных только при первичной инициализации, когда пользователя admin в базе данных еще нет.
Восстановленная база данных уже содержит пользователя admin с паролем исходного экземпляра платформы.
Случайные пароли, сгенерированные операторами для нового экземпляра платформы, не применятся к базе данных.
Если этот шаг пропустить, происходит следующее:
задание импорта контента Private Automation Hub завершается ошибкой
invalid username/password: unauthorized: authentication required;оператор Event-Driven Automation завершается ошибкой
HTTP Error 401: Unauthorized, ресурс Event-Driven Automation остается в состоянииFailure=True;корневой ресурс
AstraAutomationне достигаетSuccessful=True;пароли в секретах
*-admin-passwordне соответствуют реальным паролям.
До создания нового ресурса AstraAutomation создайте секреты паролей администраторов дочерних компонентов с названиями, которые будут ожидать операторы (<название дочернего ресурса>-admin-password), задав им значения из секретов исходного экземпляра платформы:
NS=astra-automation
# Соответствие названий дочерних ресурсов исходного и нового экземпляров платформы
declare -A MAP=( [ac-demo]=ac-restored [eda-demo]=eda-restored [pah-demo]=pah-restored )
for SRC in "${!MAP[@]}"; do
NEW=${MAP[$SRC]}
PW=$(kubectl -n "$NS" get secret "${SRC}-admin-password" -o jsonpath='{.data.password}' | base64 -d)
kubectl -n "$NS" create secret generic "${NEW}-admin-password" \
--from-literal=password="$PW"
done
Оператор при согласовании ресурсов обнаружит существующий секрет и не будет генерировать новый.
Для шлюза платформы в поле admin_password_secret нового ресурса укажите секрет исходного экземпляра платформы либо создайте секрет с его значением.
Несовпадение пароля в секрете с паролем admin в базе данных не препятствует работе шлюза.
Однако пароль в секрете должен соответствовать реальному паролю admin в восстановленной базе данных.
Шаг 5. Создание ресурса AstraAutomation#
Создайте новый ресурс AstraAutomation, ссылающийся на подготовленные секреты (см. полное описание манифестов):
apiVersion: aa.astra-automation.ru/v1alpha1
kind: AstraAutomation
metadata: { name: aa-restored, namespace: astra-automation }
spec:
database: { database_secret: aa-restored-pg-secret }
controller: { name: ac-restored, database_secret: ac-restored-pg-secret, secret_key_secret: ac-encryption-secret }
eda: { name: eda-restored, database_secret: eda-restored-pg-secret, db_fields_encryption_secret: eda-encryption-secret }
hub: { name: pah-restored, database_secret: pah-restored-pg-secret }
admin_password_secret: aa-demo-admin-password
db_fields_encryption_secret: aa-encryption-secret
hostname: aa-restored.example.com
public_base_url: https://aa-restored.example.com
ingress_class_name: nginx
ingress_type: Ingress
ingress_tls_secret: aa-restored-tls
image_pull_secrets: [ aa-operators-pull-secret ]
Пример сокращен до полей, которые важны для восстановления.
Остальные поля (реплики, образы, параметры хранилища Private Automation Hub и другие) возьмите из файла aa_object резервной копии или из манифеста исходного экземпляра платформы.
Важно
Секреты шифрования контроллера (db_fields_encryption_secret, secret_key_secret) и Event-Driven Automation (db_fields_encryption_secret) должны совпадать с секретами исходного экземпляра платформы.
Этими ключами зашифрованы чувствительные поля в базах данных.
Замена сделает записи нечитаемыми.
Оператор развернет компоненты нового экземпляра платформы, применит миграции поверх восстановленной схемы и подключится к новому серверу баз данных. Исходный экземпляр платформы остается без изменений.
Если компоненты завершаются ошибкой relation ... already exists, синхронизируйте состояние миграций (см. Рассинхронизация состояния миграций).
Шаг 6. Перенос файлового хранилища Private Automation Hub#
Шаг обязателен при использовании файлового хранилища Private Automation Hub (storage_type: File).
Резервная копия реестра состоит из дампа базы данных (метаданные контента) и каталога pulp/ с файлами артефактов.
Автоматическое восстановление файлов работает только при восстановлении ресурсом AstraAutomationRestore; при ручной процедуре перенос файлов выполняет администратор.
Без переноса восстановленный Private Automation Hub получит базу данных, ссылающуюся на отсутствующие файлы.
Задание Kubernetes (Job) импорта контента будет завершаться ошибкой (FileNotFoundError в журналах подов API).
Выгрузка коллекций и образов из Private Automation Hub будет возвращать ошибку 500, а ресурс Private Automation Hub не достигнет Successful=True.
После создания ресурса AstraAutomation дождитесь появления тома PVC <new-hub>-file-storage и перенесите контент:
apiVersion: v1
kind: Pod
metadata:
name: hub-content-transfer
namespace: astra-automation
spec:
restartPolicy: Never
securityContext:
runAsUser: 1000
runAsGroup: 1000
fsGroup: 1000
containers:
- name: transfer
image: <image>
command:
- /bin/sh
- -c
- |
set -e
BACKUP_DIR=$(ls -d /backups/pah-k8s-backup-* | tail -1)
echo "Restoring hub content from $BACKUP_DIR"
mkdir -p /var/lib/pulp/media
cp -fr "$BACKUP_DIR/pulp/media/." /var/lib/pulp/media/
echo "Done: $(find /var/lib/pulp/media -type f | wc -l) files"
volumeMounts:
- name: backup
mountPath: /backups
- name: file-storage
mountPath: /var/lib/pulp
volumes:
- name: backup
persistentVolumeClaim:
claimName: <source-hub>-backup-claim
- name: file-storage
persistentVolumeClaim:
claimName: <new-hub>-file-storage
Сохраните манифест в файл hub-content-transfer.yaml и примените его:
kubectl -n astra-automation apply -f hub-content-transfer.yaml
kubectl -n astra-automation wait --for=jsonpath='{.status.phase}'=Succeeded pod/hub-content-transfer --timeout=30m
kubectl -n astra-automation delete pod hub-content-transfer
Здесь:
<image>– любой доступный кластеру образ с командной оболочкой, например образ Astra-PostgreSQL из шага 1;<source-hub>-backup-claim– том PVC с резервной копией Private Automation Hub исходного экземпляра платформы, напримерpah-demo-backup-claim;<new-hub>-file-storage– том PVC файлового хранилища нового Private Automation Hub, напримерpah-restored-file-storage.
Под переносит контент последней по времени копии.
Убедитесь, что она соответствует копии, восстановленной на шаге 2, либо подставьте нужный каталог в команду выбора BACKUP_DIR.
Проверка: количество файлов должно соответствовать числу артефактов в восстановленной базе данных Private Automation Hub (SELECT count(*) FROM core_artifact;).
Если задание импорта контента завершилось ошибкой до переноса, оператор создаст его заново на очередном цикле согласования ресурсов. Если задание не создается заново, удалите его вручную (см. Сервисные узлы шлюза платформы).
При использовании хранилища S3 вместо этого шага необходимо перенести bucket (см. Хранилище Private Automation Hub).
Шаг 7. Восстановление Automation Dashboard#
Automation Dashboard (панель аналитики) восстанавливается тем же способом, что и остальные компоненты. Для восстановления выполните следующие действия:
Возьмите дамп
dashboard.dbиз каталога копии в томе PVC Automation Dashboard (или в общем томеbackup_pvc, если он задавался). Подrestore-runnerиз шага 2 монтирует этот том в каталог/backups/dashboard/. Каталог указан в полеstatus.backupDirectoryресурсаDashboardBackup(в примерах –backup-20260716-1430-dashboard), как и в шаге 2.Подготовьте целевую базу данных: роль-владельца с названием роли исходного Automation Dashboard (поле
usernameсекрета конфигурации его базы данных) и пустую базу данных (CREATE ROLE ... LOGIN PASSWORD '...'; CREATE DATABASE ... OWNER ...).Восстановите дамп как описано в шаге 2, от имени суперпользователя, с параметром
--disable-triggersи с сохранением журнала. Владение объектами восстановится на созданную роль:pg_restore --no-acl --no-comments --no-security-labels --disable-triggers \ -U postgres -h <host> -d <db> dashboard.db 2>&1 | tee /tmp/pg_restore_dashboard.log
Здесь:
<host>– адрес целевого сервера PostgreSQL;<db>– база данных Automation Dashboard нового экземпляра платформы.
Проверьте результат восстановления тем же способом, что в шаге 2. Убедитесь, что в журнале
/tmp/pg_restore_dashboard.logнет ошибок, кроме ошибок мандатного контроля доступа (MAC LABEL,MAC CCR,insufficient privilege or MAC capabilities). Убедитесь, что схема базы данных не пуста, то есть запросSELECT count(*) FROM pg_stat_user_tables;возвращает ненулевое значение.Сразу после восстановления дампа отключите расписание синхронизации записи Cluster исходного экземпляра платформы. Иначе Automation Dashboard после запуска начнет синхронизацию с исходным и перезапишет восстановленные данные (см. описание механизма и команды):
UPDATE scheduler_syncschedule SET enabled = false WHERE cluster_id = <id>;
Здесь:
<id>– идентификатор записи исходного экземпляра платформы в таблицеclusters_cluster.
Создайте секреты Automation Dashboard:
<name>-postgres-configuration– координаты целевой базы данных,type: unmanaged;<name>-secret-key– копия секретаsecret-keyисходного Automation Dashboard без изменений, так как в нем находится ключdatabase_key, без которого зашифрованные данные в восстановленной базе нечитаемы;секрет
aap-authсоздается заново при регистрации OAuth в новом экземпляре платформы; копируйте секрет исходного Automation Dashboard, только если использовался собственный секрет с нестандартным названием в полеaap_auth_secret.
Здесь:
<name>– название ресурсаDashboardнового экземпляра платформы.
Создайте ресурс
Dashboardнового экземпляра платформы с полемdatabase.database_secret: <name>-postgres-configuration.
Шаг 8. Очистка сервисных узлов#
Дамп базы данных шлюза содержит записи сервисных узлов исходного экземпляра платформы.
После создания нового ресурса AstraAutomation (когда оператор зарегистрировал собственные узлы) удалите записи исходного экземпляра платформы по процедуре очистки сервисных узлов.
До очистки проверка восстановленных данных недостоверна, так как часть запросов обслуживается компонентами исходного экземпляра платформы.
Для экземпляров платформы с внешними узлами плоскости исполнения после завершения процедуры также отключите внешние узлы в восстановленном экземпляре платформы (см. Внешние узлы плоскости исполнения). См. также полный перечень действий изоляции.
Восстановление взамен утраченной платформы#
Процедура выше применима и тогда, когда исходный экземпляр платформы утрачен (потерян кластер или удален ресурс AstraAutomation).
Процедура имеет следующие отличия:
Название экземпляра платформы и название узла (
hostname) можно сохранить прежними, так как конфликта с исходным экземпляром платформы больше нет.Если сервер внешней СУБД сохранился и данные в нем не повреждены, шаги 1–2 не требуются. В секретах конфигурации (см. шаг 3) укажите координаты существующих баз данных. Новый экземпляр платформы продолжит работать на них. Резервная копия при этом сохраняется на случай повреждения самих баз данных.
Секреты необходимо создать заново (см. шаги 3–5). Значения секретов шифрования и паролей возьмите из файла
secrets.ymlрезервной копии (см. Структура файлов резервной копии).При прежнем названии экземпляра платформы названия сервисных узлов совпадают с записями в восстановленной базе данных шлюза. Записи перезаписываются. Очистка (см. шаг 8) не требуется. При новом названии выполните шаг 8.
Типичные проблемы ручного восстановления#
Операторы не обрабатывают перечисленные проблемы автоматически; при ручной процедуре их учитывает администратор.
Параметр WITH (MACS=FALSE) на сервере без поддержки мандатного контроля#
pg_dump Astra-PostgreSQL записывает у каждой таблицы параметр мандатного контроля доступа:
CREATE TABLE public.main_organization (...) WITH (macs='false');
Сервер PostgreSQL без поддержки этого параметра (например, docker.io/postgres) завершает каждую команду CREATE TABLE ошибкой ERROR: unrecognized parameter "macs".
По умолчанию pg_restore продолжает работу при ошибках и завершается с нулевым кодом возврата, но схема остается пустой.
Таблицы не созданы, данные не вставлены.
Параметр --no-security-labels от этого не защищает, так как WITH (MACS=...) является параметром хранения таблицы, а не меткой безопасности.
Рекомендуется восстанавливать в Astra-PostgreSQL (registry.astra.ru/aa/postgresql), который поддерживает параметр.
Если доступен только сервер без поддержки мандатного контроля, преобразуйте дамп в текстовый формат SQL и удалите специфичные конструкции перед загрузкой:
kubectl -n astra-automation exec restore-runner -- \
env AA_DIR="$AA_DIR" PGPASSWORD=<superuser-password> bash -c '
H=restore-pg-0.restore-pg.astra-automation.svc.cluster.local
# Преобразование дампа из формата custom в текстовый SQL
pg_restore --no-acl --no-comments --no-security-labels \
-f /tmp/gateway.sql /backups/aa/$AA_DIR/aa.db
# Удаление параметра MACS и команд мандатного контроля
sed -i -E "s/ WITH \(macs=.?(false|true).?\)//Ig; /^(MAC LABEL|MAC CCR) /Id" /tmp/gateway.sql
# Загрузка
psql -U postgres -h $H -d gateway -v ON_ERROR_STOP=0 -f /tmp/gateway.sql
' 2>&1 | tee /tmp/psql_restore.log
Здесь:
AA_DIR– тот же каталог копии, что выбран в шаге 2 (из поляstatus.backupDirectory). Для остальных компонентов подставьтеAC_DIR,EDA_DIR,PAH_DIRи их дампы аналогично.<superuser-password>– пароль административной ролиpostgres.
После загрузки проверьте отсутствие ошибок в журнале:
grep -cE "^psql:.*(ERROR|ОШИБКА):" /tmp/psql_restore.log
Ожидаемый результат: 0.
Команды мандатного контроля удалены из файла перед загрузкой, поэтому допустимых ошибок на этом пути нет.
Затем убедитесь, что схема каждой базы данных не пустая, тем же запросом, что в шаге 2.
Текстовый формат теряет параллелизм формата custom и работает медленнее на больших базах данных, поэтому Astra-PostgreSQL предпочтительнее.
Рассинхронизация состояния миграций#
Если после восстановления таблица django_migrations содержит неполный набор записей, при запуске компонента механизм миграций пытается создать уже существующие объекты, и компонент завершается ошибкой relation "..." already exists.
Синхронизируйте состояние миграций как «уже примененные» и перезапустите компонент.
Для Automation Controller выполните следующую команду:
POD=$(kubectl -n astra-automation get pod -l app.kubernetes.io/name=ac-restored-task \
-o jsonpath='{.items[0].metadata.name}')
kubectl -n astra-automation exec "$POD" -c ac-restored-task -- awx-manage migrate --fake
Для Private Automation Hub выполните следующую команду:
POD=$(kubectl -n astra-automation get pod -l app.kubernetes.io/name=pah-restored-api \
-o jsonpath='{.items[0].metadata.name}')
kubectl -n astra-automation exec "$POD" -- pulpcore-manager migrate --fake
Параметр --fake помечает миграции примененными без изменения схемы.
Он корректен, только когда схема полностью восстановлена из дампа.
Если схема была неполной (см. Параметр WITH (MACS=FALSE) на сервере без поддержки мандатного контроля), сначала восстановите дамп повторно.
Потеря данных из-за нарушений внешних ключей#
Если pg_restore выполняется без параметра --disable-triggers, часть строк не вставляется из-за порядка загрузки и циклических ссылок.
pg_restore сообщает о нарушениях внешних ключей.
Данные (например, инвентарные списки Automation Controller) восстанавливаются не полностью.
Восстанавливайте от имени суперпользователя с параметром --disable-triggers (уже включен в команду шага 2).
На время загрузки данных отключаются все триггеры, включая системные проверки внешних ключей.
От имени обычного владельца базы данных параметр недоступен.