Arquitecturas para la alta disponibilidad de los clústeres de PostgreSQL en Compute Engine

Last reviewed 2023-10-09 UTC
descripción: Varias arquitecturas que proporcionan alta disponibilidad (HA) para las implementaciones de PostgreSQL en Google Cloud.

En este artículo, se describen varias arquitecturas que proporcionan alta disponibilidad para implementaciones de PostgreSQL en Google Cloud. La alta disponibilidad es la medida de la resiliencia del sistema en respuesta a una falla de la infraestructura subyacente. En este documento, alta disponibilidad se refiere a la disponibilidad de clústeres de PostgreSQL dentro de una región de una nube o en múltiples regiones, según la arquitectura de alta disponibilidad.

Este documento está dirigido a los administradores de bases de datos, los arquitectos de la nube y los ingenieros DevOps que desean aprender a aumentar la confiabilidad a nivel de datos de PostgreSQL mediante la mejora del tiempo de actividad general del sistema. En este documento, se analizan los conceptos que son relevantes para ejecutar PostgreSQL en Compute Engine. El documento no aborda el uso de Cloud SQL para PostgreSQL.

Si un sistema o una aplicación requieren un estado persistente para manejar solicitudes o transacciones, la capa de persistencia de datos (el nivel de datos) debe estar disponible para manejar correctamente las solicitudes de consultas o mutaciones de datos. El tiempo de inactividad en el nivel de datos impide que el sistema o la aplicación realice las tareas necesarias.

Según los objetivos de nivel de servicio (SLO) de tu sistema, puede que necesites una arquitectura que proporcione un nivel de disponibilidad más alto. Hay más de una forma de lograr alta disponibilidad. Pero, en general, debes aprovisionar una infraestructura redundante en la que puedas habilitar el acceso para tu aplicación con rapidez.

En este documento, se analizan los siguientes temas:

  • Definición de los términos relacionados con conceptos de bases de datos de alta disponibilidad.
  • Opciones para topologías con alta disponibilidad de PostgreSQL.
  • Información contextual considerar cada opción de arquitectura.

Terminología

Los siguientes términos y conceptos son estándares de la industria y son útiles para comprender propósitos que están fuera del alcance de este documento.

