PostgreSQL на базе Patroni, HAProxy и Keepalived

Материал из Национальной библиотеки им. Н. Э. Баумана
Последнее изменение этой страницы: 13:29, 24 сентября 2018.

PostgreSQL на базе Patroni, HAProxy и Keepalived - это отказоустойчивый высокодоступный кластер базы данных, который легко интегрируется практически в любую систему.

Задача создания отказоустойчивого кластера с ведущими и ведомыми узлами стала очень актуальной после массовой миграции баз данных в облака AWS или GCE. Возможность в считанные секунды заменить отказавший сервер на новый является очень привлекательной для СУБД, но, для того, чтобы это всегда работало, необходимо организовать автоматическое переключение с отказавшего ведущего узла на бывший ведомый. Более того, задача запуска мастера и множества реплик в облаке требует возможностей, отсутствующих в ядре PostgreSQL, таких как автоматическое обнаружение узлов, относящихся к одному кластеру и их переконфигурирование в случае смены мастера. Для этих задач используется Patroni - служебная программа для запуска PostgreSQL кластеров, состоящих из одного ведущего узла и множества ведомых, а также автоматического переключения ведущих узлов в случае аварии.

Описание кластера

  1. PostgreSQL (Postgres) - это реляционная база данных с полным исходным кодом, полностью совместимая с ACID, которая работает во всех основных операционных системах. Хотя Postgres - это очень универсальная, многофункциональная и мощная база данных, у нее нет встроенного решения для высокой доступности
  2. Patroni использует поточную репликацию Postgres, которая по умолчанию является асинхронной. Конфигурация асинхронной репликации Patroni позволяет устанавливать параметры maximum_lag_on_failover[1]
  3. HAProxy используется для отслеживания состояния серверов и перенаправления запросов на мастер сервер.
  4. Keepalived cлужит для обеспечения наличия единой точки входа в кластер — виртуального IP.

Patroni

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

PostgreSQL кластер - репликация, подключение и API взаимодействие
  1. Автоматическое переключение клиентов
    1. haproxy, pgbouncer
  2. Хранилище WAL файлов
  3. Регулярные резервные копии
  4. Мониторинг
  5. DB servers deployment

Возможности Patroni

  1. Поддержка Consul, Zookeeper и etcd
  2. Manual and Scheduled Failover
  3. Cascading replication/pg_basebackup from replica
  4. Synchronous replication
  5. Customizable replica creation methods
  6. Callbacks[2]
    1. on_start, on_stop, on_restart, on_role_change
  7. REST API
  8. Динамическая конфигурация
  9. Tags
    1. nofailover, noloadbalance, clonefrom, replicatefrom
  10. patronictl
  11. Поддержка pg_rewind (при использовании репликации ведущий-ведомый,

позволяет быстро синхронизировать упавший ведущий сервер с ведомым, на который произошло переключение после сбоя)

Patroni + DCS

  1. DCS + PostgreSQL = отказоустойчивость
  2. Patroni управляет PostgreSQL
  3. TTL для ключа или сессии лидера
  4. Watch для ключа лидера
  5. Выборы лидера

Установка

Подготовка

Ansible-playbook essentialsoftware.yml Чтобы подготовить все сервера кластера необходимо предустановить минимально необходимо ПО. Используем Ansible для разворачивания ПО

$ 
---
- name: Install essential software
  yum: name={{ item }} state=latest
  tags: software
  with_items:
   - ntpdate
   - bzip2
   - zip
   - unzip
   - openssl-devel
   - mc
   - vim
   - atop
   - wget
   - mytop
   - screen
   - net-tools
   - rsync
   - psmisc
   - gdb
   - subversion
   - htop
   - bind-utils
   - sysstat
   - nano
   - iptraf
   - nethogs
   - ngrep
   - tcpdump
   - lm_sensors
   - mtr
   - s3cmd
   - psmisc
   - gcc
   - git
   - python2-pip
   - python-devel

- name: install the 'Development tools' package group
  yum:
    name: "@Development tools"
    state: present

Создадим отдельную роль ansible-role-patroni

$  main.yml
- include: postgres.yml
- include: haproxy.yml
- include: keepalived.yml 

Опишем каждый таск данной роли:

$  postgres.yml
---
- name: Import Postgresql96 repo
  yum: name=https://download.postgresql.org/pub/repos/yum/9.6/redhat/rhel-7-x86_64/pgdg-centos96-9.6-3.noarch.rpm state=present
  tags: patroni
  when: install is defined

