Установка PostgreSQL в выделенном кластере

В этом разделе описан процесс установки СУБД PostgreSQL в выделенном отказоустойчивом кластере.

Инструкция описывает процесс установки PostgreSQL 16 в выделенном кластере в ОС Debian 11 и РЕД ОС 7.3.

Для установки PostgreSQL согласно этой инструкции требуется:

  • Для PostgreSQL — не менее двух выделенных узлов.

  • Для хранилища конфигураций etcd — нечетное количество выделенных узлов, не менее трех. Рекомендуется использовать три узла.

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

  • хранилище конфигураций etcd;

  • фреймворк для управления кластером Patroni.

Развертывание кластера PostgreSQL состоит из следующих этапов:

Установка etcd

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

  1. Установите etcd.

    Необходимо использовать etcd версии ниже 3.6. Patroni для передачи данных в etcd использует API V2, поддержка которого была прекращена в etcd 3.6.

    • РЕД ОС

    • Debian

    dnf install etcd-3.5.15-2.el7
    apt-get update
    apt-get install etcd=3.3.25+dfsg-6
  2. В терминале создайте переменные окружения, значения которых будут использованы в конфигурационном файле etcd:

    ETCD1="<etcd_1_ip>"
    ETCD2="<etcd_2_ip>"
    ETCD<N>="<etcd_n_ip>"
    ETCD_TOKEN="<etcd_token>"

    Здесь:

    • <etcd_1_ip>, <etcd_2_ip>, <etcd_n_ip> — IP-адреса узлов etcd.

      Необходимо указать IP-адреса всех узлов etcd в формате ETCD<I>="<etcd_i_ip>".

    • <N> — количество узлов в кластере etcd.

    • <etcd_token> — токен доступа к кластеру etcd. Токен представляет собой последовательность из произвольных латинских букв и цифр, например, ArhXS2pIyurzwuFU.

  3. Создайте конфигурационный файл etcd, выполнив команду ниже.

    Перед выполнением команды необходимо заменить шаблоны в угловых скобках (<>) на значения параметров, актуальные для вашего кластера.
    echo -e """
    ETCD_NAME="<etcd_node_name>"
    ETCD_DATA_DIR="/var/lib/etcd"
    ETCD_LISTEN_CLIENT_URLS="http://0.0.0.0:2379"
    ETCD_ADVERTISE_CLIENT_URLS="http://${ETCD<I>}:2379"
    ETCD_LISTEN_PEER_URLS="http://0.0.0.0:2380"
    ETCD_INITIAL_ADVERTISE_PEER_URLS="http://${ETCD<I>}:2380"
    ETCD_INITIAL_CLUSTER_TOKEN="${ETCD_TOKEN:?}"
    # Если в конфигурации вашего кластера более трех выделенных узлов etcd, добавьте их в эту строку.
    ETCD_INITIAL_CLUSTER="etcd1=http://${ETCD1:?}:2380,etcd2=http://${ETCD2:?}:2380,etcd3=http://${ETCD3:?}:2380"
    ETCD_INITIAL_CLUSTER_STATE="new"
    ETCD_ELECTION_TIMEOUT="5000"
    ETCD_HEARTBEAT_INTERVAL="1000"
    ETCD_ENABLE_V2="true"
    """ > cat $(systemctl show -P FragmentPath etcd.service --no-pager) | grep EnvironmentFile | cut -d'-' -f2 | sed 's/%p/etcd/g'

    Здесь:

    • <etcd_node_name> — имя узла кластера etcd, например, etcd1.

    • <I> — номер текущего узла кластера etcd.

  4. Запустите сервис etcd:

    systemctl enable --now etcd
  5. Чтобы убедиться, что etcd успешно запущен, выведите таблицу статусов узлов кластера etcd:

    etcdctl --endpoints="${ETCD1}:2379,${ETCD2}:2379,${ETCD3}:2379" endpoint status --write-out=table

    Если количество узлов etcd в вашем кластере отличается, необходимо соответственно изменить значение аргумента --endpoints. Например, для пяти узлов:

    etcdctl --endpoints="${ETCD1}:2379,${ETCD2}:2379,${ETCD3}:2379,${ETCD4}:2379,${ETCD5}:2379" endpoint status --write-out=table

