Saltar a contenido

Resolución de problemas de etcd

Info

Todo el procedimiento debe realizarse como root. Para elevar sus privilegios a root, puede utilizar el comando su -.

etcd es un almacén clave-valor distribuido (distributed key-value store) que se utiliza como punto de coordinación entre los nodos del clúster de PostgreSQL. Centraliza y comparte de forma fiable el estado del clúster, en particular la identificación del líder, el estado de los miembros y los mecanismos de bloqueo.

patroni se apoya en etcd para dirigir la elección del nodo líder y activar automáticamente las conmutaciones en caso de incidente. Instalado en todos los nodos, etcd garantiza la coherencia global del clúster, sin intervenir en el almacenamiento ni en el tratamiento de los datos de PostgreSQL.

Por tanto, patroni depende de etcd y no puede funcionar correctamente si etcd no funciona.

Info

La configuración de etcd se almacena en el fichero /etc/default/etcd de cada uno de los nodos.

Logs

Todo este procedimiento se basa en los logs del servicio etcd, que se obtienen con el siguiente comando:

1
journalctl -u etcd

Consejo

Para consultar los logs en directo, añada la opción -f al comando:

1
journalctl -fu etcd

Info

Los logs de etcd también están disponibles en /var/log/syslog.

Explicación de los logs de error

health check for peer <PEER_PSQL_NODE_ID> could not connect: dial tcp <PEER_IP_PSQL_NODE>:2380: i/o timeout

Si el flujo TCP/2380 no está abierto entre dos nodos, la conexión caduca y etcd escribe los siguientes logs:

1
2
3
4
5
6
Apr 15 11:48:09 PSQL_1 etcd[1342933]: health check for peer <PEER_PSQL_NODE_ID> could not connect: dial tcp <PEER_IP_PSQL_NODE>:2380: i/o timeout
Apr 15 11:48:09 PSQL_1 etcd[1342933]: health check for peer <PEER_PSQL_NODE_ID> could not connect: dial tcp <PEER_IP_PSQL_NODE>:2380: i/o timeout
Apr 15 11:48:14 PSQL_1 etcd[1342933]: health check for peer <PEER_PSQL_NODE_ID> could not connect: dial tcp <PEER_IP_PSQL_NODE>:2380: i/o timeout
Apr 15 11:48:14 PSQL_1 etcd[1342933]: health check for peer <PEER_PSQL_NODE_ID> could not connect: dial tcp <PEER_IP_PSQL_NODE>:2380: i/o timeout
Apr 15 11:48:19 PSQL_1 etcd[1342933]: health check for peer <PEER_PSQL_NODE_ID> could not connect: dial tcp <PEER_IP_PSQL_NODE>:2380: i/o timeout
Apr 15 11:48:19 PSQL_1 etcd[1342933]: health check for peer <PEER_PSQL_NODE_ID> could not connect: dial tcp <PEER_IP_PSQL_NODE>:2380: i/o timeout

Donde <PEER_PSQL_NODE_ID> es el ID asignado por etcd al nodo de destino, y <PEER_IP_PSQL_NODE> la dirección IP del nodo de destino.

Ejemplo

En nuestro ejemplo, la configuración del clúster de PostgreSQL es la siguiente:

Nodo IP del nodo ID de etcd
PSQL_1 192.168.1.1 53d2c129945ccb8b
PSQL_2 192.168.1.2 7176dd381f583d83
PSQL_3 192.168.1.3 e3d5ef565a5bb46c

Al ejecutar el comando journalctl -fu etcd desde el servidor PSQL_1, se obtienen los siguientes logs:

1
2
3
4
5
Apr 15 11:50:39 PSQL_1 etcd[1342933]: health check for peer 7176dd381f583d83 could not connect: dial tcp 192.168.1.2:2380: i/o timeout
Apr 15 11:50:44 PSQL_1 etcd[1342933]: health check for peer 7176dd381f583d83 could not connect: dial tcp 192.168.1.2:2380: i/o timeout
Apr 15 11:50:44 PSQL_1 etcd[1342933]: health check for peer 7176dd381f583d83 could not connect: dial tcp 192.168.1.2:2380: i/o timeout
Apr 15 11:50:49 PSQL_1 etcd[1342933]: health check for peer 7176dd381f583d83 could not connect: dial tcp 192.168.1.2:2380: i/o timeout
Apr 15 11:50:49 PSQL_1 etcd[1342933]: health check for peer 7176dd381f583d83 could not connect: dial tcp 192.168.1.2:2380: i/o timeout

