Резервное копирование и восстановление PostgreSQL

Резервная копия базы данных системы может понадобиться для ее восстановления после сбоя или переноса на другое оборудование. Система использует СУБД PostgreSQL для хранения конфигураций сервисов.

В данном разделе рассматривается процесс резервного копирования, когда инсталляция PostgreSQL находится внутри кластера.

Резервное копирование

Чтобы создать резервную копию таблиц PostgreSQL, выполните следующие действия:

  1. Подключитесь к управляющему узлу кластера.

  2. В любой директории создайте скрипт backup_pg.sh со следующим содержимым:

    backup_pg.sh
    #!/bin/bash
    
    # Создание директории для сохранения резервной копии.
    back_dir=<backup-dir>
    mkdir -p $back_dir
    
    # Создание резервной копии всех баз данных.
    kubectl exec -n <namespace> postgresql-0 -- /bin/sh -c 'pg_dumpall --port 5432 --username postgres -w --verbose --file "/tmp/all_databases.sql"'
    
    # Проверка, что файл был создан.
    kubectl exec -n <namespace> postgresql-0 -- /bin/sh -c 'test -f /tmp/all_databases.sql'
    if [ $? -ne 0 ]; then
        echo "Ошибка: файл /tmp/all_databases.sql не был создан"
        exit 1
    fi
    
    # Копирование резервной копии из контейнера на хост.
    kubectl cp -n <namespace> postgresql-0:/tmp/all_databases.sql $back_dir/all_databases.sql
    
    # Архивирование резервной копии.
    cd $back_dir
    tar -czpf postgres_backup_all_databases.tar.gz all_databases.sql
    
    # Удаление временного файла.
    kubectl exec -n <namespace> postgresql-0 -- /bin/sh -c 'rm /tmp/all_databases.sql'
    
    echo "Резервная копия всех баз данных создана и сохранена в $back_dir/postgres_backup_all_databases.tar.gz"

    Здесь:

    • <namespace> — имя пространства имен, в котором установлен кластер.

    • <backup-dir> — путь к директории, в которой будет создана резервная копия.

  3. Разрешите выполнение созданного скрипта:

    chmod +x backup_pg.sh
  4. Запустите скрипт:

    ./backup_pg.sh

В результате выполнения скрипта по указанному пути <backup-dir> будет создан архив postgres_backup_all_databases.tar.gz с резервной копией всех баз данных PostgreSQL..

Восстановление из резервных копий