- name: Install PGsql96
  yum: name={{ item }} state=latest
  tags: patroni
  with_items:
    - postgresql96
    - postgresql96-contrib
    - postgresql96-server
    - python-psycopg2
    - repmgr96
  when: install is defined

- name: checkout patroni
  git: repo=https://github.com/zalando/patroni.git dest=/opt/patroni
  tags: patroni
  when: install is defined

- name: create /etc/patroni
  file: state=directory dest=/etc/patroni
  tags: patroni
  when: install is defined

- name: put postgres.yml
  template: src=postgres0.yml dest=/etc/patroni/postgres.yml backup=yes
  tags: patroni
  when: install is defined

- name: install python packages
  pip: name={{ item }}
  tags: patroni
  with_items:
    - python-etcd
    - python-consul
    - dnspython
    - boto
    - mock
    - requests
    - six
    - kazoo
    - click
    - tzlocal
    - prettytable
    - PyYAML
  when: install is defined

- name: put patroni.service systemd unit
  template: src=patroni.service dest=/etc/systemd/system/patroni.service backup=yes
  tags: patroni
  when: install is defined

- name: Reload daemon definitions
  command: /usr/bin/systemctl daemon-reload
  tags: patroni

- name: restart
  service: name=patroni state=restarted enabled=yes
  tags: patroni 
$  haproxy.yml
---

- name: Install haproxy
  yum: name={{ item }} state=latest
  tags:
    - patroni
    - haproxy
  with_items:
    - haproxy
  when: install is defined

- name: put config
  template: src=haproxy.cfg.j2 dest=/etc/haproxy/haproxy.cfg backup=yes
  tags:
    - patroni
    - haproxy

- name: restart and enable
  service: name=haproxy state=restarted enabled=yes
  tags:
    - patroni
    - haproxy 
$  keepalived.yml
---

- name: Install keepalived
  yum: name={{ item }} state=latest
  tags:
    - patroni
    - keepalived
  with_items:
    - keepalived
  when: install is defined

- name: put alert script
  template: src=alert.sh.j2 dest=/usr/local/sbin/alert.sh backup=yes mode=755
  tags:
    - patroni
    - keepalived
  when: install is defined

- name: put config
  template: src=keepalived.conf.j2 dest=/etc/keepalived/keepalived.conf backup=yes
  tags:
    - patroni
    - keepalived

- name: restart and enable
  service: name=keepalived state=restarted enabled=yes
  tags:
    - patroni
    - keepalived 

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

$ cluster-pgsql.yml
---
- hosts: pgsql

  pre_tasks:
    - name: Setting system hostname
      hostname: name="{{ ansible_host }}"

    - include: tasks/essentialsoftware.yml

  roles:
     - ansible-role-patroni

Накатываем полную конфигурацию кластера на сервера:


~# ansible-playbook cluster-pgsql.yml

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

$~# journalctl -f -u patroni

Установка

Преимущества

  • Балансировку нагрузки(на чтение) через haproxy
  • Отсутствие единой точки отказа — keepalived переносит ip адрес на другую ноду, которая была автоматически “повышена” до мастера в случае отказа;
  • Возможность настроить систему “под себя”.
  • Автоматический failover в случае отказа мастера

Примечания

Источники

  1. PostgreSQL [Электронный ресурс]: Postgres Professional / Дата обращения: 25.06.2018. — Режим доступа: https://edu.postgrespro.ru/dba1-9.4/dba1_01_introduction.pdf
  2. Postgres [Электронный ресурс]: Postgres Pro Standard 10 Documentional / Дата обращения: 25.06.2018. — Режим доступа: https://postgrespro.com/docs/postgrespro/10/release-9-5
  3. Cluster PostgreSQL [Электронный ресурс]: HA PostgreSQL on Patroni, Haproxy, Keepalived / Дата обращения: 25.06.2018. — Режим доступа: https://habr.com/post/322036/
  4. Github [Электронный ресурс]: Плейбуки ансибл для разворачивания кластера — Режим доступа: https://github.com/1v1expert/Cluster_PostgreSQL

Ссылки

  • github.com [Электронный ресурс]: GitHub: официальный репозиторий Patroni / Дата обращения: 25.06.2018. — Режим доступа: https://github.com/zalando/patroni
  • pgconf.ru [Электронный ресурс]: Доклад конференции PgConf.Russia 2017 отказоустойчивый PostgreSQL кластер с Patroni / Дата обращения: 05.05.2018. — Режим доступа: https://pgconf.ru/2017/93520
  • consul [Электронный ресурс]: Официальный сайт разработчиков Consul / Дата обращения: 25.06.2018. — Режим доступа: [ https://www.consul.io/