replicación
El proceso mediante el cual las transacciones de escritura (INSERT, UPDATE o DELETE ) y los cambios en los esquemas (lenguaje de definición de datos (DDL)) se capturan, registran y, luego, aplican en serie a todos los nodos de réplica de bases de datos descendentes de la arquitectura.
nodo principal
El nodo que proporciona una lectura con el estado más actualizado de los datos persistentes. Todas las escrituras de la base de datos deben dirigirse a un nodo principal.
nodo de réplica (secundario)
Es una copia en línea del nodo de la base de datos principal. Los cambios se replican de forma síncrona o asíncrona en los nodos de réplica desde el nodo principal. Puedes leer desde los nodos de réplica, pero debes tener en cuenta que los datos podrían estar un poco retrasados debido al retraso de la replicación.
retraso de la replicación
Una medición por número de secuencia de registro (LSN), ID de transacción o tiempo. El retraso de replicación expresa la diferencia entre el momento en que se aplican operaciones de cambios en la réplica y el momento en que se aplican en el nodo principal.
archivado continuo
Una copia de seguridad incremental en la que la base de datos guarda de manera continua transacciones secuenciales en un archivo.
registro de escritura por adelantado (WAL)
Un registro de escritura por adelantado (WAL) es un archivo de registro que registra los cambios en los archivos de datos antes de que se realicen cambios en los archivos. En caso de una falla del servidor, el WAL es una forma estándar de garantizar la integridad y durabilidad de los datos.
registro WAL
Un registro de una transacción que se aplicó a la base de datos. Un registro WAL se formatea y se almacena como una serie de registros que describen los cambios a nivel de la página del archivo de datos.
Número de secuencia de registro (LSN)
Las transacciones crean registros WAL que se agregan al archivo WAL. La posición en la que se realiza la inserción se llama número de secuencia de registro (LSN). Es un número entero de 64 bits, representado como dos números hexadecimales separados por una barra (XXXXXXXX/YYZZZZZ). La “Z” representa la posición de desplazamiento en el archivo WAL.
archivos de segmentos
Los archivos que contienen la mayor cantidad posible de registros WAL, según el tamaño de archivo que configures. Los archivos de segmentos tienen nombres de archivo que aumentan de forma monótona y un tamaño de archivo predeterminado de 16 MiB.
replicación síncrona
Una forma de replicación en la que el servidor principal espera a que la réplica confirme que los datos se escribieron en el registro de transacciones de la réplica antes de confirmar una confirmación al cliente. Cuando ejecutas la replicación de transmisión, puedes usar la opción synchronous_commit de PostgreSQL para configurar garantías de coherencia.
replicación asíncrona
Una forma de replicación en la que el servidor principal no espera a que la réplica confirme que la transacción se recibió de forma correcta antes de confirmar una confirmación al cliente. La replicación asíncrona tiene una latencia más baja en comparación con la replicación síncrona. Sin embargo, si las fallas principales y sus transacciones confirmadas no se transfieren a la réplica, existe la posibilidad de que se pierdan los datos. La replicación asíncrona es el modo predeterminado de replicación en PostgreSQL, ya sea mediante el envío de registros basado en archivos o la replicación de transmisión.
envío de registros basados en archivos
Un método de replicación de PostgreSQL que transfiere los archivos de segmentos WAL desde el servidor de la base de datos principal a la réplica. El nodo principal funciona en modo de archivado continuo, mientras que cada servicio en espera opera en un modo de recuperación continua para leer los archivos WAL. Esta replicación es asíncrona.
replicación de transmisión
Un método de replicación en el que la réplica se conecta al nodo principal y recibe una secuencia de cambios continua constantemente. Debido a que las actualizaciones llegan a través de una transmisión, este método mantiene a la réplica más actualizada con el nodo principal que la replicación de envío de registro. Aunque la replicación es asíncrona de forma predeterminada, tienes la opción de configurar la replicación síncrona.
replicación de transmisión física
Un método de replicación que transporta los cambios a la réplica. Este método usa los registros WAL que contienen los cambios de datos físicos como direcciones de bloques de disco y cambios de byte por byte.
replicación de transmisión lógica
Un método de replicación que captura los cambios según su identidad de replicación (clave primaria), lo que permite tener más control sobre cómo se replican los datos en comparación con la replicación física. Debido a las restricciones a la replicación lógica de PostgreSQL, la replicación de transmisión lógica requiere una configuración especial para los entornos con alta disponibilidad. En esta guía, se describe la replicación física estándar y no se trata de la replicación lógica.
tiempo de actividad
Es el porcentaje de tiempo en que un recurso se encuentra en funcionamiento y puede entregar una respuesta a una solicitud.
detección de fallos
Es el proceso con el que se identifica que se produjo un error en la infraestructura.
conmutación por error
Es el proceso que consiste en promover la infraestructura de copia de seguridad o en espera (en este caso, el nodo de réplica) para que se convierta en la infraestructura principal. Durante la conmutación por error, el nodo de réplica se convierte en el nodo principal.
cambio
El proceso de ejecutar una conmutación por error manual en un sistema de producción. Un cambio comprueba que el sistema funcione bien o quita el nodo principal actual del clúster para hacer mantenimiento.
objetivo de tiempo de recuperación (RTO).
La duración máxima en tiempo real del proceso de conmutación por error a nivel de datos. El RTO depende de la cantidad de tiempo que sería aceptable según una perspectiva empresarial.
objetivo de punto de recuperación (RPO)
La cantidad de pérdida de datos (en tiempo real transcurrido) para que el nivel de datos se mantenga como resultado de la conmutación por error. El RPO depende de la cantidad de pérdida de datos que sea aceptable según una perspectiva empresarial.
resguardo
Proceso de restablecimiento del nodo principal anterior luego de que se corrige la condición que provocó la conmutación por error.
autorreparación
Es la capacidad que tiene un sistema de resolver problemas sin necesidad de que un operador humano realice acciones externas.
partición de red
Una condición en la que dos nodos de una arquitectura (por ejemplo, los nodos principal y de réplica), no pueden comunicarse entre sí a través de la red.
cerebro dividido
Es una condición que ocurre cuando dos nodos creen de forma simultánea que son el nodo principal.
grupo de nodos
Un conjunto de recursos de procesamiento que proporcionan un servicio. En este documento, ese servicio es el nivel de persistencia de los datos.
nodo testigo o de quórum.
Es un recurso de procesamiento independiente que ayuda a un grupo de nodos a determinar qué hacer cuando surge una condición de cerebro dividido.
elección del líder o del principal
Es el proceso mediante el cual un grupo de nodos adaptados al intercambio de tráfico, incluidos los nodos testigo, determina cuál nodo debe ser el principal.

Cuándo considerar el uso de una arquitectura de alta disponibilidad

Las arquitecturas de alta disponibilidad proporcionan mayor protección contra el tiempo de inactividad a nivel de datos en comparación con las configuraciones de bases de datos de nodo único. A fin de seleccionar la mejor opción para tu caso de uso empresarial, debes comprender la tolerancia al tiempo de inactividad y las compensaciones de las diferentes arquitecturas.

Usa una arquitectura de alta disponibilidad cuando quieras proporcionar un mayor tiempo de actividad a nivel de datos para cumplir con los requisitos de confiabilidad de las cargas de trabajo y los servicios. Si tu entorno tolera cierta cantidad de tiempo de inactividad, una arquitectura de alta disponibilidad podría generar costos y complejidad innecesarios. Por ejemplo, es poco frecuente que los entornos de desarrollo o de pruebas necesiten alta disponibilidad a nivel de base de datos.

Considera tus requisitos para la alta disponibilidad

A continuación, se incluyen varias preguntas que te ayudarán a decidir qué opción de alta disponibilidad de PostgreSQL es la más adecuada para tu empresa:

  • ¿Qué nivel de disponibilidad esperas alcanzar? ¿Necesitas una opción que permita que tu servicio siga funcionando durante la falla de una sola zona o de una región completa? Algunas opciones de alta disponibilidad se limitan a una región, mientras que otras pueden ser multirregionales.
  • ¿Qué servicios o clientes dependen de tu nivel de datos y cuál es el costo para tu empresa si hay tiempo de inactividad en el nivel de persistencia de datos? Si un servicio se ofrece solo para clientes internos que no necesitan usar mucho el sistema, es probable que tenga requisitos de disponibilidad más bajos que los de un servicio orientado al cliente final que presta servicios de forma continua.
  • ¿Cuál es tu presupuesto operativo? El costo es una cuestión importante: para proporcionar alta disponibilidad, es probable que aumenten los costos de infraestructura y almacenamiento.
  • ¿Qué tan automatizado debe ser el proceso y qué tan rápido necesitas realizar conmutaciones por error? (¿Cuál es tu RTO?) Las opciones de alta disponibilidad varían según la rapidez con la que el sistema pueda realizar la conmutación por error y estar disponible para los clientes.
  • ¿Puedes permitirte perder datos como resultado de la conmutación por error? (¿Cuál es tu RPO?) Debido a la naturaleza distribuida de las topologías de alta disponibilidad, hay una relación entre la latencia de las confirmaciones y el riesgo de pérdida de datos debido a una falla.

