Alta disponibilidad en PostgreSQL con Patroni (II)
En el anterior artículo de esta serie, describimos nuestra solución de Patroni con etcd y haproxy para desplegar un servicio de PostgreSQL en alta disponibilidad.
Ha llegado el momento de configurar los servicios planificados. En este artículo configuraremos todo lo relacionado con el cluster de PostgreSQL y, en el próximo, finalizaremos con la configuración de HAproxy para acceder al cluster de forma transparente.
Recordemos que esta instalación la estamos realizando sobre Debian 11.
Antes de instalar Patroni debemos establecer y configurar los requisitos, que en nuestro caso son: PostgreSQL, etcd y Softdog.
PostgreSQL
$ wget https://repo.percona.com/apt/percona-release_latest.$(lsb_release -sc)_all.deb
$ sudo dpkg -i percona-release_latest.$(lsb_release -sc)_all.deb
$ sudo apt update
Una vez instalado el paquete percona release para controlar los repositorios de Percona, habilitamos el de PostgreSQL y actualizamos de nuevo los repositorios.
$ sudo percona-release setup ppg-13
$ sudo apt update
Instalamos el paquete de PostgreSQL y ya podemos proceder a parar el servicio y borrar el contenido generado en /var/lib/postgresql.
$ sudo apt install percona-ppg-server
$ sudo systemctl stop postgresql
$ sudo rm -rf /var/lib/postgresql/13/main
Paramos el servicio y eliminamos el contenido porque se generará de nuevo con la puesta en marcha de Patroni.
ETCD
Una vez instalado PostgreSQL, podemos proceder con el servicio de configuración distribuida que utilizará Patroni. En nuestro caso hemos elegido etcd y vamos a montar el cluster sobre los mismos nodos.
Instalamos el paquete de etcd en todos los nodos y comprobamos su estado:
$ sudo apt install etcd
Si no detectamos ningún problema, podemos proceder a incluir la configuración de etcd en todos los nodos.
BBDD01
ETCD_NAME=bbdd01
ETCD_INITIAL_CLUSTER="bbdd01=http://[ip_bbdd01]:2380,bbdd02=http://[ip_bbdd02]:2380,bbdd03=http://[ip_bbdd03]:2380"
ETCD_INITIAL_CLUSTER_TOKEN="test_patroni_str"
ETCD_INITIAL_CLUSTER_STATE="new"
ETCD_INITIAL_ADVERTISE_PEER_URLS="http://[ip_bbdd01]:2380"
ETCD_DATA_DIR="/var/lib/etcd/postgresql"
ETCD_LISTEN_PEER_URLS="http://[ip_bbdd01]:2380"
ETCD_LISTEN_CLIENT_URLS="http://[ip_bbdd01]:2379,http://localhost:2379"
ETCD_ADVERTISE_CLIENT_URLS="http://[ip_bbdd01]:2379"
BBDD02
ETCD_NAME=bbdd02
ETCD_INITIAL_CLUSTER="bbdd01=http://[ip_bbdd01]:2380,bbdd02=http://[ip_bbdd02]:2380,bbdd03=http://[ip_bbdd03]:2380"
ETCD_INITIAL_CLUSTER_TOKEN="test_patroni_str"
ETCD_INITIAL_CLUSTER_STATE="new"
ETCD_INITIAL_ADVERTISE_PEER_URLS="http://[ip_bbdd02]:2380"
ETCD_DATA_DIR="/var/lib/etcd/postgresql"
ETCD_LISTEN_PEER_URLS="http://[ip_bbdd02]:2380"
ETCD_LISTEN_CLIENT_URLS="http://[ip_bbdd02]:2379,http://localhost:2379"
ETCD_ADVERTISE_CLIENT_URLS="http://[ip_bbdd02]:2379"
BBDD03
ETCD_NAME=bbdd03
ETCD_INITIAL_CLUSTER="bbdd01=http://[ip_bbdd01]:2380,bbdd02=http://[ip_bbdd02]:2380,bbdd03=http://[ip_bbdd03]:2380"
ETCD_INITIAL_CLUSTER_TOKEN="test_patroni_str"
ETCD_INITIAL_CLUSTER_STATE="new"
ETCD_INITIAL_ADVERTISE_PEER_URLS="http://[ip_bbdd03]:2380"
ETCD_DATA_DIR="/var/lib/etcd/postgresql"
ETCD_LISTEN_PEER_URLS="http://[ip_bbdd03]:2380"
ETCD_LISTEN_CLIENT_URLS="http://[ip_bbdd03]:2379,http://localhost:2379"
ETCD_ADVERTISE_CLIENT_URLS="http://[ip_bbdd03]:2379"
Reiniciamos el servicio de etcd para que lea la nueva configuración en todos los nodos y comprobamos que se han unido al cluster:
$ sudo systemctl restart etcd
$ sudo etcdctl member list
Softdog
El kernel de linux cuenta con la utilidad de watchdog para protegerse de sistemas que no responden.
Patroni permite utilizar este sistema para mejorar la alta disponibilidad. En nuestro caso vamos a hacer uso de Softdog.
Cargamos el módulo de Softdog:
$ sudo sh -c 'echo "softdog" >> /etc/modules'
El usuario postgres tiene que tener acceso a Softdog, ya que el encargado de ejecutarlo es el software de Patroni y éste se ejecuta a su vez con el usuario postgres. Por ello tenemos que dar permisos:
$ sudo sh -c 'echo "KERNEL==\"watchdog\", OWNER=\"postgres\", GROUP=\"postgres\"" >> /etc/udev/rules.d/61-watchdog.rules'
Ahora ya podemos recargar el servicio y comprobar que está corriendo correctamente.
$ sudo modprobe softdog
$ sudo lsmod | grep softdog
Patroni
En este punto ya tenemos todos los requisitos necesarios para comenzar la instalación y configuración del propio servicio de Patroni.
De nuevo en nuestro caso vamos a utilizar la distribución de Percona. Dado que ya hemos configurado los repositorios para la instalación de PostgreSQL, podemos continuar directamente con la instalación del paquete en todos los nodos:
$ sudo apt install percona-patroni
Una vez instalado el paquete, podemos incluir la configuración en /etc/patroni/patroni.yml.
A continuación incluimos el template que habría que incluir en cada nodo completando los campos entre [ ]:
scope: test_str
name: [bbdd_hostname]
restapi:
listen: 0.0.0.0:8008
connect_address: [bbdd_hostname]:8008
etcd:
host: [bbdd_hostname]:2379
bootstrap:
dcs:
ttl: 30
loop_wait: 10
retry_timeout: 10
maximum_lag_on_failover: 1048576
postgresql:
use_pg_rewind: true
use_slots: true
parameters:
wal_level: replica
hot_standby: "on"
logging_collector: 'on'
max_wal_senders: 5
max_replication_slots: 5
wal_log_hints: "on"
initdb:
- encoding: UTF8
- data-checksums
pg_hba:
- host replication replicator [bbdd01_ip]/32 md5
- host replication replicator [bbdd02_ip]/32 md5
- host replication replicator [bbdd03_ip]/32 md5
# acceso externo
- host all all 0.0.0.0/0 md5
users:
admin:
password: [admin_passwd]
options:
- createrole
- createdb
replicator:
password: [replicator_passwd]
options:
- replication
postgresql:
listen: 0.0.0.0:5432
connect_address: [bbdd_hostname]:5432
data_dir: "/var/lib/postgresql/13/main"
bin_dir: "/usr/lib/postgresql/13/bin"
pgpass: /tmp/pgpass0
authentication:
replication:
username: replicator
password: [replicator_passwd]
superuser:
username: postgres
password: [postgres_passwd]
parameters:
unix_socket_directories: '/var/run/postgresql'
watchdog:
mode: required
device: /dev/watchdog
safety_margin: 5
tags:
nofailover: false
noloadbalance: false
clonefrom: false
nosync: false
La configuración de Patroni es extensa y hay que ajustarla a cada caso. Se pueden consultar todos los parámetros disponibles en la documentación de Patroni.
Vamos a detallar algunas de las secciones más importantes:??????
- scope: es el nombre del cluster y afecta a donde se guarda la configuración en etcd. Por lo tanto, si modificamos este nombre tras la puesta en marcha, se regenerará el cluster. También tendremos que hacer referencia a este nombre con el uso de patronictl, que comentaremos con más detalle en el próximo artículo de esta serie.
- bootstrap: en esta sección se incluye la configuración que tendrá efecto únicamente durante el proceso de puesta en marcha del cluster.
- pg_hba: en esta sección, que es opcional, se puede incluir la configuración del fichero pg_hba, que limita el acceso de usuarios. Aunque habitualmente este fichero se encuentra en /etc/postgresql/pg_hba.com, al utilizar Patroni se encuentra en el directorio de datos, en nuestro caso en "/var/lib/postgresql/13/main". Es importante incluir los permisos para la replicación de forma explícita.
- users: una lista de usuarios que se crearán en el inicio.
- postgresql: en esta sección se incluye la configuración del propio servicio de PostgreSQL.
Con la configuración en cada nodo podemos proceder a habilitar y reiniciar el servicio de Patroni en todos los nodos:
$ sudo systemctl enable patroni
$ sudo systemctl restart patroni
Antes de continuar comprobamos que el servicio se ha iniciado correctamente revisando el log:
$ sudo journalctl -u patroni.service -n 100 -f
Con las configuraciones llevadas a cabo ya contamos con un cluster de Patroni en funcionamiento, pero debemos conectar a cada nodo individualmente. Si conectamos al nodo leader podremos actualizar la bbdd, pero si conectamos a alguna de las replicas, solo podremos hacer queries de lectura.
En el próximo artículo veremos como configurar Haproxy para habilitar el acceso desde un único punto de acceso y cómo utilizar la herramienta de administración patronictl.