Patroni

Patroni — это Python-приложение для создания высокодоступных кластеров QHB на основе потоковой репликации. Оно используется такими компаниями, как Red Hat, IBM Compose, Zalando и многие другие. С его помощью можно преобразовать систему из основного и резервного серверов в высокодоступный кластер с поддержкой автоматического контролируемого и аварийного переключения. Patroni позволяет легко добавлять новые реплики в существующий кластер, поддерживает динамическое изменение конфигурации QHB одновременно на всех серверах кластера, а также множество других возможностей, таких как синхронная репликация, настраиваемые действия при переключении узлов, REST API, возможность запуска пользовательских команд для создания реплики.

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

  • QHB в качестве СУБД;
  • Patroni в качестве решения для кластеризации;
  • etcd или consul в качестве распределенного хранилища для Patroni.

Patroni является приложением с открытым исходным кодом, поэтому для удобства использования и для совместимости с QHB мы вносим изменения в исходные пакеты. Совместимые пакеты Patroni находятся в репозиториях QHB.


Установка компонентов

Установка etcd

Пример установки на CentOS 7:

yum install etcd

Также возможна установка через пакеты или исходный код по документации на установку etcd.

Рекомендуется устанавливать etcd на отдельных машинах, где не будут установлены узлы Patroni и QHB, так как для etcd очень важна нагрузка на диски. Для штатной работы кластера etcd минимальное количество узлов — три. Для разработки и тестирования можно использовать один узел.

Установка Consul

В связи с ограничениями Hashicorp на данный момент установка возможна только с использованием VPN.

Установка выполняется через пакеты с ресурса pkgs.org, либо по документации на установку Consul.

Серверы Consul — это место, где хранятся и реплицируются данные Patroni. Поэтому рекомендованное минимальное количество узлов — три. Для разработки и тестирования можно использовать один узел. Для продуктивных высоконагруженных систем следует разворачивать сервисы Consul на отдельных от Patroni и QHB машинах.

Клиент Consul также является членом системы и может подключаться к кластеру серверов Consul для получения информации об инфраструктуре. Клиента можно расположить на сервере с Patroni и QHB для подключения к кластеру серверов Consul через локального клиента Consul.


Установка QHB

Для установки обратитесь к документации по установке QHB.

Создание и запуск сервиса QHB, а также инициализация кластера базы данных не требуется. Все управление кластером СУБД осуществляется через Patroni.

Установка Patroni

Patroni требуется установить на тех же машинах, где уже установлены серверы QHB.

Имя пакета для установки qhb-patroni

Для установки обратитесь к документации по установке QHB.

Обращаем внимание, что для работы с QHB выпущен специализированный пакет qhb-patroni. Стандартный Patroni для PostgreSQL не может использоваться совместно с QHB.

Проверьте версию qhb-patroni:

patroni --version

Результат: Patroni 3.0.2


Настройка компонентов

Настройка etcd

Выполняется независимо от Patroni и QHB, может быть выполнена предварительно (подробнее см. в официальной документации etcd). Для конфигурации каждого узла etcd нужно внести необходимые для запуска параметры в файл /etc/etcd/etcd.conf. Также предварительно на каждом из узлов необходимо создать каталог под данные etcd, например /var/lib/etcd/default.etcd. Ниже представлен пример минимальной конфигурации узлов на 3 машинах с адресами: X.X.X.101, X.X.X.102, X.X.X.103.

Для первого узла:

ETCD_DATA_DIR="/var/lib/etcd/default.etcd"
ETCD_LISTEN_PEER_URLS="http://X.X.X.101:2380"
ETCD_LISTEN_CLIENT_URLS="http://X.X.X.101:2379,http://127.0.0.1:2379"
ETCD_NAME="etcd0"
ETCD_INITIAL_ADVERTISE_PEER_URLS="http://X.X.X.101:2380"
ETCD_ADVERTISE_CLIENT_URLS="http://X.X.X.101:2379"
ETCD_INITIAL_CLUSTER="etcd0=http://X.X.X.101:2380,etcd1=http://X.X.X.102:2380,etcd2=http://X.X.X.103:2380"
ETCD_INITIAL_CLUSTER_TOKEN="qhb_token"