Cómo funciona la alta disponibilidad

En esta sección, se describen la transmisión y la replicación de transmisión síncrona que subyace en las arquitecturas de alta disponibilidad de PostgreSQL.

Replicación de transmisión

La replicación de transmisión es un enfoque de replicación en el que la réplica se conecta al nodo principal y recibe un flujo de registros WAL de forma continua. En comparación con la replicación de envío de registro, la replicación de transmisión permite que la réplica se mantenga más actualizada con el nodo principal. PostgreSQL ofrece replicación de transmisión incorporada a partir de la versión 9. Muchas soluciones de alta disponibilidad de PostgreSQL usan la replicación de transmisión incorporada para proporcionar el mecanismo que permite a varios nodos de réplica de PostgreSQL mantenerse sincronizados con el principal. Varias de estas opciones se analizan en la sección Arquitecturas de alta disponibilidad de PostgreSQL más adelante en este documento.

Cada nodo de réplica requiere recursos dedicados de procesamiento y almacenamiento. La infraestructura de nodos de réplica es independiente del nodo principal. Puedes usar nodos de réplica como nodos en espera activa para entregar consultas de cliente de solo lectura. Este enfoque permite el balanceo de cargas de consulta de solo lectura en el nodo principal y en una o más réplicas.

La replicación de transmisión es asíncrona de forma predeterminada; el nodo principal no espera una confirmación de una réplica para confirmar una confirmación de transacción al cliente. Si un nodo principal sufre una falla después de confirmar la transacción, antes de que la reciba una réplica, la replicación asíncrona puede provocar una pérdida de datos. Si la réplica asciende y se convierte en una instancia principal nueva, la transacción no estará presente.

Replicación de transmisión síncrona

Puedes configurar la replicación de transmisión como síncrona si eliges una o más réplicas para que estén en espera síncrona. Si configuras la arquitectura para la replicación síncrona, el nodo principal no confirmará una confirmación de transacción hasta que la réplica confirme la persistencia de la transacción. La replicación de transmisión síncrona proporciona más durabilidad a cambio de una latencia de transacción más alta.

La opción de configuración synchronous_commit también te permite configurar las siguientes garantías progresivas de durabilidad de réplicas para la transacción:

  • on [predeterminada]: las réplicas en espera síncrona escriben las transacciones confirmadas en su WAL antes de confirmar la recepción al nodo principal. El uso de la configuración on garantiza que la transacción se perderá solo si el nodo principal y las réplicas en espera síncrona experimentan fallas de almacenamiento simultáneas. Debido a que las réplicas solo envían una confirmación de recepción después de que escriben registros WAL, los clientes que consultan la réplica no verán cambios hasta que se apliquen los registros WAL respectivos a la base de datos de la réplica.
  • remote_write: las réplicas en espera síncronas confirman la recepción del registro WAL a nivel del SO, pero no garantizan que el registro WAL se haya escrito en el disco. Debido a que remote_write no garantiza que se escriba el WAL, la transacción se puede perder si se produce algún error tanto en el nodo principal como en el secundario antes de que se escriban los registros. remote_write tiene una durabilidad menor que la de la opción on.
  • remote_apply: Las réplicas en espera síncrona confirman la recepción de la transacción y que esta se aplicó correctamente a la base de datos antes de confirmar la confirmación de la transacción al cliente. El uso de la configuración remote_apply garantiza que la transacción persista en la réplica y que los resultados de la consulta del cliente incluyan de inmediato los efectos de la transacción. remote_apply proporciona mayor durabilidad y coherencia en comparación con on y remote_write.

Arquitecturas de alta disponibilidad de PostgreSQL

En el nivel más básico, la alta disponibilidad de nivel de datos consta de lo siguiente:

  • Un mecanismo para identificar si se produce una falla del nodo principal.
  • Un proceso para realizar una conmutación por error en la que el nodo de réplica asciende para ser un nodo principal.
  • Un proceso para cambiar el enrutamiento de la consulta de forma que las solicitudes de la aplicación lleguen al nodo principal nuevo
  • De forma opcional, un método para recurrir a la arquitectura original con nodos principales y de réplica anteriores a la conmutación por error y con sus capacidades originales

En las siguientes secciones, se proporciona una descripción general de las siguientes arquitecturas de alta disponibilidad:

  • La plantilla Patroni
  • La extensión y el servicio pg_auto_failover
  • MIG con estado y disco persistente regional

Estas soluciones de alta disponibilidad minimizan el tiempo de inactividad si hay una interrupción zonal o de la infraestructura. Cuando elijas entre estas opciones, equilibra la latencia y la durabilidad de las confirmaciones según las necesidades de tu empresa.

