Резервне копіювання та відновлення бази даних реєстру

На цій сторінці:
🌐 Цей документ доступний українською та англійською мовами. Використовуйте перемикач у правому верхньому куті, щоб змінити версію.

1. Загальний опис

Платформа надає можливість налаштувати надійне резервне копіювання та відновлення баз даних (БД) реєстру. Це забезпечує захист даних від втрати, дозволяє відновлювати інформацію у випадку збоїв системи та підтримує бізнес-континуїтет.

Для реалізації цих можливостей використовується Postgres Operator від Crunchy Data (PGO) у поєднанні з pgBackRest — потужним інструментом з відкритим кодом для резервного копіювання та відновлення баз даних PostgreSQL.

PGO спрощує та автоматизує багато завдань, пов’язаних із резервним копіюванням і відновленням, зокрема:

  • Налаштування розкладів автоматичного резервного копіювання та політик збереження

  • Зберігання резервних копій у кількох сховищах: Kubernetes, AWS S3 (та S3-сумісні сервіси, такі як MinIO), Google Cloud Storage (GCS) і Azure Blob Storage

  • Виконання одноразових резервних копій за запитом

  • Підтримку "відновлення на певний момент часу (PITR)

  • Клонування баз даних у нові екземпляри

2. Налаштування резервного копіювання

Проблематика

За замовчуванням операційний та аналітичний кластери Postgres налаштовані для постійного архівування журналів попереднього запису (WAL) і створення повної резервної копії щодня. Поточна політика збереження передбачає зберігання лише однієї повної копії — при створенні нової pgBackRest автоматично видаляє стару разом із відповідними WAL-файлами.

Рішення

pgBackRest дозволяє налаштувати різні типи резервного копіювання, політики збереження та розклади для задоволення вимог до точки відновлення (RPO), часу відновлення (RTO) та ефективного використання дискового простору.

2.1. Налаштування розкладу резервного копіювання

Можна налаштувати розклад для трьох основних типів резервних копій:

  • full: повна резервна копія всього кластера Postgres. Це найбільший за обсягом тип резервної копії.

  • differential: копіює всі зміни з моменту останньої повної резервної копії.

  • incremental: копіює всі зміни з моменту останньої повної, диференціальної або інкрементної резервної копії.

Приклад

Для створення повної резервної копії щонеділі о 1:00 ночі та інкрементних копій щодня (крім неділі) о 1:00 використовуйте таку конфігурацію:

spec:
  backups:
    pgbackrest:
      repos:
      - name: repo1
        schedules:
          full: "0 1 * * 0"
          incremental: "0 1 * * 1-6"
Розклади задаються в секції spec.backups.pgbackrest.repos.schedules у форматі cron.

PGO створить відповідні Kubernetes CronJobs для автоматичного запуску резервного копіювання. Резервні копії використовуватимуть конфігурацію, яку ви вказали.

2.2. Управління політиками збереження резервних копій

PGO дозволяє гнучко керувати політиками збереження резервних копій для повних та диференціальних бекапів, забезпечуючи баланс між доступністю історичних копій та ефективним використанням дискового простору.

2.2.1. Логіка збереження

Коли термін дії повної резервної копії закінчується, pgBackRest автоматично видаляє цю копію разом із пов’язаними інкрементними та диференціальними копіями, а також відповідними файлами WAL (Write-Ahead Logging).

Приклад

Якщо у вас є повна резервна копія з чотирма інкрементними копіями, всі інкрементні копії також будуть видалені, коли закінчиться термін дії повної копії.

2.2.2. Типи політик збереження

Існує два типи політик для налаштування збереження повних резервних копій (repo1-retention-full-type):

  • count — збереження певної кількості останніх повних резервних копій. (Значення за замовчуванням)

  • time — збереження копій за певний період (у днях).

2.2.3. Приклад налаштування

Щоб зберігати повні резервні копії протягом 14 днів, додайте до spec.backups.pgbackrest.global наступну конфігурацію:

spec:
  backups:
    pgbackrest:
      global:
        repo1-retention-full: "14"
        repo1-retention-full-type: time

У випадку, якщо є дві резервні копії — одній 12 днів, а іншій — 15 днів, жодна з них не буде видалена. Це тому, що видалення 15-денної копії залишило б тільки 12-денну, яка не відповідає політиці збереження (мінімум одна копія 14-денної давності повинна бути збережена).

2.3. Управління збереженням WAL журналів