Для второго узла:

ETCD_DATA_DIR="/var/lib/etcd/default.etcd"
ETCD_LISTEN_PEER_URLS="http://X.X.X.102:2380"
ETCD_LISTEN_CLIENT_URLS="http://X.X.X.102:2379,http://127.0.0.1:2379"
ETCD_NAME="etcd1"
ETCD_INITIAL_ADVERTISE_PEER_URLS="http://X.X.X.102:2380"
ETCD_ADVERTISE_CLIENT_URLS="http://X.X.X..102:2379"
ETCD_INITIAL_CLUSTER="etcd0=http://X.X.X.101:2380,etcd1=http://X.X.X.102:2380,etcd2=http://X.X.X.103:2380"
ETCD_INITIAL_CLUSTER_TOKEN="qhb_token"

Для третьего узла:

ETCD_DATA_DIR="/var/lib/etcd/default.etcd"
ETCD_LISTEN_PEER_URLS="http://X.X.X.103:2380"
ETCD_LISTEN_CLIENT_URLS="http://X.X.X.103:2379,http://127.0.0.1:2379"
ETCD_NAME="etcd2"
ETCD_INITIAL_ADVERTISE_PEER_URLS="http://X.X.X.103:2380"
ETCD_ADVERTISE_CLIENT_URLS="http://X.X.X.103:2379"
ETCD_INITIAL_CLUSTER="etcd0=http://X.X.X.101:2380,etcd1=http://X.X.X.102:2380,etcd2=http://X.X.X.103:2380"
ETCD_INITIAL_CLUSTER_TOKEN="qhb_token"

Базу данных etcd при пересоздании кластера нужно переинициализировать, удаляя данные в каталоге /var/lib/etcd/default.etcd.

Создайте сервис etcd на каждом из узлов для удобного управления кластером:

[Unit]
Description=Etcd Server
After=network.target
After=network-online.target
Wants=network-online.target

[Service]
Type=notify
WorkingDirectory=/var/lib/etcd/
EnvironmentFile=-/etc/etcd/etcd.conf
User=etcd
# установить в GOMAXPROCS число процессоров
ExecStart=/bin/bash -c "GOMAXPROCS=$(nproc) /usr/bin/etcd --name=\"${ETCD_NAME}\" --data-dir=\"${ETCD_DATA_DIR}\" --listen-client-urls=\"${ETCD_LISTEN_CLIENT_URLS}\""
Restart=on-failure
LimitNOFILE=65536

[Install]
WantedBy=multi-user.target

Настройка Consul

Выполняется независимо от Patroni и QHB, может быть выполнена предварительно (подробнее см. в официальной документации Consul). Для конфигурации каждого узла кластера серверов consul нужно внести необходимые для запуска параметры в файл /etc/consul.d/config.json.

Ниже представлен пример минимальной конфигурации узлов на 3 машинах. Адреса и доменные имена:

X.X.X.101, qhb-srv-01.quantom.local;
X.X.X.102, qhb-srv-02.quantom.local;
X.X.X.103, qhb-srv-03.quantom.local.

Для первого узла кластера серверов consul (для второго и третьего узла изменить bind_addr и client_addr):

{
  "bind_addr": "X.X.X.101",
  "bootstrap_expect": 3,
  "client_addr": "X.X.X.101",
  "datacenter": "dc1",
  "data_dir": "/opt/consul",
  "domain": "consul",
  "enable_script_checks": true,
  "dns_config": {
    "enable_truncate": true,
    "only_passing": true
  },
  "enable_syslog": true,
  "encrypt": "v6+HtK6JQ6kX2XgYkSFQM9KFXF1YeGyFHcRo6hWZbjI=",
  "leave_on_terminate": true,
  "log_level": "INFO",
  "rejoin_after_leave": true,
  "retry_join": [
    "qhb-srv-01.quantom.local",
    "qhb-srv-02.quantom.local",
    "qhb-srv-03.quantom.local"
  ],
  "server": true,
  "start_join": [
    "qhb-srv-01.quantom.local",
    "qhb-srv-02.quantom.local",
    "qhb-srv-03.quantom.local"
  ],
  "ui_config": { "enabled": true }
}