Un aspecto fundamental de una arquitectura de alta disponibilidad es el tiempo y el esfuerzo manual que se necesitan a fin de preparar un nuevo entorno en espera para realizar conmutaciones por errores o resguardos posteriores. De lo contrario, el sistema solo podrá resistir una falla y el servicio no tendrá protección contra un incumplimiento del ANS. Te recomendamos seleccionar una arquitectura de alta disponibilidad que pueda realizar conmutaciones por error manuales o cambios con la infraestructura de producción.

Alta disponibilidad con la plantilla Patroni

Patroni es una plantilla de software de código abierto (con licencia del MIT) consolidada y mantenida de forma activa que te brinda las herramientas para configurar, implementar y operar una arquitectura de alta disponibilidad de PostgreSQL. Patroni proporciona un estado de clúster compartido y una configuración de arquitectura que persiste en un almacén de configuración distribuido (DCS). Entre las opciones para implementar un DSC se incluyen las siguientes: etcd, Consul, Apache ZooKeeper o Kubernetes. En el siguiente diagrama, se muestran los componentes principales de un clúster de Patroni.

En un clúster de Patroni, interactúan los nodos de PostgreSQL, los DCS y los agentes de Patroni.

Figura 1. Diagrama de los componentes principales de un clúster de Patroni.

En la figura 1, los balanceadores de cargas se ubican detrás de los nodos de PostgreSQL, y los agentes de DCS de Patroni operan en los nodos de PostgreSQL.

Patroni ejecuta un proceso de agente en cada nodo de PostgreSQL. El proceso de agente administra el proceso de PostgreSQL y la configuración de los nodos de datos. El agente Patroni coordina con otros nodos a través del DSC. El proceso del agente de Patroni también expone una API de REST que puedes consultar para determinar el estado y la configuración del servicio de PostgreSQL para cada nodo.

Para confirmar su función de membresía del clúster, el nodo principal actualiza con regularidad la clave de líder en el DSC. La clave de líder incluye un tiempo de actividad (TTL). Si el TTL transcurre sin una actualización, la clave de líder se expulsa del DCS y se selecciona un nuevo nodo principal del grupo de candidatos.

En el siguiente diagrama, se muestra un clúster en buen estado en el que el nodo A actualiza correctamente el bloqueo del líder.

Un nodo líder de un clúster actualiza el bloqueo del líder mientras los candidatos observan.

Figura 2. Diagrama de un clúster en buen estado.

En la figura 2, se muestra un clúster en buen estado: el nodo B y el nodo C observan mientras el nodo A actualiza la clave de líder.

Detección de fallos

El agente de Patroni comunica su estado de manera continua mediante la actualización de su clave en el DCS. Al mismo tiempo, el agente valida el estado de PostgreSQL. Si el agente detecta un problema, aísla el nodo. Para ello, se apaga solo o aplica un descenso al nodo para que se convierta en una réplica. Como se muestra en el siguiente diagrama, si el nodo afectado es el principal, su clave de líder en el DSC vence y se elige un nuevo líder.

Un clúster afectado elige a un nuevo líder después de que vence la clave de líder existente.

Figura 3. Diagrama de un clúster afectado

En la figura 3, se muestra un clúster afectado: un nodo principal inhabilitado no actualizó recientemente su clave de líder en el DSC y las réplicas no líderes reciben una notificación de que la clave caducó.

En los hosts de Linux, Patroni también ejecuta un perro guardián de nivel de SO en los nodos principales. Este perro guardián detecta mensajes de keep-alive del proceso del agente de Patroni. Si el proceso deja de responder y no se envía el mensaje de keep-alive no se envía, el perro guardián reinicia el host. El perro guardián ayuda a evitar una condición de cerebro dividido en la que el nodo de PostgreSQL continúa funcionando como el principal, a pesar de que la clave de líder del DSC caducó debido a un error del agente y se eligió otro nodo principal (líder).

Proceso de conmutación por error

Si el bloqueo del líder vence en el DCS, se elegirá otro líder entre los nodos de réplica que son candidatos. Cuando una réplica descubre que no hay un bloqueo de líder, verifica su posición de replicación respecto a las otras réplicas. Cada réplica usa la API de REST para obtener las posiciones de registro WAL de los otros nodos de réplica, como se muestra en el siguiente diagrama.

Durante el proceso de conmutación por error de Patroni, las réplicas verifican su posición en el registro WAL.

Figura 4. Diagrama del proceso de conmutación por error de Patroni.

En la figura 4, se muestran las consultas de posición de registro WAL y los resultados correspondientes de los nodos de réplica activos. El nodo A no está disponible, y los nodos en buen estado B y C muestran la misma posición WAL uno respecto del otro.

Al mismo tiempo, el nodo (o nodos, si están en la misma posición) más actualizado intentará adquirir el bloqueo de líder del DCS. Sin embargo, solo un nodo puede crear la clave de líder en el DSC. El primer nodo que consigue crear correctamente la clave de líder será el ganador de la carrera, como se muestra en el siguiente diagrama.

Un nodo crea una clave de líder en el DSC y se convierte en el nuevo nodo principal.

Figura 5. Diagrama de la carrera para convertirse en líder.

En la figura 5, se muestra una carrera para convertirse en líder: dos candidatos intentan obtener el bloqueo del líder, pero solo uno de los dos nodos, el nodo C, establece la clave líder correctamente y gana la carrera.