У випадках, коли об’єм WAL-журналів є значним, можна оптимізувати простір, обмеживши кількість збережених журналів без шкоди для відновлення.

pgBackRest дозволяє налаштувати параметри для зберігання WAL журналів:

  • repo1-retention-archive — кількість резервних копій, для яких зберігатимуться WAL-журнали.

  • repo1-retention-archive-type — типи копій, для яких зберігатимуться WAL-журнали. Підтримувані значення:

    • full — зберігати WAL лише для повних копій.

    • diff — зберігати WAL для повних та диференціальних копій.

    • incr — зберігати WAL для повних, диференціальних та інкрементних копій.

Приклади використання

  1. Економія простору: Якщо важливо зменшити обсяг збережених WAL, налаштуйте збереження журналів лише для повних копій:

    repo1-retention-archive: "2"
    repo1-retention-archive-type: full
  2. Гнучке відновлення: Для можливості відновлення на будь-який момент часу (PITR) використовуйте:

    repo1-retention-archive: "5"
    repo1-retention-archive-type: incr

2.4. Одноразове створення резервної копії

Postgres Operator (PGO) дозволяє створювати одноразові резервні копії за допомогою pgBackRest. Цей процес складається з двох основних етапів:

  1. Налаштування параметрів резервного копіювання

  2. Запуск резервної копії через анотацію

Крок 1: Налаштування параметрів резервного копіювання

Спочатку налаштуйте розділ spec.backups.pgbackrest.manual, щоб визначити параметри для одноразового резервного копіювання. У цьому розділі ви задаєте тип резервної копії та додаткові опції для pgBackRest.

Приклад. Налаштування для створення повної резервної копії
spec:
  backups:
    pgbackrest:
      manual:
        repoName: repo1 (1)
        options:
          - --type=full (2)

Пояснення параметрів:

1 repoName — ім’я репозиторію, куди буде збережена резервна копія.
2 --type=full — тип резервної копії (у цьому випадку — повна копія).

Ця конфігурація лише готує параметри для резервного копіювання, але не запускає сам процес.

Крок 2: Запуск резервного копіювання

Щоб ініціювати резервне копіювання, додайте анотацію postgres-operator.crunchydata.com/pgbackrest-backup до вашого ресурсу PostgresCluster. Анотація повинна містити позначку часу, яка вказує, коли було ініційовано резервне копіювання.

Приклад. Запуск резервного копіювання для operational кластера
kubectl annotate -n <registry-name> postgrescluster operational \
  postgres-operator.crunchydata.com/pgbackrest-backup="$(date)"
Замініть <registry-name> на назву вашого реєстру/namespace.

В результаті PGO виявить додану анотацію та створить завдання для одноразового резервного копіювання відповідно до вказаних параметрів.

Повторний запуск резервного копіювання

Якщо вам потрібно повторно виконати резервне копіювання з тими ж параметрами, оновіть значення анотації, додавши атрибут --overwrite.

Приклад. Повторний запуск резервного копіювання
kubectl annotate -n <registry-name> postgrescluster operational --overwrite \
  postgres-operator.crunchydata.com/pgbackrest-backup="$(date)"
Замініть <registry-name> на назву вашого реєстру/namespace.

Рекомендації

  • Якщо плануєте створювати одноразові резервні копії з однаковими параметрами у майбутньому, збережіть їх у секції manual для повторного використання.

  • Використання мітки часу в анотації дозволяє легко відстежувати, коли було ініційовано резервне копіювання.

  • Для великих кластерів рекомендується створювати повну резервну копію в позаробочий час для мінімізації навантаження.

3. Відновлення

3.1. Відновлення на момент часу або на конкретну резервну копію

pgBackRest підтримує два основних підходи до відновлення бази даних:

  1. Відновлення на певний момент часу (PITR) — для повернення бази даних у стан, який вона мала на конкретну дату і час.

  2. Відновлення з конкретної резервної копії — для відновлення з певного бекапу без урахування WAL журналів.

3.1.1. Відновлення на певний момент часу (PITR)

