Alta disponibilidad en PostgreSQL con Patroni (III)
En esta tercera parte de nuestra serie sobre la alta disponibilidad en PostgreSQL con Patroni, vamos a ver cómo configurar un servicio de HAproxy para acceder al cluster de Patroni y para obtener más información sobre su API y patronictl.
Si no has visto la primera y la segunda parte de esta serie, te recomendamos que lo hagas para ver por qué estamos utilizando Patroni, y cómo hemos configurado el servicio.
Al finalizar el anterior artículo ya contábamos con un cluster funcional de Patroni, pero para conectar al servicio, lo teníamos que hacer nodo a nodo. Esto no es funcional ya que en caso de fallo de alguno de los nodos, deberíamos elegir el nuevo leader para conectar.
Para poder tener un único endpoint que se actualice con los cambios de role de los nodos, debemos utilizar un servicio de proxy y, en nuestro caso, hemos elegido HAproxy.
API
Para que esto sea posible desde el proxy, debemos conocer el role de los nodos para poder determinar a cuál conectar. Eso lo hacemos mediante la API de Patroni. El puerto por defecto de la API, y el cual hemos configurado en el anterior artículo, es 8008.
Se trata de una REST API muy completa con la que podemos obtener información del funcionamiento del cluster y también realizar cambios en la configuración o roles de los nodos.
Puedes obtener la información completa en la documentación de Patroni, pero vamos a describir las funcionalidades más interesantes:
Endpoints de healthcheck
La api cuenta con múltiples endpoints con healthchecks que además nos pueden aportar información sobre los roles de los nodos. Para todos ellos se utiliza el método GET:
- /leader: Devuelve un código 200 cuando el nodo de Patroni tiene el leader lock.
- /replica: Devuelve un código 200 cuando el nodo de Patroni está en estado running, cuenta con el role de replica y no cuenta con la etiqueta noloadbalance. /replica?lag=<max-lag>: Tiene la misma funcionalidad que el anterior endpoint, pero además permite indicar un valor máximo de lag. En caso de sobrepasarse no devolverá el código 200.
- /read-only: Devuelve un código 200 cuando el nodo de Patroni está en estado running y se pueden realizar lecturas. Por lo tanto, también cuenta con el leader y replicas.
- /patroni es utilizado por el propio servicio durante la elección de leader y puede ser utilizado por nuestra parte para monitorización, al igual que los anteriores.
Endpoint de estado
El endpoint /cluster devuelve la información del estado del cluster en formato JSON, y por su parte, /history devuelve la información también en formato JSON sobre los cambios de leader del cluster. Esta información puede ser muy útil para diagnosticar problemas del servicio.
HAproxy
Ahora que conocemos más sobre la REST API de Patroni podemos utilizar estos endpoints para comprobar el servicio desde HAproxy.
Vamos a configurar este servicio en una instancia a parte del cluster, comenzamos instalando el paquete de HAproxy:
$ sudo apt install percona-haproxy
Una vez instalado el paquete, podemos incluir la configuración en /etc/haproxy/haproxy.cfg
global
maxconn 100
defaults
log global
mode tcp
option tcplog
option dontlognull
timeout connect 120000
timeout client 600000
timeout server 600000
listen postgresql
bind *:5432
option httpchk /primary
http-check expect status 200
default-server inter 3s fall 3 rise 2 on-marked-down shutdown-sessions
server bbdd01 bbdd01:5432 check port 8008
server bbdd02 bbdd02:5432 check port 8008
server bbdd03 bbdd03:5432 check port 8008
listen postgresql-ro
balance roundrobin
bind *:5433
option httpchk /replica
http-check expect status 200
default-server inter 3s fall 3 rise 2 on-marked-down shutdown-sessions
server bbdd01 bbdd01:5432 check port 8008
server bbdd02 bbdd02:5432 check port 8008
server bbdd03 bbdd03:5432 check port 8008
En esta configuración tenemos 2 endpoints diferentes, uno de lectura-escritura y otro de solo lectura. Podemos definir qué servidor es de cada tipo gracias a los checks de la API que hemos descrito en la sección anterior y la funcionalidad de comprobación de healthcheck de HAproxy.
Ya podemos reiniciar el servicio de HAproxy para que cargue la nueva configuración y comprobar si se están dando errores en el log:
$ sudo systemctl restart haproxy
$ sudo journalctl -u haproxy.service -n 100 -f
Ahora ya tenemos disponibles 2 endopoints que se actualizan dinámicamente con los cambios de role de los nodos del cluster de Patroni, consiguiendo alta disponibilidad.
Patronictl
Ya con el servicio en funcionamiento tendremos que llevar a cabo tareas de mantenimiento sobre el cluster. Para ello, Patroni tiene la herramienta patronictl. Comentamos las funcionalidades más interesantes:
- Edit-config: Edita directamente la configuración compartida. Es útil para hacer cambios rápidos, pero suele ser mejor realizar los cambios de forma permanente en el fichero patroni.yml
- Show-config: Muestra la configuración compartida en uso. Se puede utilizar para comprobar posibles diferencias con patroni.yml de parámetros que se hayan incluido con edit-config.
- Failover: Con este comando se puede hacer un cambio de leader. Esto puede ser útil cuando se van a llevar a cabo trabajos de mantenimiento sobre alguno de los nodos y se quiere hacer una parada controlada.
- Restart: Reinicia uno o varios nodos del cluster. Este comando es muy útil ya que ciertos cambios en la configuración requieren un reinicio. Con este comando se pueden reiniciar los nodos de forma inmediata y controlada o dejar el reinicio programado para una fecha que no afecte a nuestro servicio.
Con esto terminamos nuestro repaso a cómo desplegar un servicio de PostgreSQL en alta disponibilidad con Patroni. En este caso hemos incluido un único punto de fallo en el balanceador que utilizamos para el acceso al servicio de PostgreSQL para simplificar el ejemplo.
Si estás interesado en ver cómo desplegar un servicio de HAproxy en alta disponibilidad no dudes en decírnoslo en nuestras redes sociales.