Estos logs indican que la conexión del servidor PSQL_1 al servidor con dirección IP 192.168.1.2 (PSQL_2) e ID de etcd 7176dd381f583d83, en el puerto TCP/2380, no se ha establecido: ha caducado. Se deduce que un cortafuegos bloquea (DROP) el flujo del servidor PSQL_1 al servidor PSQL_2.

Este flujo puede estar bloqueado (DROP) por el cortafuegos local del appliance PostgreSQL: compruebe la configuración del cortafuegos del appliance en los nodos afectados. Si esta configuración es correcta, es un cortafuegos de la infraestructura el que bloquea (DROP) el flujo TCP/2380 entre los dos nodos.

health check for peer <PEER_PSQL_NODE_ID> could not connect: dial tcp <PEER_IP_PSQL_NODE>:2380: connect: connection refused

Cuando se rechaza una conexión entre dos nodos, etcd lo indica con los siguientes logs:

1
2
3
4
5
6
Apr 15 14:04:30 PSQL_1 etcd[1342933]: health check for peer <PEER_PSQL_NODE_ID> could not connect: dial tcp <PEER_IP_PSQL_NODE>:2380: connect: connection refused
Apr 15 14:04:30 PSQL_1 etcd[1342933]: health check for peer <PEER_PSQL_NODE_ID> could not connect: dial tcp <PEER_IP_PSQL_NODE>:2380: connect: connection refused
Apr 15 14:04:35 PSQL_1 etcd[1342933]: health check for peer <PEER_PSQL_NODE_ID> could not connect: dial tcp <PEER_IP_PSQL_NODE>:2380: connect: connection refused
Apr 15 14:04:35 PSQL_1 etcd[1342933]: health check for peer <PEER_PSQL_NODE_ID> could not connect: dial tcp <PEER_IP_PSQL_NODE>:2380: connect: connection refused
Apr 15 14:04:40 PSQL_1 etcd[1342933]: health check for peer <PEER_PSQL_NODE_ID> could not connect: dial tcp <PEER_IP_PSQL_NODE>:2380: connect: connection refused
Apr 15 14:04:40 PSQL_1 etcd[1342933]: health check for peer <PEER_PSQL_NODE_ID> could not connect: dial tcp <PEER_IP_PSQL_NODE>:2380: connect: connection refused

Donde <PEER_PSQL_NODE_ID> es el ID asignado por etcd al nodo de destino, y <PEER_IP_PSQL_NODE> la dirección IP del nodo de destino.

Este rechazo puede tener varias causas:

  • El servicio etcd falla o está detenido en el nodo de destino. En ese caso, consulte el estado (systemctl status etcd) y los logs del servicio etcd en ese nodo.
  • Un cortafuegos rechaza (REJECT) el flujo TCP/2380 entre los dos nodos. Puede tratarse del cortafuegos local del appliance o de un cortafuegos de la infraestructura.
Ejemplo

En nuestro ejemplo, la configuración del clúster de PostgreSQL es la siguiente:

Nodo IP del nodo ID de etcd
PSQL_1 192.168.1.1 53d2c129945ccb8b
PSQL_2 192.168.1.2 7176dd381f583d83
PSQL_3 192.168.1.3 e3d5ef565a5bb46c

Al ejecutar el comando journalctl -fu etcd desde el servidor PSQL_1, se obtienen los siguientes logs:

1
2
3
4
5
Apr 15 14:04:15 PSQL_1 etcd[1342933]: health check for peer e3d5ef565a5bb46c could not connect: dial tcp 192.168.1.3:2380: connect: connection refused
Apr 15 14:04:15 PSQL_1 etcd[1342933]: health check for peer e3d5ef565a5bb46c could not connect: dial tcp 192.168.1.3:2380: connect: connection refused
Apr 15 14:04:20 PSQL_1 etcd[1342933]: health check for peer e3d5ef565a5bb46c could not connect: dial tcp 192.168.1.3:2380: connect: connection refused
Apr 15 14:04:20 PSQL_1 etcd[1342933]: health check for peer e3d5ef565a5bb46c could not connect: dial tcp 192.168.1.3:2380: connect: connection refused
Apr 15 14:04:25 PSQL_1 etcd[1342933]: health check for peer e3d5ef565a5bb46c could not connect: dial tcp 192.168.1.3:2380: connect: connection refused