Щоб відновити базу даних до конкретного моменту часу:

  1. Додайте конфігурацію до секції spec.backups.pgbackrest:

    spec:
      backups:
        pgbackrest:
          restore:
            enabled: true
            repoName: repo1
            options:
              - --type=time (1)
              - --target="2022-06-09 14:15:11" (2)

    Пояснення параметрів:

    1 --type=time — відновлення до конкретного моменту часу.
    2 --target — дата і час для відновлення у форматі YYYY-MM-DD HH:MM:SS.

    Час відновлення має бути вказаний у форматі UTC.

  2. Ініціюйте процес відновлення за допомогою анотації:

    kubectl annotate -n <registry-name> postgrescluster operational --overwrite \
      postgres-operator.crunchydata.com/pgbackrest-restore="$(date)"
    Замініть <registry-name> на назву вашого namespace.
  • Усі дані, створені після вказаного моменту часу (--target="2022-06-09 14:15:11") і до початку процесу відновлення, будуть втрачені.

  • Перед початком PITR обов’язково переконайтеся, що втрата змін після обраної дати є прийнятною.

3.1.2. Відновлення з конкретної резервної копії

Цей метод дозволяє відновити базу даних зі збереженої резервної копії без відновлення WAL журналів.

  1. Додайте до секції spec.backups.pgbackrest наступну конфігурацію:

    spec:
      backups:
        pgbackrest:
          restore:
            enabled: true
            repoName: repo1
            options:
              - --type=immediate (1)
              - --set=20220602-073427F_20220602-073507I (2)

    Пояснення параметрів:

    1 --type=immediate — відновлення з конкретної резервної копії.
    2 --set — ідентифікатор резервної копії, яку потрібно відновити.
  2. Перегляньте список доступних резервних копій. Це можна зробити 2 способами:

    • За допомогою pgBackRest. Для цього виконайте наступну команду:

      pgbackrest info --stanza=db
    • Перевірте вміст S3-кошика, де зберігаються резервні копії.

  3. Ініціюйте відновлення, додавши анотацію:

    kubectl annotate -n <registry-name> postgrescluster operational --overwrite \
      postgres-operator.crunchydata.com/pgbackrest-restore="$(date)"

3.1.3. Завершення процесу відновлення

Після завершення відновлення обов’язково вимкніть параметр restore.enabled, щоб уникнути повторного запуску процесу.

spec:
  backups:
    pgbackrest:
      restore:
        enabled: false

3.1.4. Додаткові зауваження

  • Всі дії з відновлення необхідно виконати як для операційної, так і для аналітичної бази даних.

  • Щоб забезпечити консистентність між цими базами після відновлення, виконайте кроки з Узгодження даних на аналітичному кластері.

3.2. Клонування з резервної копії

pgBackRest дозволяє клонувати базу даних зі збереженої резервної копії, створюючи новий екземпляр БД з бажаного стану — на певний момент часу або з конкретної резервної копії.

3.2.1. Клонування на момент часу (PITR)

Щоб створити новий екземпляр бази даних, відновлений на певний момент часу, додайте секцію spec.dataSource до маніфесту нового екземпляра БД.

Приклад конфігурації для PITR
spec:                                     (1)
  dataSource:                             (2)
    pgbackrest:                           (3)
      stanza: db                          (4)
      configuration:                      (5)
        - secret:                         (6)
            name: s3-conf                 (7)
      global:                             (8)
        repo1-path: "/postgres-backup/source_system/operational"       (9)
        repo1-s3-uri-style: path                                  (10)
        repo1-storage-verify-tls: n                              (11)
        repo1-storage-port: "9000"                               (12)
      options:                                                  (13)
        - --type=time                                           (14)
        - --target="2022-06-09 14:15:11-04"                     (15)
      repo:                                                     (16)
        name: repo1                                             (17)
        s3:                                                     (18)
          bucket: "bucketName"                                  (19)
          endpoint: "endpoint"                                  (20)
          region: "us-east-1"                                   (21)

Пояснення параметрів:

1 spec — коренева секція маніфесту Kubernetes.
2 dataSource — визначає джерело даних для відновлення.
3 pgbackrest — конфігурація для використання pgBackRest як джерела даних.
4 stanza — ім’я конфігурації pgBackRest для конкретної бази даних.
5 configuration — масив конфігурацій для підключення до сховища.
6 secret — об’єкт Kubernetes Secret для зберігання облікових даних.
7 name — ім’я секрету, що містить облікові дані для доступу до S3 (тут: s3-conf).
8 global — глобальні параметри для підключення до сховища.
9 repo1-path — шлях до резервної копії в сховищі.
10 repo1-s3-uri-style — стиль URI для підключення до S3 (наприклад, path або virtual).
11 repo1-storage-verify-tls — вимкнення TLS перевірки (n означає "ні").
12 repo1-storage-port — порт для підключення до сховища (наприклад, 9000).
13 options — параметри для відновлення.
14 --type=time — вказує, що відновлення виконується на певний момент часу.
15 --target — цільова дата і час для відновлення (YYYY-MM-DD HH:MM:SS з часовим поясом).
16 repo — інформація про репозиторій для відновлення.
17 name — ім’я репозиторію (тут: repo1).
18 s3 — параметри підключення до S3 сховища.
19 bucket — ім’я бакета/кошика в S3 для збереження резервних копій.
20 endpoint — URL-адреса для підключення до S3-сумісного сховища.
21 region — регіон S3 (наприклад, us-east-1).