Después de ganar la elección para convertirse en líder, la réplica se asciende a sí misma como el nuevo nodo principal. A partir del momento en que la réplica se asciende, el nuevo nodo principal actualiza la clave de líder en el DSC para mantener el bloqueo del líder, y los otros nodos funcionan como réplicas.

Patroni también proporciona la herramienta de control patronictl que te permite ejecutar cambios para probar el proceso de conmutación por error de los nodos. Esta herramienta ayuda a los operadores a probar sus configuraciones de alta disponibilidad en producción.

Enrutamiento de consultas

El proceso del agente de Patroni que se ejecuta en cada nodo expone extremos de la API de REST que revelan el rol actual de nodo: ya sea principal o de réplica.

Extremo de REST Código de retorno HTTP si es el nodo principal Código de retorno HTTP si es una réplica
/primary 200 503
/replica 503 200

Debido a que las verificaciones de estado relevantes cambian sus respuestas si un nodo específico cambia su función, una verificación de estado del balanceador de cargas puede usar estos extremos para informar sobre el enrutamiento de tráfico del nodo principal y de la réplica. El proyecto Patroni proporciona configuraciones de plantilla para el balanceador de cargas del proxy con alta disponibilidad. El balanceador de cargas de red de transferencia interno puede usar estas mismas verificaciones de estado para proporcionar funcionalidad similar.

Proceso de resguardo

Si un nodo falla, su clúster queda en un estado degradado. El proceso de resguardo de Patroni ayuda a restablecer un clúster de alta disponibilidad a un buen estado después de una conmutación por error. El proceso de resguardo administra la devolución del clúster a su estado original mediante la inicialización automática del nodo afectado como una réplica del clúster.

Por ejemplo, un nodo puede reiniciarse debido a una falla en el sistema operativo o en la infraestructura subyacente. Si el nodo es el principal y el reinicio tarda más que el TTL, se activará una elección de líder y se seleccionará y ascenderá un nuevo nodo principal. Cuando comienza el proceso del nodo principal inactivo de Patroni, este detecta que no tiene el bloqueo de líder, desciende automáticamente a una réplica y se une al clúster en esa calidad.

Si se produce una falla de un nodo irrecuperable, como una falla zonal que es poco probable, deberás iniciar un nodo nuevo. Un operador de base de datos puede iniciar un nodo nuevo de forma manual o puedes usar un grupo de instancias (MIG) regionales administrado con estado con un recuento de nodos mínimo para automatizar el proceso. Después de crear el nodo nuevo, Patroni detecta que el nodo nuevo es parte de un clúster existente y, luego, lo inicializa automáticamente como una réplica.

Alta disponibilidad con la extensión y el servicio pg_auto_failover

pg_auto_failover es una extensión de PostgreSQL de código abierto (con licencia de PostgreSQL) desarrollada de forma activa. Esta extensión configura una arquitectura de alta disponibilidad mediante la extensión de las funcionalidades existentes de PostgreSQL y solo tiene dependencias que son de PostgreSQL.

Para usar la extensión pg_auto_failover con una arquitectura de alta disponibilidad, necesitas al menos tres nodos, cada uno de los cuales debe ejecutar PostgreSQL con la extensión habilitada. Cualquiera de los nodos puede fallar sin afectar el tiempo de actividad del grupo de base de datos. Una colección de nodos administrados por pg_auto_failover se denomina formación. En el siguiente diagrama, se muestra una arquitectura de pg_auto_failover.

Una arquitectura de pg_auto_failover contiene una formación de nodos.

Figura 6. Diagrama de una arquitectura de pg_auto_failover.

En la figura 6, se muestra una arquitectura de pg_auto_failover que consta de dos componentes principales: el servicio Monitor y el agente Keeper. Keeper y Monitor están en la extensión pg_auto_failover.

Servicio Monitor

El servicio Monitor de pg_auto_failover se implementa como una extensión de PostgreSQL. Cuando el servicio crea un nodo Monitor, inicia una instancia de PostgreSQL con la extensión pg_auto_failover habilitada. El nodo Monitor mantiene el estado global de la formación, obtiene el resultado de la verificación de estado de los nodos de datos miembros de PostgreSQL y organiza el grupo con las reglas establecidas por una máquina de estado finito (FSM). Según las reglas de las FSM respecto a las transiciones de estado, el Monitor comunica las instrucciones a los nodos del grupo para realizar acciones como ascender, descender de nivel y cambios de configuración.

Agente Keeper

En cada nodo de datos de pg_auto_failover, la extensión inicia un proceso de agente Keeper. Este proceso de Keeper observa y administra el servicio de PostgreSQL. Keeper envía actualizaciones de estado al nodo Monitor y recibe y ejecuta las acciones que Monitor envía en respuesta.

De forma predeterminada, pg_auto_failover configura todos los nodos de datos secundarios del grupo como réplicas síncronas. La cantidad de réplicas síncronas necesarias para una confirmación se basa en la configuración number_sync_standby que estableces en el Monitor.

Detección de fallos

Los agentes Keeper de los nodos de datos principales y secundarios se conectan de forma periódica al nodo Monitor para comunicar su estado actual y verificar si hay acciones para ejecutar. El nodo Monitor también se conecta a los nodos de datos para realizar una verificación de estado mediante la ejecución de las llamadas a la API del protocolo de PostgreSQL (libpq), que emula la aplicación cliente de PostgreSQL pg_isready(). Si ninguna de estas acciones se completa de forma correcta después de un período específico (30  segundos según la configuración predeterminada), el nodo Monitor determinará que se produjo un error en el nodo de datos. Puedes cambiar la configuración de PostgreSQL para personalizar el tiempo que esperará el nodo Monitor y la cantidad de reintentos. Para obtener más información, consulta Conmutación por error y tolerancia a errores.