Estos logs indican que la conexión del servidor PSQL_1 al servidor con dirección IP 192.168.1.3 (PSQL_3) e ID de etcd e3d5ef565a5bb46c, en el puerto TCP/2380, ha sido rechazada.

En el servidor PSQL_3, el comando systemctl status etcd muestra que etcd está detenido:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
○ etcd.service - etcd - highly-available key value store
    Loaded: loaded (/lib/systemd/system/etcd.service; enabled; preset: enabled)
    Active: inactive (dead) since Wed 2026-04-15 16:09:34 CEST; 38s ago
Duration: 1min 36.087s
    Docs: https://etcd.io/docs
            man:etcd
    Process: 1400558 ExecStart=/usr/bin/etcd $DAEMON_ARGS (code=killed, signal=TERM)
Main PID: 1400558 (code=killed, signal=TERM)
        CPU: 49.071s

Apr 15 12:26:32 PSQL_3 etcd[1197556]: finished scheduled compaction at 1665243 (took 583.297µs)
Apr 15 13:26:32 PSQL_3 etcd[1197556]: store.index: compact 1665949
Apr 15 13:26:32 PSQL_3 etcd[1197556]: finished scheduled compaction at 1665949 (took 574.496µs)
Apr 15 14:26:32 PSQL_3 etcd[1197556]: store.index: compact 1666658
Apr 15 14:26:32 PSQL_3 etcd[1197556]: finished scheduled compaction at 1666658 (took 567.196µs)
Apr 15 15:26:32 PSQL_3 etcd[1197556]: store.index: compact 1667368
Apr 15 15:26:32 PSQL_3 etcd[1197556]: finished scheduled compaction at 1667368 (took 568.096µs)
Apr 15 16:09:34 PSQL_3 systemd[1]: etcd.service: Deactivated successfully.
Apr 15 16:09:34 PSQL_3 systemd[1]: Stopped etcd.service - etcd - highly-available key value store.
Apr 15 16:09:34 PSQL_3 systemd[1]: etcd.service: Consumed 49.071s CPU time.

Una vez iniciado etcd, el problema queda resuelto.

rejected connection from "<PEER_IP_PSQL_NODE>:35956" (error "remote error: tls: bad certificate", ServerName "PSQL_1")

Si los certificados del clúster de PostgreSQL han caducado, o si no se han instalado o renovado correctamente en el nodo desde el que se consultan los logs, aparece el siguiente error en los logs de etcd:

1
2
3
4
5
6
Apr 15 16:38:54 PSQL_1 etcd[1407644]: rejected connection from "<PEER_IP_PSQL_NODE>:49274" (error "remote error: tls: bad certificate", ServerName "PSQL_1")
Apr 15 16:38:54 PSQL_1 etcd[1407644]: rejected connection from "<PEER_IP_PSQL_NODE>:49294" (error "remote error: tls: bad certificate", ServerName "PSQL_1")
Apr 15 16:38:54 PSQL_1 etcd[1407644]: rejected connection from "<PEER_IP_PSQL_NODE>:49288" (error "remote error: tls: bad certificate", ServerName "PSQL_1")
Apr 15 16:38:55 PSQL_1 etcd[1407644]: rejected connection from "<PEER_IP_PSQL_NODE>:49316" (error "remote error: tls: bad certificate", ServerName "PSQL_1")
Apr 15 16:38:55 PSQL_1 etcd[1407644]: rejected connection from "<PEER_IP_PSQL_NODE>:49304" (error "remote error: tls: bad certificate", ServerName "PSQL_1")
Apr 15 16:38:55 PSQL_1 etcd[1407644]: rejected connection from "<PEER_IP_PSQL_NODE>:60958" (error "remote error: tls: bad certificate", ServerName "PSQL_1")