Для подключения к кластеру серверов consul можно создать клиента consul (например, разместить на серверах с Patroni). При такой конфигурации Patroni подключается к локальному клиенту consul, который обращается ко всему кластеру серверов consul.

Для конфигурации клиента consul необходимо внести необходимые для запуска параметры в файл /etc/consul.d/config.json.

Пример минимальной конфигурации клиента:

{
  "bind_addr": "X.X.X.104",
  "client_addr": "X.X.X.104",
  "datacenter": "dc1",
  "node_name": "client01",
  "data_dir": "/opt/consul",
  "domain": "consul",
  "enable_script_checks": true,
  "dns_config": {
    "enable_truncate": true,
    "only_passing": true
  },
  "enable_syslog": true,
  "encrypt": "v6+HtK6JQ6kX2XgYkSFQM9KFXF1YeGyFHcRo6hWZbjI=",
  "leave_on_terminate": true,
  "log_level": "INFO",
  "rejoin_after_leave": true,
  "retry_join": [
    "qhb-srv-01.quantom.local",
    "qhb-srv-02.quantom.local",
    "qhb-srv-03.quantom.local"
  ],
  "server": false,
  "start_join": [
    "qhb-srv-01.quantom.local",
    "qhb-srv-02.quantom.local",
    "qhb-srv-03.quantom.local"
  ],
  "ui_config": { "enabled": true }
}

Каждую конфигурацию необходимо проверить на допустимость:

consul validate /etc/consul.d/config.json

Создайте сервис consul на каждом из узлов для удобного управления кластером:

[Unit]
Description=Consul Service Discovery Agent
Documentation=https://www.consul.io/
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
User=consul
Group=consul
ExecStart=/usr/bin/consul agent \
    -node=qhb-srv-01.quantom.local \
    -config-dir=/etc/consul.d
ExecReload=/bin/kill -HUP $MAINPID
KillSignal=SIGINT
TimeoutStopSec=5
Restart=on-failure
SyslogIdentifier=consul

[Install]
WantedBy=multi-user.target

Настройка Patroni

На каждом хосте с qhb-patroni необходимо создать директорию под кластер баз данных QHB и раздать необходимые права пользователю qhb, например, /mnt/patroni:

mkdir -p /mnt/patroni
chown qhb:qhb /mnt/patroni
chmod 700 /mnt/patroni

Создайте конфигурационный файл с расширением .yml на каждом хосте с qhb-patroni. Можете скопировать примеры конфигурационных файлов в rpm системах /usr/share/doc/patroni-3.0.2/qhb1.yml (qhb2.yml) и в deb системах /usr/share/doc/patroni/qhb1.yml (qhb2.yml) Подробнее параметры конфигурации описаны в документации Patroni.

Кроме основных параметров конфигурации, указанных в документации Patroni, в реализации qhb-patroni добавлены дополнительные параметры для управления QHB:

# параметры QHB
  hba_file: qhb_hba.conf
  ident_file: qhb_ident.conf
  database: qhb
  config_base_name: qhb

Ниже представлен пример минимальной конфигурации кластера qhb-patroni на 2 хостах с адресами: X.X.X.104, X.X.X.105.

Примечание
В примере указаны параметры подключения к etcd, для работы с consul раскомментируйте и добавьте необходимые строки.

qhb0.yml для первого узла кластера qhb-patroni:

scope: cluster
# пространство имен: /служба/
name: qhb0

restapi:
  listen: 127.0.0.1:8008
  connect_address: 127.0.0.1:8008