Чтобы восстановить таблицы PostgreSQL из резервной копии, выполните следующие действия:

  1. Подключитесь к управляющему узлу кластера.

  2. В любую директорию загрузите архив postgres_backup_all_databases.tar.gz, полученный в результате резервного копирования.

  3. В этой же директории создайте скрипт restore_pg.sh со следующим содержимым:

    restore_pg.sh
    #!/bin/bash
    
    backup_file="$(dirname "$0")/postgres_backup_all_databases.tar.gz"
    extract_dir="/tmp/pg_conf/restore"
    mkdir -p $extract_dir
    
    # Список баз данных, которые НЕ нужно удалять (исключения для удаления).
    # Не следует редактировать, изменения могут привести к ошибкам в работе системы.
    excluded_databases=("postgres" "template0" "template1" "evo_core_access" "evo_core_mf_feed")
    
    # Список баз данных, которые НЕ нужно восстанавливать (исключения для восстановления).
    # Не следует редактировать, изменения могут привести к ошибкам в работе системы.
    excluded_restore_databases=("evo_core_access" "evo_core_mf_feed")
    
    # Проверка наличия файла резервной копии.
    if [ ! -f "$backup_file" ]; then
        echo "Ошибка: файл резервной копии $backup_file не найден"
        exit 1
    fi
    
    echo "Распаковка архива $backup_file"
    tar -xzf "$backup_file" -C "$extract_dir"
    
    # Проверка, что файл all_databases.sql существует.
    if [ ! -f "$extract_dir/all_databases.sql" ]; then
        echo "Ошибка: файл all_databases.sql не найден в архиве"
        exit 1
    fi
    
    echo "Копирование файла резервной копии в под"
    kubectl cp -n <namespace> "$extract_dir/all_databases.sql" postgresql-0:/tmp/all_databases.sql
    
    echo "Завершение всех активных сессий для баз данных, которые нужно удалить"
    kubectl exec -n <namespace> postgresql-0 -- /bin/sh -c "
      psql --port 5432 --username postgres -w -tAc \"
        SELECT pg_terminate_backend(pg_stat_activity.pid)
        FROM pg_stat_activity
        WHERE pg_stat_activity.datname NOT IN ('$(IFS="','"; echo "${excluded_databases[*]}")')
        AND pid <> pg_backend_pid();
      \"
    "
    
    echo "Удаление всех баз данных, кроме исключений"
    kubectl exec -n <namespace> postgresql-0 -- /bin/sh -c "
      psql --port 5432 --username postgres -w -tAc \"
        SELECT 'DROP DATABASE IF EXISTS ' || quote_ident(datname) || ';'
        FROM pg_database
        WHERE datistemplate = false
        AND datname NOT IN ('$(IFS="','"; echo "${excluded_databases[*]}")');
      \" | psql --port 5432 --username postgres -w
    "
    
    echo "Удаление всех пользовательских ролей, кроме исключений"
    kubectl exec -n <namespace> postgresql-0 -- /bin/sh -c "
      psql --port 5432 --username postgres -w -tAc \"
        SELECT 'DROP ROLE IF EXISTS ' || quote_ident(rolname) || ';'
        FROM pg_roles
        WHERE rolname NOT IN (
          'postgres', 'pg_read_all_data', 'pg_write_all_data',
          'pg_monitor', 'pg_read_all_settings', 'pg_read_all_stats',
          'pg_stat_scan_tables', 'pg_read_server_files', 'pg_write_server_files',
          'pg_execute_server_program', 'pg_signal_backend'
        );
      \" | psql --port 5432 --username postgres -w
    "
    
    echo "Фильтрация файла резервной копии для исключения определенных баз данных"
    kubectl exec -n <namespace> postgresql-0 -- /bin/sh -c "
      grep -Ev '^(CREATE DATABASE|ALTER DATABASE) ($(IFS="|"; echo "${excluded_restore_databases[*]}"))' /tmp/all_databases.sql > /tmp/filtered_databases.sql
    "
    
    echo "Создание отсутствующих баз данных перед восстановлением"
    kubectl exec -n <namespace> postgresql-0 -- /bin/sh -c "
      psql --port 5432 --username postgres -w -tAc \"
        SELECT 'CREATE DATABASE ' || quote_ident(datname) || ';'
        FROM pg_database
        WHERE datname NOT IN ('$(IFS="','"; echo "${excluded_databases[*]}")')
        AND datname NOT IN (SELECT datname FROM pg_database);
      \" | psql --port 5432 --username postgres -w
    "
    
    echo "Восстановление данных из отфильтрованного файла резервной копии"
    kubectl exec -n <namespace> postgresql-0 -- /bin/sh -c 'psql --port 5432 --username postgres -w -f /tmp/filtered_databases.sql'
    
    echo "Очистка временных файлов"
    rm -rf "$extract_dir"
    kubectl exec -n <namespace> postgresql-0 -- /bin/sh -c 'rm /tmp/all_databases.sql /tmp/filtered_databases.sql'
    
    echo "Восстановление завершено"

    Здесь:

    • <namespace> — имя пространства имен, в котором установлен кластер.

  4. Разрешите выполнение созданного скрипта:

    chmod +x restore_pg.sh
  5. Запустите скрипт:

    ./restore_pg.sh

В результате выполнения скрипта конфигурация сервисов системы будет восстановлена.