Donde <PEER_IP_PSQL_NODE> es la dirección IP de uno de los nodos del clúster.

Este log indica que, cuando el nodo en el que se está conectado intentó establecer una conexión con los demás nodos del clúster (<PEER_IP_PSQL_NODE>), estos la rechazaron señalando un error en el certificado del nodo actual.

Por tanto, conviene comprobar la validez de los certificados del clúster en el nodo en el que se está conectado.

Atención

Si la autoridad de certificación configurada en un nodo remoto (en /etc/etcd/ca.crt) es incorrecta, el error también aparece en el nodo desde el que se consultan los logs: indica entonces que el nodo remoto no consigue validar el certificado presentado, por no disponer de la CA correcta.

Ejemplo

En nuestro ejemplo, la configuración del clúster de PostgreSQL es la siguiente:

Nodo IP del nodo ID de etcd
PSQL_1 192.168.1.1 53d2c129945ccb8b
PSQL_2 192.168.1.2 7176dd381f583d83
PSQL_3 192.168.1.3 e3d5ef565a5bb46c

Al ejecutar el comando journalctl -fu etcd desde el servidor PSQL_1, se obtienen los siguientes logs:

1
2
3
4
5
6
Apr 15 16:38:54 PSQL_1 etcd[1407644]: rejected connection from "192.168.1.2:49274" (error "remote error: tls: bad certificate", ServerName "PSQL_1")
Apr 15 16:38:54 PSQL_1 etcd[1407644]: rejected connection from "192.168.1.3:49294" (error "remote error: tls: bad certificate", ServerName "PSQL_1")
Apr 15 16:38:54 PSQL_1 etcd[1407644]: rejected connection from "192.168.1.2:49288" (error "remote error: tls: bad certificate", ServerName "PSQL_1")
Apr 15 16:38:55 PSQL_1 etcd[1407644]: rejected connection from "192.168.1.2:49316" (error "remote error: tls: bad certificate", ServerName "PSQL_1")
Apr 15 16:38:55 PSQL_1 etcd[1407644]: rejected connection from "192.168.1.3:49304" (error "remote error: tls: bad certificate", ServerName "PSQL_1")
Apr 15 16:38:55 PSQL_1 etcd[1407644]: rejected connection from "192.168.1.3:60958" (error "remote error: tls: bad certificate", ServerName "PSQL_1")

Estos logs indican que los nodos PSQL_2 y PSQL_3 rechazaron la conexión del nodo PSQL_1, porque el certificado de PSQL_1 no es válido en este contexto.

Se comprueba entonces la validez de los certificados del nodo PSQL_1 siguiendo el procedimiento de comprobación de los certificados del clúster:

1
2
openssl x509 -in /etc/etcd/peer.crt -noout -enddate
openssl x509 -in /etc/etcd/ca.crt -noout -enddate

El resultado muestra que el certificado del nodo ha caducado:

1
2
notAfter=Dec 18 14:04:09 2025 GMT
notAfter=Dec 17 14:03:47 2030 GMT

En este caso, es necesario renovar los certificados del clúster de PostgreSQL.

error listing data dir: /var/lib/etcd/cleanroom

Si etcd no tiene los permisos correctos sobre el directorio /var/lib/etcd/cleanroom, el servicio se niega a iniciarse y escribe los siguientes logs:

1
2
3
4
5
6
Apr 10 14:15:26 PSQL_1 etcd[454701]: Go OS/Arch: linux/amd64
Apr 10 14:15:26 PSQL_1 etcd[454701]: setting maximum number of CPUs to 1, total number of available CPUs is 1
Apr 10 14:15:26 PSQL_1 etcd[454701]: error listing data dir: /var/lib/etcd/cleanroom
Apr 10 14:15:26 PSQL_1 systemd[1]: etcd.service: Main process exited, code=exited, status=1/FAILURE
Apr 10 14:15:26 PSQL_1 systemd[1]: etcd.service: Failed with result 'exit-code'.
Apr 10 14:15:26 PSQL_1 systemd[1]: Failed to start etcd.service - etcd - highly-available key value store

Para resolver este problema, asigne los permisos correctos al directorio con el siguiente comando:

1
chown -R etcd:etcd /var/lib/etcd/cleanroom