etcd:
  # Использовать «хосты» для предоставления нескольких рабочих станций
  hosts:
    - X.X.X.101:2379
    - X.X.X.102:2379
    - X.X.X.103:2379

  #consul:
  #хост: X.X.X.104:8500

bootstrap:
  # этот раздел будет записан в etcd/Consul:/<пространство_имен>/<область_применения>/config
  # после инициализации нового кластера, и все остальные члены кластера будут
  # использовать его в качестве «общих настроек»
  dcs:
    ttl: 30
    loop_wait: 10
    retry_timeout: 10
    maximum_lag_on_failover: 1048576
    postgresql:
      use_pg_rewind: true
  # некоторые желаемые параметры для 'initdb'
  initdb:  # Примечание: Это должен быть список (для некоторых параметров
    # нужны значения, а другие являются флагами)
    - encoding: UTF8
    - data-checksums

  pg_hba:  # Добавить следующие строки в qhb_hba.conf после запуска 'initdb'
    - host replication replicator 127.0.0.1/32 md5
    - host replication replicator X.X.X.0/24 md5
    - host all all 0.0.0.0/0 md5

  # Некоторые дополнительные пользователи, которых нужно создать после
  # инициализации нового кластера
  users:
    admin:
      password: admin
      options:
        - createrole
        - createdb
postgresql:
  listen: 127.0.0.1,X.X.X.104,::1:5432
  connect_address: X.X.X.104:5432
  data_dir: /mnt/patroni
  bin_dir: /usr/local/qhb/bin
  pgpass: /tmp/pgpass0
  authentication:
    replication:
      username: replicator
      password: rep-pass
    superuser:
      username: qhb
      password: qhb
    rewind:
      username: rewind_user
      password: rewind_password
  parameters:
    unix_socket_directories: '.'
  # параметры QHB
  hba_file: qhb_hba.conf
  ident_file: qhb_ident.conf
  database: qhb
  config_base_name: qhb

tags:
  nofailover: false
  noloadbalance: false
  clonefrom: false

qhb1.yml для второго узла кластера qhb-patroni:

scope: cluster
# пространство имен: /служба/
name: qhb1

restapi:
  listen: 127.0.0.1:8008
  connect_address: 127.0.0.1:8008

etcd:
  # Использовать «хосты» для предоставления нескольких рабочих станций
  hosts:
    - X.X.X.101:2379
    - X.X.X.102:2379
    - X.X.X.103:2379

  #consul:
  #хост: X.X.X.105:8500

bootstrap:
  # этот раздел будет записан в etcd/Consul:/<пространство_имен>/<область_применения>/config
  # после инициализации нового кластера, и все остальные члены кластера будут
  # использовать его в качестве «общих настроек»
  dcs:
    ttl: 30
    loop_wait: 10
    retry_timeout: 10
    maximum_lag_on_failover: 1048576
    postgresql:
      use_pg_rewind: true
  # некоторые желаемые параметры для 'initdb'
  initdb:  # Примечание: Это должен быть список (для некоторых параметров
    # нужны значения, а другие являются флагами)
    - encoding: UTF8
    - data-checksums

  pg_hba:  # Добавить следующие строки в qhb_hba.conf после запуска 'initdb'
    - host replication replicator 127.0.0.1/32 md5
    - host replication replicator X.X.X.0/24 md5
    - host all all 0.0.0.0/0 md5

  # Некоторые дополнительные пользователи, которых нужно создать после инициализации нового кластера
  users:
    admin:
      password: admin
      options:
        - createrole
        - createdb
postgresql:
  listen: 127.0.0.1,X.X.X.105,::1:5432
  connect_address: X.X.X.105:5432
  data_dir: /mnt/patroni
  bin_dir: /usr/local/qhb/bin
  pgpass: /tmp/pgpass0
  authentication:
    replication:
      username: replicator
      password: rep-pass
    superuser:
      username: qhb
      password: qhb
    rewind:
      username: rewind_user
      password: rewind_password
  parameters:
    unix_socket_directories: '.'
  # параметры QHB
  hba_file: qhb_hba.conf
  ident_file: qhb_ident.conf
  database: qhb
  config_base_name: qhb