Si ocurre una falla de un solo nodo, se cumplirá una de las siguientes condiciones:

  • Si el nodo de datos en mal estado es el principal, el Monitor iniciará una conmutación por error.
  • Si el nodo de datos en mal estado es secundario, el monitor inhabilitará la replicación síncrona del nodo en mal estado.
  • Si el nodo con errores es el nodo Monitor, no se podrá realizar la conmutación por error automática. Para evitar este punto único de fallo, debes asegurarte de que estén funcionando la supervisión y la recuperación ante desastres adecuadas.

En el siguiente diagrama, se muestran las situaciones de falla y los estados de los resultados de las formaciones que se describen en la lista anterior.

Las situaciones de falla de pg_auto_failover en caso de que falle el nodo principal, uno secundario o el nodo Monitor.

Figura 7. Diagrama de las situaciones de falla de pg_auto_failover.

Proceso de conmutación por error

Cada nodo de la base de datos del grupo tiene las siguientes opciones de configuración que determinan el proceso de conmutación por error:

  • replication_quorum: es una opción booleana. Si replication_quorum se configura como true, el nodo se considera como posible candidato de conmutación por error.
  • candidate_priority: un número entero de 0 a 100. candidate_priority tiene un valor predeterminado de 50, que puedes cambiar para influir en la prioridad de la conmutación por error. Los nodos se priorizan como posibles candidatos de conmutación por error en función del valor candidate_priority. Los nodos que tienen un valor candidate_priority más alto tienen una prioridad más alta. El proceso de conmutación por error requiere que al menos dos nodos tengan una prioridad de candidato distinta de cero en cualquier formación de pg_auto_failover.

Si hay una falla de nodo principal, se considerará ascender a los nodos secundarios si tienen la replicación síncrona activa y si son miembros de replication_quorum.

El ascenso de los nodos secundarios se considera según los siguientes criterios progresivos:

  • Nodos con mayor prioridad de candidato
  • Nodos en espera con la posición de registro WAL más avanzada publicada en el Monitor
  • Selección aleatoria como desempate al final del proceso

Un candidato de conmutación por error se convierte en un candidato atrasado cuando no se publica la posición de LSN más avanzada en el WAL. En esta situación, pg_auto_failover organiza un paso intermedio en el mecanismo de conmutación por error: el candidato atrasado recupera los bytes WAL faltantes de un nodo en espera que tiene la posición de LSN más avanzada. Luego, el nodo en espera asciende. Postgres permite esta operación porque la replicación en cascada permite que cualquier nodo de espera actúe como nodo ascendente para otro nodo en espera.

Enrutamiento de consultas

pg_auto_failure no proporciona ninguna funcionalidad de enrutamiento de consultas del servidor. En vez de aquello, la extensión se vale del enrutamiento de consultas del cliente que usa el controlador de cliente oficial de PostgreSQL, libpq. Cuando defines el URI de conexión, el controlador puede aceptar varios hosts en su palabra clave host.

La biblioteca cliente que usa tu aplicación debe unir libpq o implementar la funcionalidad para proporcionar varios hosts a fin de que la arquitectura admita una conmutación por error completamente automatizada.

Procesos de resguardo y cambio

Cuando el proceso de Keep reinicia un nodo con errores o inicia uno nuevo, el proceso revisa el nodo Monitor para determinar la siguiente acción que se debe realizar. Si un nodo con errores reiniciado era el principal anteriormente y el Monitor ya seleccionó un nuevo principal según el proceso de conmutación por error, Keeper reiniciará ese principal inactivo como una réplica secundaria.

pg_auto_failure proporciona la herramienta de pg_autoctl, que te permite ejecutar cambios para probar el proceso de conmutación por error de los nodos. Además de permitir que los operadores prueben sus configuraciones de alta disponibilidad en la etapa de producción, la herramienta te ayuda a restablecer un clúster de alta disponibilidad a un buen estado después de una conmutación por error.

Alta disponibilidad con MIG con estado y discos persistentes regionales

En esta sección, se describe un enfoque de alta disponibilidad que usa los siguientes componentes de Google Cloud:

  • disco persistente regional. Cuando usas discos persistentes regionales, los datos se replican de forma síncrona entre dos zonas de una región, por lo que no necesitas usar la replicación de transmisión. Sin embargo, la alta disponibilidad se limita a solo dos zonas en una región.
  • Grupos de instancias administrado con estado. Se usa un par de MIG con estado como parte de un plano de control para mantener un nodo PostgreSQL principal en ejecución. Cuando el MIG con estado inicia una instancia nueva, puede conectar el disco persistente regional existente. En un momento determinado, solo uno de los dos MIG tendrá una instancia en ejecución.
  • Cloud Storage. Un objeto de un bucket de Cloud Storage contiene una configuración que indica cuál de los dos MIG ejecuta el nodo de base de datos principal y en cuál se debe crear una instancia de conmutación por error.
  • Verificaciones de estado de MIG y reparación automática. La verificación de estado supervisa el estado de la instancia. Si el nodo en ejecución está en mal estado, la verificación de estado inicia el proceso de reparación automática.
  • Registros: Cuando la reparación automática detiene el nodo principal, se registra una entrada en Logging. Las entradas de registro pertinentes se exportan a un tema de receptor de Pub/Sub mediante un filtro.
  • Cloud Functions controladas por eventos. El mensaje de Pub/Sub activa Cloud Functions. Cloud Functions usa la configuración De Cloud Storage para determinar qué acciones realizar en cada MIG con estado.
  • Balanceador de cargas de red de transferencia interno. El balanceador de cargas proporciona enrutamiento a la instancia del grupo que está en ejecución. Esto garantiza que el cambio de dirección IP de una instancia provocado por la recreación de instancias se abstraiga del cliente.

