Отказоустойчивый кластер PostgreSQL

При установке Визион.Сервер СУБД PostgreSQL развёртывается на одном узле. Такая конфигурация не требует дополнительных настроек, но не обеспечивает отказоустойчивости. При выходе узла из строя работа СУБД будет нарушена.

В производственных средах рекомендуется развернуть и использовать отказоустойчивый кластер PostgreSQL из трёх узлов.

ПРИМЕЧАНИЕ
Визион может использовать для хранения служебной БД внешний сервер PostgreSQL. Подробнее в инструкции Миграция служебной БД во внешний сервер PostgreSQL .

Развёртывание кластера выполняется с помощью плейбука Ansible. Далее узел, на котором запускается плейбук, называется управляющим (control node).

Доступ к мастеру кластера выполняется через виртуальный IP-адрес (Virtual IP Address, VIP). Для автоматического переназначения VIP на узлах кластера развёртываются службы vip-manager и etcd .

Для отслеживания состояния узлов кластера и автоматического выбора нового мастера используется Patroni.

ПРИМЕЧАНИЕ
В Patroni мастер PostgreSQL называется лидером.

Системные требования#

Отказоустойчивая конфигурация предъявляет свои требования к узлам кластера PostgreSQL в дополнение к основным:

  • ОС ALT Linux c10f1 или ALT Linux c10f2.

  • Подключены актуальные репозитории пакетов.

  • Настроена синхронизация времени.

  • Настроен доступ по SSH.

К управляющему узлу предъявляются те же требования, что и к узлам кластера, однако, работать он должен под управлением ОС ALT Linux c10f2.

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

etcd#

Все соединения etcd используют TLS/HTTPS с взаимной аутентификацией по сертификатам.

Локальный адрес Порт Протокол Описание Клиенты сервиса
127.0.0.1 2379 TCP/HTTPS Клиентский API etcd (локальный). Используется для локальных подключений и мониторинга Patroni (локальные подключения), vip-manager (локальные подключения)
IP-адрес узла 2379 TCP/HTTPS Клиентский API etcd (внешний). Используется для подключений от других узлов кластера Patroni (с других узлов), vip-manager (с других узлов), etcdctl (с других узлов)
127.0.0.1 2380 TCP/HTTPS Peer API etcd (локальный). Используется для коммуникации между узлами кластера etcd Другие узлы etcd (локальные подключения)
IP-адрес узла 2380 TCP/HTTPS Peer API etcd (внешний). Используется для коммуникации между узлами кластера etcd Другие узлы кластера etcd для репликации и выборов лидера

Patroni#

REST API Patroni использует HTTPS с опциональной проверкой клиентских сертификатов.

Локальный адрес Порт Протокол Описание Клиенты сервиса
0.0.0.0 8008 TCP/HTTPS REST API Patroni. Используется для управления кластером PostgreSQL, мониторинга состояния, получения информации о лидере Patroni, системы мониторинга

PostgreSQL#

PostgreSQL использует протокол TCP с аутентификацией через SCRAM-SHA-256. Параметры аутентификации задаются в конфигурационном файле pg_hba.conf.

Локальный адрес Порт Протокол Описание Клиенты сервиса
0.0.0.0 5432 TCP Сервер PostgreSQL. Основной сервис СУБД, управляемый через Patroni Приложения, использующие базу данных, репликация между узлами (пользователь repl)

vip_manager#

vip_manager не является сетевым сервисом и не слушает сетевые порты. Он как клиент подключается к etcd для определения лидера и управляет VIP.

Подготовка управляющего узла#

Подготовьте управляющий узел к работе:

  1. Распакуйте архив с плейбуками в произвольный каталог.

  2. Создайте пару ключей SSH.

  3. Разместите публичный ключ SSH на узлах кластера, например, с помощью команды:

    ssh-copy-id -i /path/to/key.pub <user>@<host>
    

Подготовка узлов кластера#

Чтобы подготовить узлы кластера:

  1. Убедитесь, что время на всех трёх узлах синхронизировано.

  2. Измените настройки сервера OpenSSH таким образом, чтобы он разрешал вход в систему с использованием ключей.

  3. Убедитесь, что настройки sudo разрешают группе wheel выполнение любых команд.

    Как правило, достаточно выполнить команду visudo и в конце файла раскомментировать строку:

    WHEEL_USERS ALL=(ALL:ALL) ALL
    
  4. Убедитесь, что пользователь root состоит в группе wheel.

  5. Убедитесь, что необходимые репозитории подключены и актуальны.

Установка#

После подготовительных работ переходите к установке:

  1. Перейдите в директорию с плейбуком cluster.yml и инвентарём inventory.yml.

  2. Внесите изменения в конфигурационный файл inventory.yml:

    • Укажите параметры подключения к узлам кластера, в том числе путь к приватному ключу SSH.

      Используйте адреса сети, по которой узлы кластера будут взаимодействовать друг с другом.

    • Укажите VIP, который будет назначаться мастеру PostgreSQL.

    • Если узлы кластера работают под управлением ОС ALT Linux c10f1, добавьте в блок vars дополнительную переменную packages_to_install:

      ---
      # ...
      vars:
        # ...
        packages_to_install:
          - postgresql15-server
          - postgresql15-contrib
          - etcd
          - patroni
          - python3-module-psycopg2
      
    • В значении переменной service_users укажите учётные данные администратора СУБД:

      ---
      # ...
      vars:
        # ...
        service_users:
          - name: <admin>
            password: <password>
            flags: SUPERUSER
      
  3. Запустите развёртывание:

    ansible-playbook -i inventory.yml cluster.yml
    

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

Для проверки корректности развёртывания кластера выполните следующие действия:

  1. На любом узле кластера выполните команду:

    patronictl -c /etc/patroni/config.yml topology
    

    Ожидаемый результат выполнения команды:

    • Один узел находится в статусе Leader.

    • Остальные узлы находятся в статусе Replica.

  2. На лидере выполните команду:

    ip -br a
    

    Ожидаемый результат выполнения команды: VIP привязан к одному из сетевых интерфейсов.

  3. Убедитесь в возможности подключения к кластеру с не входящих в него узлов:

    psql -h <vip> -U <admin> -p 5432 -d postgres
    

    Здесь:

    • <vip> — VIP лидера.

    • <admin> — название учётной записи администратора СУБД.

    Подключение должно быть успешным.

  4. Выполните дополнительные проверки:

    • Убедитесь, что на лидере запрос возвращает значение f:

      SELECT pg_is_in_recovery();
      
    • Получите список БД:

    \l+
    
    • Убедитесь, что на лидере выводится информация о репликах:

      SELECT * FROM pg_stat_replication \gx
      
    • Проверьте значение настройки archive_mode.

      По умолчанию её значение равно off.

      SHOW archive_mode;