Час відновлення (--target) повинен бути вказаний у відповідному часовому поясі (наприклад, -04 для UTC-4).

3.2.2. Клонування з конкретної резервної копії

Якщо потрібно відновити базу з певного збереженого бекапу (без відновлення WAL журналів), змініть параметри в секції options:

options:
  - --type=immediate
  - --set=20220602-073427F_20220602-073507I

Пояснення параметрів:

  • --type=immediate — відновлення з конкретної резервної копії.

  • --set — ідентифікатор резервної копії, яку потрібно використати для відновлення.

Переглянути список доступних резервних копій можна 2 способами:

  • За допомогою pgBackRest. Для цього виконайте наступну команду:

    pgbackrest info --stanza=db
  • Перевірте вміст S3-кошика, де зберігаються резервні копії.

3.2.3. Завершення процесу клонування

Після налаштування маніфесту та запуску процесу, PGO автоматично відновить базу даних у новий екземпляр на основі зазначених параметрів.

  • Виконайте процес клонування для операційної та аналітичної бази даних, щоб зберегти консистентність.

  • Після завершення клонування переконайтеся, що дані між обома базами узгоджені. Для цього дотримуйтеся інструкцій у розділі Узгодження даних на аналітичному кластері.

3.2.4. Основні рекомендації

  • Використовуйте PITR для клонування бази до конкретного моменту часу, якщо потрібно відновити дані до певного стану.

  • Застосовуйте відновлення з конкретного бекапу для створення точних копій збережених резервних копій.

  • Регулярно перевіряйте конфігурації доступу до S3 сховищ та секретів для уникнення помилок під час клонування.

3.3. Узгодження даних на аналітичному кластері

Проблематика

Операційна та аналітична бази даних реплікуються в асинхронному режимі. Через це їх резервні копії можуть бути неузгодженими, навіть якщо обидві бази були відновлені на один і той самий момент часу.

Рішення

Щоб забезпечити консистентність між базами після відновлення, необхідно вручну синхронізувати аналітичну базу з операційною.

3.3.1. Кроки для узгодження даних

Виконайте наступні дії на базі даних registry аналітичного екземпляра для відновлення узгодженого стану:

  1. Зупиніть поточну підписку на реплікацію, щоб уникнути записів під час очищення таблиць.

    ALTER SUBSCRIPTION operational_sub DISABLE;
  2. Очистіть усі таблиці, що входять до підписки: видаліть усі дані з таблиць, які беруть участь у реплікації, використовуючи команду TRUNCATE.

    SELECT 'TRUNCATE ' || srrelid::regclass || ' CASCADE;' FROM pg_subscription_rel \gexec

    Ця команда генерує та виконує SQL-запити для очищення всіх таблиць з підтримкою каскадного видалення.

  3. Видаліть стару підписку: після очищення таблиць видаліть чинну підписку на реплікацію.

    DROP SUBSCRIPTION operational_sub;
  4. Створіть нову підписку: налаштуйте нову підписку для відновлення логічної реплікації з операційної бази.

    CREATE SUBSCRIPTION operational_sub
    CONNECTION 'host=OperationalHost user=postgres dbname=registry password=XXXXXX'
    PUBLICATION analytical_pub
    WITH (create_slot=false, slot_name=operational_sub);

    Пояснення параметрів:

    • host=OperationalHost — адреса сервера операційної бази.

    • user=postgres — користувач для підключення.

    • dbname=registry — ім’я бази даних.

    • password=XXXXXX — пароль користувача.

    • PUBLICATION analytical_pub — публікація для реплікації.

    • WITH (create_slot=false, slot_name=operational_sub) — використовує наявний слот для реплікації.

Що відбудеться далі?

  • Після створення нової підписки почнеться первинна синхронізація таблиць з операційної бази до аналітичної.

  • Після завершення первинної синхронізації логічна реплікація автоматично увімкнеться.

  • Операційна та аналітична бази даних знову будуть знаходитися в узгодженому стані.

