Nota:
- Este tutorial requiere acceso a Oracle Cloud. Para registrarse en una cuenta gratuita, consulte Introducción al nivel gratuito de Oracle Cloud Infrastructure.
- Utiliza valores de ejemplo para las credenciales, el arrendamiento y los compartimentos de Oracle Cloud Infrastructure. Al finalizar la práctica, sustituya estos valores por valores específicos de su entorno en la nube.
Despliegue un cluster de Postgres de alta disponibilidad en Oracle Cloud Infrastructure
Introducción
En este tutorial se describe el diseño y la implementación de Postgres en una configuración de alta disponibilidad mediante Patroni y otros componentes. PostgreSQL carece de un failover automático incorporado y un mecanismo automático para volver a agregar el maestro fallido al cluster. Patroni es la nueva solución de alta disponibilidad (HA) de edad para PostgreSQL con funciones nativas en la nube y opciones avanzadas para la configuración de réplicas y de inicio automático de failover/switchover.
Patroni es una plantilla para crear su propia solución de alta disponibilidad personalizada mediante Python y para una máxima accesibilidad, un almacén de configuración distribuido como etcd.
A continuación se muestran algunas limitaciones con la replicación nativa de Postgres y su solución con Patroni:
Limitaciones en la replicación de Postgres nativa | Soluciones basadas en Patroni |
---|---|
El mecanismo de replicación por defecto no admite el failover automático. | Patroni proporciona failover automático. |
El uso de herramientas externas para failover puede necesitar más esfuerzos para mantenerlas activas y en ejecución. | Patroni se encarga del failover. |
La supervisión de postgres también puede ser un desafío. | Patroni cuenta con un mecanismo integrado que supervisa el servicio Postgres. |
Para volver a agregar automáticamente el nodo fallido al cluster, se necesitan conocimientos avanzados sobre scripts. | Patroni ha integrado la automatización para devolver un nodo fallido al cluster. |
No se pueden manejar los escenarios de cerebro dividido. | Patroni con la ayuda del ETCD podrá elegir a un nuevo líder. |
Otras soluciones de alta disponibilidad PostgreSQL incluyen:
- gestor de recursos
- PostgreSQL Failover automático (PAF)
- pglookout
- pgPool-II
Sin embargo, el uso de Patroni con la implantación de Postgres simplifica significativamente el ciclo de vida general de la gestión del cluster.
-
ETCD se utiliza como almacén de configuración distribuida (DCS). Almacena el estado del cluster PostgreSQL. Cuando hay cambios en el estado de cualquier nodo PostgreSQL, Patroni actualiza el cambio de estado en el almacén de clave-valor ETCD. ETCD utiliza esta información para elegir el nodo maestro y mantener el cluster en funcionamiento.
-
pgBackrest es una solución sencilla y fiable para las copias de seguridad automáticas. Ventajas de Pgbackrest:
- Es una herramienta de copia de seguridad física y puede realizar copias de seguridad diferenciales, incrementales y completas.
- Los trabajos paralelos se pueden configurar para realizar copias de seguridad
- La copia de seguridad se puede realizar desde los servidores en espera
- Transferencia y extracción de WAL asíncrono (Write Ahead Archive Logs)
- Se pueden configurar varios repositorios
- Opciones de copia de seguridad en la nube para OCI/GCP/S3/Azure
-
El equilibrador de carga de red de OCI se utiliza para comunicarse con el nodo principal en lugar de con HAProxy. El equilibrador de carga de red de Oracle Cloud Infrastructure (OCI) que es un servicio gestionado se integra fácilmente con esta configuración.
Objetivo
En este tutorial se muestra una solución de alto rendimiento viable con posibles alternativas para que los clientes migren las bases de datos de Postgres (de AWS u otros proveedores en la nube) a OCI. Los requisitos clave son HA y migración de datos en tiempo real.
Arquitectura
La siguiente arquitectura consta de 3 servidores ETCD, 3 (Postgres + Patroni + Pgbackrest), cubo de Object Storage y equilibrador de carga de red.
Recomendaciones
- Para HA: utilice 3 servidores ETCD, 3 nodos para PostgreSQL y colóquelos en diferentes dominios de disponibilidad.
- Para un mejor rendimiento, cree volúmenes en bloque independientes para archivos de datos, temporales, de núcleo central y log.
- Defina todos los parámetros personalizados en la sección de inicialización de datos
patroni.yaml
en el momento de la creación del cluster.
Configurar e instalar los componentes de HA PostgreSQL
La configuración se divide en dos partes:
- Aprovisionamiento de infraestructura
- Instalación y configuración del software
Tarea 1: Aprovisionamiento de la infraestructura
-
Cree máquinas virtuales de recursos informáticos:
- 3 servidores ETCD
- 3 servidores para Postgres + Patroni (1 líder y 2 réplicas)
-
Cree un cubo de almacenamiento de objetos para almacenar copias de seguridad.
-
Cree un usuario de arrendamiento de OCI con acceso READ/WRITE en el cubo de almacén de objetos anterior.
Tarea 2: Instalación y configuración del software
-
Configurar ETCD.
-
Instale ETCD en 3 servidores.
cd /tmp wget https://github.com/etcd-io/etcd/releases/download/v3.5.2/etcd-v3.5.2-linux-amd64.tar.gz tar xzvf /tmp/etcd-v3.5.2-linux-amd64.tar.gz cd etcd-v3.5.2-linux-amd64 cp etcdutl etcdctl etcd /usr/local/bin/ mkdir -p /etc/etcd mkdir -p /var/lib/etcd groupadd -f -g 1501 etcd useradd -c "etcd user" -d /var/lib/etcd -s /bin/false -g etcd -u 1501 etcd chown -R etcd:etcd /var/lib/etcd
-
Configurar e iniciar ETCD en los 3 servidores.
A continuación se muestran los detalles del servidor ETCD:
| Hostname | IP Address | Availability Domain | | --- | --- | --- | | pg-etcd-01 | 192.0.2.4 | AD1 | | pg-etcd-02 | 192.0.2.5 | AD2 | | pg-etcd-03 | 192.0.2.6 | AD3 |
Nota: Modifique las IP según el requisito.
pg-etcd-01
vi /etc/etcd/etcd.conf ###Node1 ##192.0.2.4 ETCD_NAME="pg-etcd-01" ETCD_INITIAL_CLUSTER="pg-etcd-01=http://192.0.2.4:2380" ETCD_LISTEN_CLIENT_URLS="http://192.0.2.4:2379,http://127.0.0.1:2379" ETCD_ADVERTISE_CLIENT_URLS="http://192.0.2.4:2379" ETCD_LISTEN_PEER_URLS="http://192.0.2.4:2380,http://127.0.0.1:7001" ETCD_INITIAL_ADVERTISE_PEER_URLS="http://192.0.2.4:2380" ETCD_INITIAL_CLUSTER_TOKEN="etcd-cluster" ETCD_INITIAL_CLUSTER_STATE="new" ETCD_DATA_DIR="/var/lib/etcd" ETCD_ELECTION_TIMEOUT="5000" ETCD_HEARTBEAT_INTERVAL="1000" ETCD_ENABLE_V2="true"
pg-etcd-02
vi /etc/etcd/etcd.conf ##Node2 ##192.0.2.5 ETCD_NAME=" pg-etcd-02" ETCD_INITIAL_CLUSTER="pg-etcd-01=http://192.0.2.4:2380,pg-etcd-02=http://192.0.2.5:2380" ETCD_INITIAL_CLUSTER_TOKEN="etcd-cluster" ETCD_INITIAL_CLUSTER_STATE="existing" ETCD_INITIAL_ADVERTISE_PEER_URLS="http://192.0.2.5:2380" ETCD_LISTEN_PEER_URLS="http://192.0.2.5:2380,http://127.0.0.1:7001" ETCD_LISTEN_CLIENT_URLS="http://192.0.2.5:2379,http://127.0.0.1:2379" ETCD_ADVERTISE_CLIENT_URLS="http://192.0.2.5:2379" ETCD_DATA_DIR="/var/lib/etcd" ETCD_ELECTION_TIMEOUT="5000" ETCD_HEARTBEAT_INTERVAL="1000" ETCD_ENABLE_V2="true"
pg-etcd-03
vi /etc/etcd/etcd.conf ##Node3 ##192.0.2.6 ETCD_NAME="pg-etcd-03" ETCD_INITIAL_CLUSTER="pg-etcd-01=http://192.0.2.4:2380,pg-etcd-02=http://192.0.2.5:2380,pg-etcd-03=http://192.0.2.6:2380" ETCD_INITIAL_CLUSTER_TOKEN="etcd-cluster" ETCD_INITIAL_CLUSTER_STATE="existing" ETCD_INITIAL_ADVERTISE_PEER_URLS="http://192.0.2.6:2380" ETCD_LISTEN_PEER_URLS="http://192.0.2.6:2380,http://127.0.0.1:7001" ETCD_LISTEN_CLIENT_URLS="http://192.0.2.6:2379,http://127.0.0.1:2379" ETCD_ADVERTISE_CLIENT_URLS="http://192.0.2.6:2379" ETCD_DATA_DIR="/var/lib/etcd" ETCD_ELECTION_TIMEOUT="5000" ETCD_HEARTBEAT_INTERVAL="1000" ETCD_ENABLE_V2="true"
-
Agregue miembros a pg-etcd-01.
etcdctl member add pg-etcd-02 --peer-urls=http://192.0.2.5:2380 etcdctl member add pg-etcd-03 --peer-urls=http://192.0.2.6:2380
-
Ejecute el siguiente comando para mostrar la lista de miembros.
etcdctl member list
-
Cree un servicio.
vi /etc/systemd/system/etcd.service [Unit] Description=Etcd Server After=network.target After=network-online.target Wants=network-online.target [Service] Type=notify WorkingDirectory=/var/lib/etcd EnvironmentFile=-/etc/etcd/etcd.conf User=etcd # set GOMAXPROCS to number of processors ExecStart=/bin/bash -c "GOMAXPROCS=$(nproc) /usr/local/bin/etcd" Restart=on-failure LimitNOFILE=65536 IOSchedulingClass=best-effort IOSchedulingPriority=0 [Install] WantedBy=multi-user.target systemctl daemon-reload systemctl enable etcd
-
-
Instale Postgres en todos los nodos. Ejecute el siguiente script para instalar Postgres:
-
Script de instalación de Postgres
Nota: En Replica, detenga postgresql y suprima el directorio de datos, ya que se copiará de la líder una vez que finalice la configuración de Patroni.
/opt/pgsql/bin/pg_ctl -D /opt/pgsql/data/$MAJORVERSION stop cd /opt/pgsql/data/ rm *
-
-
Instalar extensiones: pg_squeeze y pgaudit.
-
Instalar PGAUDIT
cd /usr/local/src/postgresql-12.6/contrib/ wget https://github.com/pgaudit/pgaudit/archive/refs/heads/REL_12_STABLE.zip unzip REL_12_STABLE.zip make install USE_PGXS=1 PG_CONFIG=/opt/pgsql/bin/pg_config
-
Instalar PG_SQUEEZE
cd /usr/local/src/postgresql-12.6/contrib/ wget https://github.com/cybertec-postgresql/pg_squeeze/archive/refs/heads/master.zip unzip master.zip make install USE_PGXS=1 PG_CONFIG=/opt/pgsql/bin/pg_config
-
-
Instale Patroni en todos los nodos.
yum update –y yum -y install epel-release yum -y install python3 yum install -y python3-devel yum install -y psutils yum install -y gcc yum install https://download.postgresql.org/pub/repos/yum/reporpms/EL-7-x86_64/pgdg-redhat-repo-latest.noarch.rpm yum install python3-psycopg2 pip3 install python-etcd pip3 install patroni
-
Instale y configure pgBackrest en todos los nodos.
-
Instalar Pgbackrest
yum install https://download.postgresql.org/pub/repos/yum/reporpms/EL-7-x86_64/pgdg-redhat-repo-latest.noarch.rpm sudo yum install pgbackrest -y
-
Configurar Pgbackrest en todos los nodos
/etc/pgbackrest.conf [global] repo1-type=s3 repo1-path=/backup repo1-s3-uri-style=path repo1-s3-region=us-ashburn-1 repo1-s3-endpoint=https://xxxxx0011.compat.objectstorage.us-ashburn-1.oraclecloud.com repo1-s3-key=0000000a90d57eddexxxxxa3dc7c4f700000ed2e6 repo1-s3-key-secret=1UhXj69xxxx1e6OyF+00000cccccyyyuuu= repo1-s3-bucket=pg_backup repo1-retention-full=10 log-level-console=info log-level-file=debug log-path=/var/log/pgbackrest/ [stanza-name] pg1-path=/opt/pgsql/data pg1-user=Postgres
-
Crear un archivo de inicialización en todos los nodos
vi /etc/patroni/boot_pgbackrest.sh #!/ usr / bin /env bash while getopts ": -:" optchar ; do [[ "${ optchar }" == "-" ]] || continue case "${ OPTARG }" in datadir =* ) DATA_DIR =${ OPTARG #*=} ;; scope =* ) SCOPE =${ OPTARG #*=} ;; esac done /bin/pgbackrest --stanza=$SCOPE --link-all restore
-
-
Configure Patroni en todos los nodos.
Nombre de host Dirección IP Dominio de disponibilidad pg-db-01 192.0.2.1 AD1 pg-db-02 192.0.2.2 AD2 pg-db-03 192.0.2.3 AD3 Nota: Modifique las IP según el requisito.
mkdir -p /etc/patroni mkdir -p /opt/pgsql/patroni chown postgres:postgres -R /opt/pgsql/patroni chmod 700 /opt/pgsql/patroni vi /etc/patroni/patroni.yml scope:pg-ha-cluster name:pg-db-01 namespace:/opt/pgsql/patroni/ ### restapi: listen: "192.0.2.1:8008" connect_address: "192.0.2.1:8008" ###ETCD Configuration etcd: hosts: "192.0.2.4:2379,192.0.2.5:2379, 192.0.2.6:2379" ###Bootstrap bootstrap: dcs: ttl: 120 loop_wait: 10 retry_timeout: 10 maximum_lag_on_failover: 1048576 postgresql: use_pg_rewind: true use_slots: true parameters: archive_command: "pgbackrest --stanza=<stanza-name> archive-push %p" archive_mode: on archive_timeout: 900s log_file_mode: "0640" log_filename: postgresql-%u.log log_rotation_age: 1d log_truncate_on_rotation: "on" logging_collector: "on" max_connections: 2000 max_replication_slots: 10 max_wal_senders: 10 max_wal_size: 5GB max_worker_processes: 40 min_wal_size: 1GB wal_level: "replica" password_encryption: scram-sha-256 superuser_reserved_connections: 200 create_replica_methods: - pgbackrest pgbackrest: command: "/usr/bin/pgbackrest --stanza=<stanza-name> restore --delta --link-all" keep_data: True no_params: True recovery_conf: recovery_target_timeline: latest restore_command: '/usr/bin/pgbackrest --stanza=<stanza-name> archive-get %f %P' method: pgbackrest pgbackrest: command: /etc/patroni/boot_pgbackrest.sh keep_existing_recovery_conf: False recovery_conf: recovery_target_timeline: latest restore_command: '/usr/bin/pgbackrest --stanza=<stanza-name> archive-get %f %P' initdb: - encoding: UTF8 - data-checksums pg_hba: - host replication replicator 127.0.0.1/32 md5 - host replication replicator 192.0.2.1/32 md5 - host replication replicator 192.0.2.2/32 md5 - host replication replicator 192.0.2.3/32 md5 - host all all x.x.x.0/0 md5 users: admin: password: admin options: - createrole - createdb #####Local Postgresql Parameters postgresql: listen: "192.0.2.1:5432" connect_address: "192.0.2.1:5432" data_dir: /opt/pgsql/data pgpass: /opt/pgsql/patroni/pgpass authentication: replication: username: replicator password: password superuser: username: postgres password: password # rewind: # username: replicator # password: password parameters: unix_socket_directories: "/var/run/postgresql, /tmp" ###Any Tags tags: nofailover: false noloadbalance: false clonefrom: false nosync: false
Nota: Cambie la IP de cada nodo, respectivamente.
chmod 640 /etc/patroni/patroni.yml chown postgres:postgres -R /etc/patroni/patroni.yml
- Crear servicio Patroni en todos los nodos
vi /etc/systemd/system/patroni.service [Unit] Description=Runners to orchestrate a high-availability PostgreSQL - patroni After=syslog.target network.target [Service] Type=simple User=postgres Group=postgres # Read in configuration file if it exists, otherwise proceed EnvironmentFile=-/etc/patroni_env.conf WorkingDirectory=~ # Where to send early-startup messages from the server # This is normally controlled by the global default set by systemd # StandardOutput=syslog
# Pre-commands to start watchdog device # Uncomment if watchdog is part of your patroni setup #ExecStartPre=-/usr/bin/sudo /sbin/modprobe softdog #ExecStartPre=-/usr/bin/sudo /bin/chown postgres /dev/watchdog # Start the patroni process ExecStart=/usr/local/bin/patroni /etc/patroni/patroni.yml # Send HUP to reload from patroni.yml ExecReload=/bin/kill -s HUP $MAINPID # Only kill the patroni process, not its children, so it will gracefully stop postgres KillMode=process # Give a reasonable amount of time for the server to start up/shut down TimeoutSec=60 # Do not restart the service if it crashes, we want to manually inspect database on failure Restart=no [Install] WantedBy=multi-user.target sudo systemctl daemon-reload sudo systemctl enable patroni sudo systemctl start patroni sudo systemctl status patroni
Nota: En los nodos de réplica, configure Patroni; sin embargo, no inicie los servicios.
-
Ejecute el siguiente comando para ver el estado del cluster Patroni en Master.
patronictl -c /etc/patroni/patroni.yml list [root@pg-db-01 ~]# /usr/local/bin/patronictl -c /etc/patroni/patroni.yml list +--------------+-------------+---------+---------+----+-----------+ | Member | Host | Role | State | TL | Lag in MB | + Cluster: pg-ha-cluster (7089354141421597068) --+----+-----------+ | pg-db-01 | 192.0.2.1 | Leader | running | 1 | | +--------------+-------------+---------+---------+----+-----------+
-
Cree Stanza y realice una copia de seguridad completa.
pgbackrest --stanza=<stanza-name> stanza-create pgbackrest --type=full --stanza= pgha --process-max=10 backup pgbackrest info
-
Inicie Patroni en los nodos de réplica y debe comenzar a ponerse al día automáticamente desde el líder.
sudo systemctl start patroni sudo systemctl status patroni
- Ejecute el siguiente comando para ver el estado del cluster:
patronictl -c /etc/patroni/patroni.yml list
El estado debe ser el siguiente:
[root@pg-db-01 ~]# /usr/local/bin/patronictl -c /etc/patroni/patroni.yml list +--------------+-------------+---------+---------+----+-----------+ | Member | Host | Role | State | TL | Lag in MB | + Cluster: pg-ha-cluster (7089354141421597068) --+----+-----------+ | pg-db-01 | 192.0.2.1 | Leader | running | 2 | | | pg-db-02 | 192.0.2.2 | Replica | running |2 | 0 | | pg-db-03 | 192.0.2.3 | Replica | running | 2 | 0 | +--------------+-------------+---------+---------+----+-----------+
-
Por último, configure los trabajos cron para la limpieza de logs, las copias de seguridad, etc.
crontab –e #Pgbackrest FULL Backup on Sunday @1AM 00 01 * * 0 postgres pgbackrest --type=full --stanza=ash1-adeprod1-pgcluster --process-max=10 backup &> /dev/null #Pgbackrest INC Backup on Mon-Sat @1AM 00 01 * * 1-6 postgres pgbackrest --type=diff --stanza=ash1-adeprod1-pgcluster --process-max=10 backup &> /dev/null #Delete PostgreSQL logs 08 * * * find /opt/pgsql/log/* -mtime +15 -exec rm {} \; &>/dev/null
Comandos Patroni adicionales
-
Miembros de Lista
patronictl -c /etc/patroni/patroni.yml list
-
Failover/reiniciar/conmutar
patronictl -c /etc/patroni/patroni.yml failover patronictl -c /etc/patroni/patroni.yml restart patronictl -c /etc/patroni/patroni.yml switchover
-
Actualizar parámetro
patronictl -c /etc/patroni/patroni.yml edit-config -p log_directory='/opt/pgsql/log/' patronictl -c /etc/patroni/patroni.yml show-config
-
Recargar
patronictl -c /etc/patroni/patroni.yml reload <cluster_name>
Enlaces relacionados
- Cómo crear una instancia de Linux
- Visión general del cubo de almacenamiento de objetos
- Creación de usuarios de IAM
- Cómo crear el equilibrador de carga de red
- Trabajar con clave de cliente
- PostgreSQL Descargar
- PostgresSQL Instalaciones
- Patroni
- Instalar Etcd
Acuses de recibo
- Autores: Deepika Nayak, Shreyas Rane, Divya Das
Más recursos de aprendizaje
Explore otros laboratorios en docs.oracle.com/learn o acceda a más contenido de aprendizaje gratuito en el canal YouTube de Oracle Learning. Además, visite education.oracle.com/learning-explorer para convertirse en Oracle Learning Explorer.
Para obtener documentación sobre el producto, visite Oracle Help Center.
Deploy a highly available Postgres cluster on Oracle Cloud Infrastructure
F74179-01
November 2022
Copyright © 2022, Oracle and/or its affiliates.