Хабр, привет!
В этом материале будем настраивать кластер PostgreSQL с Patroni и etcd. Видели множество статей на эту тему, но наше отличие в том, что мы устанавливаем кластер в виртуальной среде, используя новые компоненты.
Немного теории. Patroni — это инструмент для управления высокодоступными кластерами PostgreSQL. Он упрощает настройку и управление репликацией благодаря автоматическому переключению на резервные узлы и восстановлению после сбоев.
В нашем материале мы рассмотрим настройку такого кластера с использованием etcd для координации, а еще будем использовать только пакеты для ручной установки. Потому что частенько в локальных репозиториях преобладают старые пакеты, в которых есть уязвимости. В таких случаях лучше устанавливать пакеты вручную.
Зачем мы это делаем?
Во-первых, интересно. Во-вторых, это нам позволит установить последние версии пакетов без открытого доступа в интернет с серверов. Во многих компаниях изолированная сетевая среда — поэтому вот вам памятка по такой задаче.:)
Итак, приступим.
Систему можно использовать любую, автору захотелось Centos 8 (личное предпочтение автора, не более — прим. ред.). Совет: лучше заранее описать, какие будут имя сервера и IP-адреса. Сетевая структура у нас такая:
etcd1 192.168.60.141 etcd2 192.168.60.142 etcd3 192.168.60.143 node1 192.168.60.131 node2 192.168.60.132
У вас могут быть и другие адреса, поэтому не забудьте их поменять в конфигах.
Установка и настройка etcd
Шаг 1: скачиваем etcd
Для этого качаем пакет с оф. гита etcd вот отсюда: https://github.com/etcd-io/etcd/releases/download/v3.5.15/etcd-v3.5.15-linux-amd64.tar.gz
Затем распаковываем архив и перемещаем файлы:
tar -xzvf etcd-v3.5.15-linux-amd64.tar.gz sudo mv etcd-v3.5.15-linux-amd64/etcd* /usr/bin/
Шаг 2: создаем пользователей и директории
1. Выполняем следующие команды:
sudo groupadd --system etcd sudo useradd -s /sbin/nologin --system -g etcd etcd
2. Теперь создаем необходимые директории и устанавливаем права доступа с помощью:
sudo mkdir -p /var/lib/etcd /etc/default/etcd/.tls sudo chown -R etcd:etcd /var/lib/etcd /etc/default/etcd ```
Шаг 3: генерируем сертификаты
Если у вас нет возможности использовать собственные сертификаты, то берем самописные. Небольшой скрипт ниже в этом нам поможет:
Скрытый текст
#!/bin/bash # Директория для сертификатов: CERT_DIR="/etc/default/etcd/.tls" mkdir -p ${CERT_DIR} cd ${CERT_DIR} # Создание CA-сертификата: openssl genrsa -out ca.key 4096 openssl req -x509 -new -key ca.key -days 10000 -out ca.crt -subj "/C=RU/ST=Moscow Region/L=Moscow/O=MyOrg/OU=MyUnit/CN=myorg.com" # Функция для генерации сертификатов для нод: generate_cert() { NODE_NAME=$1 NODE_IP=$2 cat <<EOF > ${CERT_DIR}/${NODE_NAME}.san.conf [ req ] default_bits = 4096 distinguished_name = req_distinguished_name req_extensions = req_ext [ req_distinguished_name ] countryName = RU stateOrProvinceName = Moscow Region localityName = Moscow organizationName = MyOrg commonName = ${NODE_NAME} [ req_ext ] subjectAltName = @alt_names [ alt_names ] DNS.1 = ${NODE_NAME} IP.1 = ${NODE_IP} IP.2 = 127.0.0.1 EOF openssl genrsa -out ${NODE_NAME}.key 4096 openssl req -config ${NODE_NAME}.san.conf -new -key ${NODE_NAME}.key -out ${NODE_NAME}.csr -subj "/C=RU/ST=Moscow Region/L=Moscow/O=MyOrg/CN=${NODE_NAME}" openssl x509 -extfile ${NODE_NAME}.san.conf -extensions req_ext -req -in ${NODE_NAME}.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out ${NODE_NAME}.crt -days 10000 rm -f ${NODE_NAME}.san.conf ${NODE_NAME}.csr } # Список нод etcd и их IP-адресов: ETCD_NODES=("etcd01" "etcd02" "etcd03") ETCD_IPS=("192.168.60.141" "192.168.60.142" "192.168.60.143") # Список нод Patroni и их IP-адресов: PATRONI_NODES=("node01" "node02") PATRONI_IPS=("192.168.60.131" "192.168.60.132") # Генерация сертификатов для нод etcd: for i in "${!ETCD_NODES[@]}"; do generate_cert "${ETCD_NODES[$i]}" "${ETCD_IPS[$i]}" done # Генерация сертификатов для нод Patroni: for i in "${!PATRONI_NODES[@]}"; do generate_cert "${PATRONI_NODES[$i]}" "${PATRONI_IPS[$i]}" done chown -R etcd:etcd ${CERT_DIR} chmod 600 ${CERT_DIR}/*.key chmod 644 ${CERT_DIR}/*.crt echo "Сертификаты успешно сгенерированы и сохранены в ${CERT_DIR}"
Запускаем скрипт:
chmod +x generate_etcd_certs.sh sudo ./generate_etcd_certs.sh
Сделали. Чтобы узлы etcd взаимодействовали между собой, копируем ca.crt и node[01 или 03] на остальные узлы.
Теперь меняем права на всех узлах etcd:
chown -R etcd:etcd /etc/default/etcd/.tls chmod -R 744 /etc/default/etcd/.tls chmod 600 /etc/default/etcd/.tls/*.key
Шаг 4: определяем, как должен работать etcd (параметры)
На каждой ноде создаем конфиг, который минимально отличается от ноды к ноде (подсветили комментариями):
# /etc/etcd/etcd.conf.yml name: etcd01 # Изменить на других нодах data-dir: /var/lib/etcd/default listen-peer-urls: https://0.0.0.0:2380 listen-client-urls: https://0.0.0.0:2379 advertise-client-urls: https://etcd01:2379 # Изменить на других нодах initial-advertise-peer-urls: https://etcd01:2380 # Изменить на других нодах initial-cluster-token: etcd_scope initial-cluster: etcd01=https://etcd01:2380,etcd02=https://etcd02:2380,etcd03=https://etcd03:2380 initial-cluster-state: new election-timeout: 5000 heartbeat-interval: 500 client-transport-security: cert-file: /etc/default/etcd/.tls/etcd01.crt # Изменить на других нодах key-file: /etc/default/etcd/.tls/etcd01.key client-cert-auth: true trusted-ca-file: /etc/default/etcd/.tls/ca.crt peer-transport-security: cert-file: /etc/default/etcd/.tls/etcd01.crt # Изменить на других нодах key-file: /etc/default/etcd/.tls/etcd01.key client-cert-auth: true trusted-ca-file: /etc/default/etcd/.tls/ca.crt
Шаг 5: для запуска etcd cоздаем Systemd-Unit-файл
Как правило, сервис создается по следующему пути (мы использовали его): /etc/systemd/system/etcd.service
[Unit] Description=etcd key-value store Documentation=https://etcd.io/docs/ Wants=network-online.target After=network-online.target [Service] User=etcd Type=notify ExecStart=/usr/bin/etcd --config-file=/etc/etcd/etcd.conf.yml Restart=always RestartSec=5 LimitNOFILE=40000 [Install] WantedBy=multi-user.target
Шаг 6: применяем следующие команды
sudo systemctl daemon-reload sudo systemctl enable etcd
Заметка на полях: Помним, что любое изменение конфига Systemd для новых настроек требует выполнения команд выше. А также не забываем, что поезд etcd ждать не будет 🙂 (у нас есть только 30 секунд, чтобы запустить другие ноды кластера).
На этом этапе поочередно запускаем сервис с 1-й по 3-ю ноду с помощью команды: sudo systemctl start etcd
Шаг 7: настраиваем alias для etcdctl
Для этого добавляем alias в наш `~/.bashrc` или `~/.zshrc`:
echo ‘alias ectl=»etcdctl —cacert=/etc/default/etcd/.tls/ca.crt —cert=/etc/default/etcd/.tls/$(hostname).crt —key=/etc/default/etcd/.tls/$(hostname).key —endpoints=https://etcd01:2379,https://etcd02:2379,https://etcd03:2379«‘ >> ~/.bashrc
source ~/.bashrc
Благодаря этому мы получаем статус кластера etcd, не прописывая каждый раз сертификаты.
Примечание. Учтите, что имя crt и key нод должно быть аналогично hostname. Иначе команда выше не сработает и придется все настраивать вручную.
Получаем удобную таблицу:
После того как кластер запустился, на всех узлах редактируем конфиг `/etc/default/etcd` и устанавливаем параметр:
ETCD_INITIAL_CLUSTER_STATE="existing" ```
Перезапускаем службу:
systemctl restart etcd
Фух! С etcd закончили, 🙂 приступаем к Postgres и Patroni.
Установка PostgreSQL
Шаг 1: скачиваем и устанавливаем пакеты из оф. репозитория
Делаем это отсюда: https://download.postgresql.org/pub/repos/
NB: В системе по умолчанию создается daemon PostgreSQL. Его требуется отключить. Применяем команду:
systemctl --now disable postgresql-16
Затем меняем настройки пользователя Postgres при необходимости:
mkdir /home/postgres chown postgres:postgres /home/postgres usermod --home /home/postgres postgres
Шаг 2: готовим каталог PGDATA
Для этого делаем:
mkdir -p /data/16 chmod -R 700 /data mkdir /data/log chown -R postgres:postgres /data mkdir -p /var/run/postgresql chown postgres:postgres /var/run/postgresql
Важное примечание на полях: на astra linux встречали удаление директории /var/run/postgresql для сокетов, если ставить Postgres из оф. репозитория. Это можно поправить, если изменить сервис Postgres и добавить RuntimeDirectory=postgresql
Теперь нам понадобится каталог для сертификатов:
mkdir -p /opt/patroni/.tls
Помните, как мы сгенерировали сертификаты для etcd? Там же есть сертификаты для Patroni. Забираем их оттуда на узлы Patroniи назначаем права:
chmod -R 744 /opt/patroni/.tls chmod 600 /opt/patroni/.tls/*.key
Установка Patroni: подготовительные работы
Шаг 1: устанавливаем свежую версию Python
Если вдруг ее не оказалось:
yum install openssl-devel libffi-devel bzip2-devel tar -xzvf Python-3.12.4.tgz cd Python-3.12.4/ ./configure --enable-optimizations --with-ssl make altinstall sudo ln -sf /usr/local/bin/python3.12 /usr/bin/python3 sudo ln -sf /usr/local/bin/pip3.12 /usr/bin/pip3
Зачем? Так мы можем установить Patroni, не повредив систему, а также получить очень удобный каталог с бинарями.
Шаг 2: создаем виртуальную среду
Для этого используем команды:
python3 –m venv /opt/patroni source /opt/patroni/bin/activate mkdir –p /opt/patroni/packages cd /opt/patroni/packages
Сама установка
Копируем whl и архивы в /opt/patroni/packages. Затем скачиваем следующие пакеты (примерный список):
click-8.1.7-py3-none-any.whl dnspython-2.6.1-py3-none-any.whl patroni-3.3.2-py3-none-any.whl prettytable-3.10.2-py3-none-any.whl psutil-6.0.0-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl python_dateutil-2.9.0.post0-py2.py3-none-any.whl python-etcd-0.4.5.tar.gz PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl setuptools-72.1.0-py3-none-any.whl six-1.16.0-py2.py3-none-any.whl urllib3-2.2.2-py3-none-any.whl wcwidth-0.2.13-py2.py3-none-any.whl ydiff-1.3.tar.gz psycopg2_binary-2.9.9-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Применяем команды:
pip3 install --no-index --find-links=/opt/patroni/packages patroni[etcd3] pip3 install --no-index --find-links=/opt/patroni/packages psycopg2-binary chown -R postgres:postgres /opt/patroni
Patroni есть! Теперь добавляем в профайл PostgreSQL параметры:
export PG_CONFIG=/usr/pgsql-16/bin/pg_config export PATRONI_CONFIG_FILE=/etc/patroni/config.yml
А теперь активируем виртуальную среду: source /opt/patroni/bin/activate
Настройка Patroni
Cоздаем конфигурационный файл /etc/patroni/config.yml на нодах кластера Patroni:
Скрытый текст
patroni scope: patroni_cluster namespace: /patroni name: patroni_node01 # Изменить на 2 ноде log: level: INFO dir: /data/log/patroni file_size: 50000000 file_num: 10 restapi: listen: 0.0.0.0:8008 connect_address: node01:8008 # Изменить на 2 ноде verify_client: optional cafile: /opt/patroni/.tls/ca.crt certfile: /opt/patroni/.tls/node01.crt # Не забыть изменить сертификаты на 2 ноде keyfile: /opt/patroni/.tls/node01.key ctl: cacert: /opt/patroni/.tls/ca.crt # Не забыть изменить сертификаты на 2 ноде certfile: /opt/patroni/.tls/node01.crt keyfile: /opt/patroni/.tls/node01.key etcd3: hosts: ["etcd01:2379", "etcd02:2379", "etcd03:2379"] protocol: https cacert: /opt/patroni/.tls/ca.crt cert: /opt/patroni/.tls/node01.crt # Не забыть изменить сертификаты на 2 ноде key: /opt/patroni/.tls/node01.key watchdog: mode: off # Если настроен, можно включить bootstrap: dcs: failsafe_mode: true ttl: 30 loop_wait: 10 retry_timeout: 10 maximum_lag_on_failover: 1048576 synchronous_mode: true synchronous_mode_strict: true synchronous_mode_count: 1 master_start_timeout: 30 slots: prod_replica1: type: physical postgresql: use_pg_rewind: true use_slots: true parameters: shared_buffers: '512MB' wal_level: 'replica' wal_keep_size: '512MB' max_connections: 100 effective_cache_size: '1GB' maintenance_work_mem: '256MB' max_wal_senders: 5 max_replication_slots: 5 checkpoint_completion_target: 0.7 log_connections: 'on' log_disconnections: 'on' log_statement: 'ddl' log_line_prefix: '%m [%p] %q%u@%d ' logging_collector: 'on' log_destination: 'stderr' log_directory: '/data/log' log_filename: 'postgresql-%Y-%m-%d.log' log_rotation_size: '100MB' log_rotation_age: '1d' log_min_duration_statement: -1 log_min_error_statement: 'error' log_min_messages: 'warning' log_error_verbosity: 'verbose' log_hostname: 'off' log_duration: 'off' log_timezone: 'Europe/Moscow' timezone: 'Europe/Moscow' lc_messages: 'C.UTF-8' password_encryption: 'scram-sha-256' debug_print_parse: 'off' debug_print_rewritten: 'off' debug_print_plan: 'off' superuser_reserved_connections: 3 synchronous_commit: 'on' synchronous_standby_names: '*' hot_standby: 'on' compute_query_id: 'on' pg_hba: - local all all peer - host all all 127.0.0.1/32 scram-sha-256 - host all all 0.0.0.0/0 md5 - host replication replicator 127.0.0.1/32 scram-sha-256 - host replication replicator 192.168.60.0/24 scram-sha-256 pg_hba: - local all all peer - host all all 127.0.0.1/32 scram-sha-256 - host all all 0.0.0.0/0 md5 - host replication replicator 127.0.0.1/32 scram-sha-256 - host replication replicator 192.168.60.0/24 scram-sha-256 initdb: ["encoding=UTF8", "data-checksums", "username=postgres", "auth=scram-sha-256"] users: admin: password: 'new_secure_password1' options: ["createdb"] postgresql: listen: 0.0.0.0 connect_address: 192.168.60.131:5432 # не забываем заменить адрес на 2 ноде. use_unix_socket: true data_dir: /data/16 config_dir: /data/16 bin_dir: /usr/pgsql-16/bin pgpass: /home/postgres/.pgpass_patroni authentication: replication: username: replicator password: 'new_repl_password' superuser: username: postgres password: 'new_superuser_password' rewind: username: postgres password: 'new_superuser_password' parameters: unix_socket_directories: "/var/run/postgresql" create_replica_methods: ["basebackup"] basebackup: max-rate: 100M checkpoint: fast tags: nofailover: false noloadbalance: false clonefrom: false nosync: false
Чтобы не пропустить ошибки, проверяем валидность конфига:
patroni --validate-config /etc/patroni/config.yml
Patroni требуется журналирование. Для этого создаем подкаталог для логов:
mkdir /data/log/patroni chown -R postgres:postgres /data/log/patroni
Теперь — Systemd-Unit-файл для Patroni:
service patroni [Unit] Description=Patroni high-availability PostgreSQL After=network.target [Service] User=postgres Type=simple ExecStart=/opt/patroni/bin/patroni /etc/patroni/config.yml Restart=always RestartSec=5 LimitNOFILE=1024 [Install] WantedBy=multi-user.target
Перезапустите Systemd и запустите Patroni:
sudo systemctl daemon-reload sudo systemctl enable patroni sudo systemctl start patroni
Проверяем список узлов в кластере: patronictl list
Проверяем переключение (switchover)*:
patronictl switchover
и убеждаемся, что Мастер переехал: у БД есть мастер-нода и slave-нода. Для просмотра подробной работы Patroni и PostgreSQL в арсенале есть логи:
Лог Patroni: /data/log/patroni/patroni.log
Логи экземпляра СУБД: /data/log/postgresql-*.log
Теперь у вас настроен высокодоступный кластер PostgreSQL с использованием Patroni и etcd. В следующей части мы расскажем, как интегрировать балансировщик и пулер pgbouncer в кластер, созданный в этой статье. До встречи!
ссылка на оригинал статьи https://habr.com/ru/articles/847872/
Добавить комментарий