En el siguiente diagrama, se muestra un ejemplo de una arquitectura de alta disponibilidad que usa MIG con estado y discos persistentes regionales:

Una arquitectura de alta disponibilidad usa MIG con estado y discos persistentes regionales.

Figura 8. Diagrama de una arquitectura de alta disponibilidad que usa MIG con estado y discos persistentes regionales

En la Figura 8, se muestra un nodo principal con buen estado que entrega el tráfico del cliente. Los clientes se conectan a la dirección IP estática del balanceador de cargas de red de transferencia interno. El balanceador de cargas enruta las solicitudes del cliente a la VM que se está ejecutando como parte del MIG. Los volúmenes de datos se almacenan en discos persistentes regionales activados.

Para implementar este enfoque, crea una imagen de VM con PostgreSQL que se inicie en la inicialización, para utilizarse como la plantilla de instancias del MIG. También necesitas configurar una verificación de estado basada en HTTP (como pgDotor) en el nodo. Una verificación de estado basada en HTTP ayuda a garantizar que tanto el balanceador de cargas como el grupo de instancias puedan determinar el estado del nodo de PostgreSQL.

Disco persistente regional

Para aprovisionar un dispositivo de almacenamiento en bloque que proporcione replicación de datos síncrona entre dos zonas De una región, puedes usar la opción de almacenamiento de disco persistente regional de Compute Engine. Los discos persistentes regionales pueden proporcionar un componente básico fundamental para que implementes una opción de alta disponibilidad de PostgreSQL que no dependa de la replicación de transmisión integrada de PostgreSQL.

Si la instancia de VM del nodo principal deja de estar disponible debido a un error en la infraestructura o a una interrupción zonal, puedes forzar la conexión del disco persistente regional a una instancia de VM en la zona de copia de seguridad en la misma región.

Para conectar el disco persistente regional a una instancia de VM en tu zona de copia de seguridad, puedes realizar una de las siguientes acciones:

  • Mantén una instancia de VM en espera pasiva en la zona de la copia de seguridad. Una instancia de VM en espera pasiva es una instancia detenida que no tiene un Persistent Disk regional activado y que es idéntica a la instancia de VM del nodo principal. Si hay una falla, se iniciará la VM en espera pasiva y el disco persistente regional se activará en ella. La instancia en espera pasiva y la instancia del nodo principal tienen los mismos datos.
  • Crea un par de MIG con estado mediante la misma plantilla de instancias. Los MIG proporcionan verificaciones de estado y funcionan como parte del plano de control. Si el nodo principal falla, se crea una instancia de conmutación por error en el MIG de destino de forma declarativa. El MIG de destino se define en el objeto de Cloud Storage. Se usa una configuración por instancia para conectar el disco persistente regional.

Si la interrupción del servicio de datos se identifica con rapidez, la operación de conexión forzada se completará en menos de un minuto, por lo que se puede lograr un RTO medido en minutos.

Si tu empresa puede tolerar el tiempo de inactividad adicional que necesitas para detectar y comunicar una interrupción, y realizar la conmutación por error de forma manual, no necesitas automatizar el proceso de conexión forzada. Si la tolerancia del RTO es más baja, puedes automatizar el proceso de detección y conmutación por error. Como alternativa, Cloud SQL para PostgreSQL también proporciona una implementación completamente administrada de este enfoque de alta disponibilidad.

Proceso de detección de la falla y de conmutación por error

El enfoque de alta disponibilidad usa las capacidades de reparación automática de los grupos de instancias para supervisar el estado de los nodos mediante una verificación de estado. Si hay una verificación de estado con errores, la instancia existente se considerará en mal estado y se detendrá. Luego de esta detención, se inicia el proceso de conmutación por error con Logging, Pub/Sub y la función activada de Cloud Functions.

Para cumplir con el requisito de que esta VM siempre tenga activado el disco regional, Cloud Functions configurará uno de los MIG para crear una instancia en una de las dos zonas en las que el disco persistente regional está disponible. Cuando un nodo falla, se inicia la instancia de reemplazo, según el estado que se conserva en Cloud Storage, en la zona alternativa.

Durante una falla zonal, se inicia una instancia de reemplazo.

Figura 9. Diagrama de una falla zonal en un MIG.

En la Figura 9, el nodo principal previo de la zona A tiene una falla y Cloud Functions configuró el MIG B para iniciar una nueva instancia principal en la zona B. El mecanismo de detección de fallas se configura de forma automática para supervisar el estado del nuevo nodo principal.

Enrutamiento de consultas