Час, необхідний для первинної синхронізації, залежить від обсягу даних в операційній базі.

3.3.2. Рекомендації

  • Під час процесу узгодження не рекомендується вносити зміни в аналітичну базу даних до завершення первинної синхронізації.

  • Перевірте журнали PostgreSQL, щоб переконатися у відсутності помилок під час створення нової підписки та реплікації.

  • Після завершення синхронізації перевірте консистентність даних між операційною та аналітичною базами.

4. Безперервне відновлення на Standby-кластері

Удосконалені стратегії високої доступності (HA) та аварійного відновлення (Disaster Recovery, DR) передбачають використання Standby-кластерів для безперервного відновлення бази даних. Такі кластери функціонують як пасивні вузли, які постійно оновлюються з основного кластера через стрімінгову реплікацію або інші механізми синхронізації.

Postgres Operator (PGO) забезпечує простий механізм розгортання Standby-кластерів, які можуть охоплювати кілька кластерів Kubernetes і використовувати спільне зовнішнє сховище для резервних копій та WAL журналів.

4.1. Створення Standby-кластера

Standby-кластер дозволяє створити репліку основного кластера PostgreSQL, яка постійно оновлюється за допомогою резервних копій та WAL-журналів. У разі відмови основного кластера, Standby можна швидко перевести в активний режим для забезпечення безперервності роботи.

4.1.1. Вимоги для Standby-кластера

  1. Доступ до репозиторію резервних копій: Standby-кластер повинен мати доступ до S3-репозиторію, де зберігаються резервні копії та WAL журнали основного кластера.

  2. Налаштований pgBackRest: Standby використовує pgBackRest для безперервного відновлення та синхронізації з основним кластером.

4.1.2. Конфігурація Standby-кластера

Щоб налаштувати Standby-кластер, додайте до маніфесту наступні параметри:

spec:
  backups:
    pgbackrest:
      image: registry.developers.crunchydata.com/crunchydata/crunchy-pgbackrest:ubi8-2.40-1   (1)
      repos:
        - name: repo1                                                                          (2)
          s3:
            bucket: "bucket"                                                                   (3)
            endpoint: "primary.endpoint"                                                       (4)
            region: "ca-central-1"                                                              (5)
  standby:
    enabled: true                                                                              (6)
    repoName: repo1                                                                            (7)

Пояснення параметрів:

1 image — образ контейнера з pgBackRest, який використовується для резервного копіювання та відновлення.
2 repos — конфігурація репозиторіїв для зберігання резервних копій.
3 bucket — ім’я S3-кошика для зберігання резервних копій.
4 endpoint — адреса S3-сумісного сховища.
5 region — регіон S3-кошика.
6 standby.enabled — увімкнення режиму Standby для кластера. (true — Standby активний)
7 repoName — ім’я репозиторію, з якого Standby-кластер зчитуватиме резервні копії.

4.2. Підвищення (Promote) Standby-кластера

Підвищення (Promote) Standby-кластера переводить його з пасивного режиму до активного, роблячи його новим основним кластером, готовим приймати запити на запис і читання.

4.2.1. Запобігання "розщепленню мозку" (Split-Brain)

Перед підвищенням Standby-кластера обов’язково переконайтеся, що основний кластер більше не активний. Якщо обидва кластери одночасно будуть активні, це призведе до розщеплення мозку — ситуації, коли обидва кластери можуть записувати дані в сховище незалежно один від одного, що призводить до втрати або пошкодження даних.

Завжди вимикайте основний кластер перед підвищенням Standby.

4.2.2. Підвищення Standby до Primary

  1. Вимкніть Standby-режим: щоб перевести Standby-кластер в активний режим, необхідно вимкнути параметр standby.enabled у маніфесті:

    spec:
     standby:
       enabled: false
  2. Після вимкнення Standby-режиму відбувається наступне:

    • Кластер переходить в активний режим (Primary) і починає приймати запити на запис.

    • Більше не відбувається зчитування резервних копій і WAL журналів із зовнішнього сховища.

    • Всі нові зміни будуть записуватися безпосередньо у новий Primary-кластер.

4.2.3. Перевірка статусу після підвищення

Після переведення Standby у Primary рекомендується:

  • Перевірити статус кластера: використайте інструменти моніторингу для перевірки стану бази даних і переконання, що кластер приймає запити.

  • Налаштувати новий Standby (за потреби): якщо ви хочете забезпечити подальшу відмовостійкість, налаштуйте новий Standby-кластер для нещодавно активованого Primary.