tags:
  nofailover: false
  noloadbalance: false
  clonefrom: false

Для проверки работоспособности необходимо провести проверку конфигурации и при необходимости исправить все ошибки, например, если конфигурация первого узла кластера расположена в /opt/patroni/:

patroni --validate-config /opt/patroni/qhb0.yml

При необходимости создайте сервис qhb-patroni на каждом из узлов для удобного управления кластером qhb-patroni. Сервис располагается в /usr/lib/systemd/system/qhb-patroni.service.

# Это пример файла конфигурации systemd для Patroni
# Вы можете скопировать его в "/etc/systemd/system/patroni.service",

[Unit]
Description=Runners to orchestrate a high-availability QHB
After=syslog.target network.target

[Service]
Type=simple

User=qhb
Group=qhb

# Прочитать в файле конфигурации, если таковой существует, иначе продолжить
EnvironmentFile=-/etc/patroni_env.conf

# WorkingDirectory = /var/lib/pgsql

# Куда отправлять сообщения о раннем запуске от сервера
# Обычно это определяется общей настройкой в systemd
#StandardOutput=syslog

# Прекоманды для запуска устройства наблюдения
# Конвертировать комментарий, если устройство наблюдения является частью вашей установки patroni
#ExecStartPre=-/usr/bin/sudo /sbin/modprobe softdog
#ExecStartPre=-/usr/bin/sudo /bin/chown qhb /dev/watchdog

# Запустить процесс patroni
# См. примеры файлов конфигурации для QHB в /usr/share/doc/patroni-3.0.2/qhb*.yml
ExecStart=/usr/bin/patroni /opt/qhb1.yml

# Переслать HUP для загрузки с patroni.yml
ExecReload=/usr/bin/kill -s HUP $MAINPID

# приостановить процесс patroni, но не его дочерние процессы, чтобы он постепенно остановил qhb
KillMode=process

# Выждать достаточное время, чтобы сервер запустился/остановился
TimeoutSec=30

# Не перезапускать службу в случае сбоя; мы хотим вручную проверить базу данных на ошибки
Restart=no

[Install]
WantedBy=multi-user.target


Запуск компонентов

Запуск etcd

Предварительно убедитесь, что у вас добавлены необходимые правила в firewall. Для запуска etcd через сервис на всех узлах необходимо выполнить systemctl start etcd. Команда на всех узлах завершится, когда узлы найдут друг друга, т. е. когда команда будет выполнена на втором и третьем хосте. При пересоздании кластера нужно предварительно очистить базы etcd.

Состав кластера etcd можно посмотреть командой etcdctl member list.

Запуск Consul

Предварительно убедитесь, что у вас добавлены необходимые правила в firewall.

Для запуска etcd через сервис на всех узлах серверов и клиентах необходимо выполнить systemctl start consul.

По адресу http(s) любого участника кластера, например http://X.X.X.101:8500, можно посмотреть состав кластера (сервера и клиенты) и текущего лидера. Подробнее в официальной документации Consul.

Запуск Patroni

Предварительно убедитесь, что у вас добавлены необходимые правила в firewall.

Запуск необходимо производить только после запуска распределенного хранилища — etcd или consul.

Для запуска первого узла qhb-patroni необходимо из под пользователя qhb выполнить patroni /opt/qhb0.yml. При успешном запуске первого узла также запустите остальные узлы, указав соответствующие файлы конфигурации.

Для запуска qhb-patroni через сервис на всех узлах необходимо выполнить systemctl start qhb-patroni.

Состояние и состав кластера qhb-patroni можно посмотреть на любом узле, например patronictl -c /opt/qhb0.yml list.

При штатной работе вы увидите State — running у всех участников кластера.


Работа, переключение

При остановке работы СУБД на хосте 104 СУБД на хосте 105 становится основной.

При включении в работу СУБД на хосте 104 она становится резервной.

Если останавливается работа мастера на хосте 105 основным становится хост 104.


См. также