El balanceador de cargas de red de transferencia interno enruta los clientes a la instancia que ejecuta el servicio de PostgreSQL. El balanceador de cargas usa la misma verificación de estado que el grupo de instancias a fin de determinar si la instancia está disponible para entregar consultas. Si el nodo no está disponible porque se está volviendo a crear, las conexiones fallarán. Después de que la instancia vuelve a estar disponible, las verificaciones de estado empiezan a realizarse correctamente y las nuevas conexiones se enrutan al nodo disponible. No hay nodos de solo lectura en esta configuración porque solo hay un nodo en ejecución.

Proceso de resguardo

Si falla la verificación de estado del nodo de la base de datos debido a un problema subyacente en el hardware, se vuelve a crear el nodo en una instancia subyacente diferente. En ese punto, la arquitectura se devuelve a su estado original sin ningún paso adicional. Sin embargo, si hay un error zonal, la configuración continúa ejecutándose en un estado degradado hasta que se recupera la primera zona. Aunque es muy poco probable, si hay fallas simultáneas en ambas zonas configuradas para la replicación del Persistent Disk regional y el MIG con estado, la instancia de PostgreSQL no podrá recuperarse: la base de datos no estará disponible para entregar solicitudes durante la interrupción

Comparación entre las opciones de alta disponibilidad

En las siguientes tablas, se proporciona una comparación de las opciones de alta disponibilidad disponibles de Patroni, pg_auto_failover y MIG con estado con discos persistentes regionales.

Configuración y arquitectura

Patroni pg_auto_failover MIG con estado con discos persistentes regionales

Requiere una arquitectura de alta disponibilidad, configuración de DSC, supervisión y alertas. La configuración de los agentes en los nodos de datos es bastante sencilla.

No requiere dependencias externas además de PostgreSQL. Requiere un nodo dedicado como Monitor. El nodo Monitor requiere alta disponibilidad y DR para garantizar que no sea un punto único de fallo (SPOF). Arquitectura que consiste exclusivamente en servicios de Google Cloud. Solo puedes ejecutar un nodo de base de datos activo a la vez.

Configurabilidad de alta disponibilidad

Patroni pg_auto_failover MIG con estado con discos persistentes regionales
Extremadamente configurable: admite la replicación síncrona y asíncrona, y te permite especificar qué nodos son síncronos y asíncronos. Incluye la administración automática de los nodos síncronos. Permite configuraciones de alta disponibilidad para varias zonas y regiones. El DCS debe ser accesible. Similar a Patroni: muy configurable. Sin embargo, debido a que el nodo Monitor solo está disponible como instancia única, cualquier tipo de configuración debe tener en cuenta el acceso a este nodo. Se limita a dos zonas de una sola región con replicación síncrona.

Permite controlar la partición de la red.

Patroni pg_auto_failover MIG con estado con discos persistentes regionales
El autoaislamiento y el nodo Monitor de nivel de SO proporcionan protección contra el estado de cerebro dividido. Cualquier falla en la conexión al DSC da como resultado que el nodo principal desciende por sí mismo para convertirse en una réplica y la activación de una conmutación por error para garantizar la durabilidad por sobre la disponibilidad. Usa una combinación de verificaciones de estado del nodo principal para el monitor y la réplica a fin de detectar una partición de red y desciende por sí mismo si es necesario. No aplicable: solo hay un nodo de PostgreSQL activo a la vez, por lo que no hay una partición de red.

Configuración del cliente

Patroni pg_auto_failover MIG con estado con discos persistentes regionales
Es transparente para el cliente porque se conecta a un balanceador de cargas. Requiere una biblioteca cliente para admitir varias definiciones de host en la configuración porque no sencillo que lo encabece un balanceador de cargas. Es transparente para el cliente porque se conecta a un balanceador de cargas.

Automatización de la inicialización de nodos de PostgreSQL, administración de configuración

Patroni pg_auto_failover MIG con estado con discos persistentes regionales
Proporciona herramientas para administrar la configuración de PostgreSQL (patronictl edit-config) y, luego, inicializa automáticamente los nodos nuevos o los nodos reiniciados del clúster. Puedes inicializar nodos con pg_basebackup o con otras herramientas, como WALL-E y Barman. Inicializa los nodos de forma automática, pero solo usa pg_basebackup cuando inicializas un nodo de réplica nuevo. La administración de la configuración se limita a las configuraciones relacionadas con pg_auto_failover. Un grupo de instancias con estado con disco compartido hace que no sea necesario inicializar de nodos de PostgreSQL. Debido a que solo hay un nodo en ejecución, la administración de configuración se encuentra en un solo nodo.

Personalización y variedad de funciones

Patroni pg_auto_failover MIG con estado con discos persistentes regionales

Proporciona una interfaz de hook para permitir que se llamen acciones definibles por el usuario en pasos clave, como el ascenso y el descenso.

Ofrece una configuración con una gran variedad de funciones, como la compatibilidad con diferentes tipos de DCS, diferentes medios para inicializar réplicas y diferentes formas de proporcionar la configuración de PostgreSQL.

Te permite configurar clústeres en espera que permiten que los clústeres de réplica en cascada faciliten la migración entre clústeres.

Limitado porque es un proyecto relativamente nuevo. No aplicable

Vencimiento

Patroni pg_auto_failover MIG con estado con discos persistentes regionales
El proyecto está disponible desde 2015 y lo usan las empresas grandes, como Zalando y GitLab. Proyecto relativamente nuevo anunciado a principios de 2019. Consiste en productos de Google Cloud con disponibilidad general.

¿Qué sigue?