Установка PostgreSQL и Patroni

Установите пакеты PostgreSQL и Patroni на каждом узле кластера PostgreSQL с помощью команд:

  • РЕД ОС

  • Debian

dnf install -y postgresql16 postgresql16-server postgresql16-contrib patroni python3-psycopg2 patroni-etcd
echo "deb [signed-by=/usr/share/postgresql-common/pgdg/apt.postgresql.org.asc] https://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list
mkdir -p /usr/share/postgresql-common/pgdg/
curl -o /usr/share/postgresql-common/pgdg/apt.postgresql.org.asc --fail https://www.postgresql.org/media/keys/ACCC4CF8.asc
apt-get update
apt-get install -y postgresql-16 postgresql-contrib-16 postgresql-common postgresql-client-16 patroni

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

  1. Проверьте статус сервиса postgresql, выполнив следующую команду:

    systemctl status postgresql

    Сервис не должен быть запущен.

  2. Если сервис postgresql запущен, остановите его и очистите созданные им данные:

    systemctl disable --now postgresql
    rm -rf /var/lib/postgresql/16/main

Настройка Patroni

Создайте конфигурацию сервиса Patroni и запустите его. Для этого выполните следующие действия на каждом узле кластера PostgreSQL:

  1. Создайте директорию для конфигурационного файла, выполнив следующие команды:

    CONFIG_PATH=$(grep -E 'ExecStart.*yml' $(systemctl show -P FragmentPath patroni.service --no-pager) | sed -n 's/.* \(\/.*\.yml\)/\1/p')
    mkdir -p $(dirname $CONFIG_PATH)
  2. В терминале создайте переменные окружения, значения которых будут использованы в конфигурационном файле Patroni:

    • РЕД ОС

    • Debian

    ETCD1_IP="<etcd_1_ip>"
    ETCD2_IP="<etcd_2_ip>"
    ETCD<M>_IP="<etcd_m_ip>"
    POSTGRES1_IP="<postgres_1_ip>"
    POSTGRES2_IP="<postgres_2_ip>"
    POSTGRES<N>_IP="<postgres_n_ip>"
    POSTGRES_PASSWORD="<postgres_password>"
    REPLICATOR_PASSWORD="<replicator_password>"
    ETCD_PORT="2379"
    PATRONI_SCOPE_NAME="<patroni_scope_name>"
    RESTAPI_PASSWORD="<rest_api_pass>"
    
    DATA_DIR="/var/lib/pgsql/16/data"
    BIN_DIR="/usr/pgsql-16/bin"
    CONFIG_DIR="/var/lib/pgsql/16/data"
    ETCD1_IP="<etcd_1_ip>"
    ETCD2_IP="<etcd_2_ip>"
    ETCD<M>_IP="<etcd_m_ip>"
    POSTGRES1_IP="<postgres_1_ip>"
    POSTGRES2_IP="<postgres_2_ip>"
    POSTGRES<N>_IP="<postgres_n_ip>"
    POSTGRES_PASSWORD="<postgres_password>"
    REPLICATOR_PASSWORD="<replicator_password>"
    ETCD_PORT="2379"
    PATRONI_SCOPE_NAME="<patroni_scope_name>"
    RESTAPI_PASSWORD="<rest_api_pass>"
    
    DATA_DIR="/var/lib/postgresql/16/main"
    BIN_DIR="/usr/lib/postgresql/16/bin"
    CONFIG_DIR="/etc/postgresql/16/main"

    Здесь:

    • <etcd_1_ip>, <etcd_2_ip>, <etcd_m_ip> — IP-адреса соответствующих узлов etcd.

    • <M> — количество узлов в кластере etcd.

      Необходимо указать IP-адреса всех узлов etcd в формате ETCD<I>_IP="<etcd_i_ip>".

    • <postgres_1_ip>, <postgres_2_ip>, <postgres_n_ip> — IP-адреса соответствующих узлов PostgreSQL.

      Необходимо указать IP-адреса всех узлов PostgreSQL в формате POSTGRES<I>_IP="<postgres_i_ip>".

    • <N> — количество узлов в кластере PostgreSQL.

    • <postgres_password> — пароль пользователя postgres.

      Этот пароль потребуется указать на этапе PostgreSQL setup установки системы.
    • <replicator_password> — пароль пользователя replicator. Учетная запись replicator используется для репликации данных между узлами кластера PostgreSQL.

    • <patroni_scope_name> — имя кластера PostgreSQL для Patroni, например, evo.

    • <rest_api_pass> — пароль для взаимодействия между узлами Patroni по REST API.

  3. Создайте конфигурационный файл Patroni, выполнив команду ниже.

    Перед выполнением команды необходимо заменить шаблоны в угловых скобках (<>) на значения параметров, актуальные для вашего кластера.
    echo -e """name: <postgres_node_name>
    scope: ${PATRONI_SCOPE_NAME:?}
    
    log:
      level: WARNING
      format: '%(asctime)s %(levelname)s: %(message)s'
      dateformat: ''
      max_queue_size: 1000
      dir: /var/log/postgresql
      file_num: 4
      file_size: 10000000
      loggers:
        postgres.postmaster: WARNING
        urllib3: DEBUG
    
    etcd:
      hosts:
      - ${ETCD1_IP:?}:${ETCD_PORT:?}
      - ${ETCD2_IP:?}:${ETCD_PORT}
      # Здесь необходимо перечислить все узлы кластера etcd согласно шаблону:
      # - ${ETCD<I>_IP:?}:${ETCD_PORT}
      - ${ETCD<M>_IP:?}:${ETCD_PORT}
    
    restapi:
      listen: 0.0.0.0:8008
      connect_address: ${POSTGRES<I>_IP}:8008
      authentication:
        username: patroni
        password: ${RESTAPI_PASSWORD:?}
    
    bootstrap:
      dcs:
        ttl: 30
        loop_wait: 10
        retry_timeout: 10
        maximum_lag_on_failover: 1048576
        postgresql:
          use_pg_rewind: true
          use_slots: true
          parameters:
            archive_mode: 'off'
            archive_command: 'mkdir -p ../wal_archive && test ! -f ../wal_archive/%f && cp %p ../wal_archive/%f'
            autovacuum: 'on'
            autovacuum_max_workers: '6'
            autovacuum_vacuum_scale_factor: '0.1'
            autovacuum_analyze_scale_factor: '0.05'
            autovacuum_vacuum_threshold: '50'
            effective_io_concurrency: '100'
            hot_standby: 'on'
            listen_addresses: '*'
            maintenance_work_mem: '256MB'
            max_connections: 500
            max_replication_slots: '10'
            max_wal_senders: '10'
            port: '5432'
            random_page_cost: '1.1'
            seq_page_cost: '1'
            shared_buffers: '512MB'
            shared_preload_libraries: 'pg_stat_statements'
            timezone: 'UTC'
            wal_compression: 'off'
            wal_level: 'replica'
            wal_keep_segments: '8'
            wal_log_hints: 'on'
            work_mem: '16MB'
            standard_conforming_strings: 'on'
            escape_string_warning: 'on'
            backslash_quote: 'safe_encoding'
    
      initdb:
      - encoding: UTF8
      - locale: en_US.UTF-8
      - data-checksums
      pg_hba:
      - host replication replicator ${POSTGRES1_IP:?}/32 scram-sha-256
      - host replication replicator ${POSTGRES2_IP:?}/32 scram-sha-256
      # Здесь необходимо перечислить все узлы кластера PostgreSQL согласно шаблону:
      # - host replication replicator ${POSTGRES<I>_IP:?}/32 scram-sha-256
      - host replication replicator ${POSTGRES<N>_IP:?}/32 scram-sha-256
      - host all all 0.0.0.0/0 scram-sha-256
      users:
        postgres:
          password: ${POSTGRES_PASSWORD:?}
        replicator:
          password: ${REPLICATOR_PASSWORD:?}
          options:
            - replication
    
    postgresql:
      listen: 0.0.0.0:5432
      connect_address: ${POSTGRES<I>_IP}:5432
      data_dir: ${DATA_DIR:?}
      bin_dir: ${BIN_DIR:?}
      config_dir: ${CONFIG_DIR:?}
      pgpass: /tmp/pgpass
      pg_hba:
        - local     all             all                             scram-sha-256
        - host      all             postgres        all             scram-sha-256
        - host      replication     replicator      ${POSTGRES1_IP}/32 scram-sha-256
        # Здесь необходимо перечислить все узлы кластера PostgreSQL согласно шаблону:
        # - host      replication     replicator      ${POSTGRES<I>_IP}/32 scram-sha-256
        - host      replication     replicator      ${POSTGRES2_IP}/32 scram-sha-256
        - host      replication     replicator      127.0.0.1/32    scram-sha-256
        - host      all             all             0.0.0.0/0       scram-sha-256
      authentication:
        superuser:
          username: postgres
          password: ${POSTGRES_PASSWORD}
        replication:
          username: replicator
          password: ${REPLICATOR_PASSWORD}
      parameters:
        unix_socket_directories: '/var/run/postgresql'
        stats_temp_directory: /var/run/postgresql/16-main.pg_stat_tmp
        log_autovacuum_min_duration: 60s2
        log_checkpoints: 'on'
        log_connections: 'on'
        log_disconnections: 'on'
        log_line_prefix: '%m [%p]: [%l-1] db=%d,user=%u,app=%a,client=%h'
        log_lock_waits: 'on'
        log_min_duration_statement: '30s'
        log_min_error_statement: 'NOTICE'
        log_min_messages: 'WARNING'
        log_statement: 'ddl'
        log_temp_files: '0'
        log_timezone: 'UTC'
        log_truncate_on_rotation: 'on'
        log_destination: 'stderr'
        log_file_mode: '0600'
        log_error_verbosity: 'verbose'
        logging_collector: 'on'
        datestyle: 'iso, dmy'
        password_encryption: 'scram-sha-256'
        tags:
        nofailover: false
        noloadbalance: false
        clonefrom: false
        nosync: false
    """ > ${CONFIG_PATH:?}

    Здесь:

    • <postgres_node_name> — имя узла кластера PostgreSQL, например, postgres1.

    • <M> — количество узлов в кластере etcd.

    • <I> — номер текущего узла кластера PostgreSQL.

    • <N> — количество узлов в кластере PostgreSQL.

  4. Чтобы убедиться, что файл конфигурации создан успешно, выведите его, выполнив следующую команду:

    patronictl -c ${CONFIG_PATH} show-config
  5. Создайте директории для хранения логов PostgreSQL, выполнив следующие команды:

    mkdir -p /var/log/postgresql
    chown postgres:postgres /var/log/postgresql
  6. Запустите сервис Patroni:

    systemctl enable --now patroni
  7. Чтобы убедиться, что Patroni успешно запущен, выведите список узлов кластера PostgreSQL, активных на текущий момент:

    patronictl -c ${CONFIG_PATH} list

После установки кластера PostgreSQL рекомендуется настроить балансировку запросов к его узлам. Методы балансировки запросов к СУБД описаны в разделе Настройка балансировки запросов к ClickHouse и PostgreSQL.

Была ли полезна эта страница?

Обратная связь