Aller au contenu

Dépannage de etcd

Info

L'ensemble de la procédure est à suivre en tant que root. Pour élever ses privilèges en root, il est possible d'utiliser la commande su -.

etcd est un magasin clé-valeur distribué (distributed key-value store) utilisé comme point de coordination entre les nœuds du cluster PostgreSQL. Il centralise et partage de manière fiable l'état du cluster, notamment l'identification du leader, l'état des membres et les mécanismes de verrouillage.

patroni s'appuie sur etcd pour piloter l'élection du nœud leader et déclencher automatiquement les bascules en cas d'incident. Installé sur l'ensemble des nœuds, etcd garantit la cohérence globale du cluster, sans intervenir dans le stockage ni dans le traitement des données PostgreSQL.

patroni dépend donc de etcd, et ne peut pas fonctionner correctement si etcd n'est pas fonctionnel.

Info

La configuration de etcd est stockée dans le fichier /etc/default/etcd sur chacun des nœuds.

Logs

L'ensemble de cette procédure s'appuie sur les logs du service etcd, que l'on obtient avec la commande ci-dessous :

1
journalctl -u etcd

Astuce

Pour consulter les logs en direct, ajoutez l'option -f à la commande :

1
journalctl -fu etcd

Info

Les logs de etcd sont aussi disponibles dans /var/log/syslog.

Explication des logs d'erreur

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

Si le flux TCP/2380 n'est pas ouvert entre deux nœuds, la connexion expire et etcd écrit les logs suivants :

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

Où <PEER_PSQL_NODE_ID> est l'ID attribué par etcd au nœud cible, et <PEER_IP_PSQL_NODE> l'adresse IP du nœud cible.

Exemple

Dans notre exemple, la configuration du cluster PostgreSQL est la suivante :

Nœud IP du nœud ID etcd
PSQL_1 192.168.1.1 53d2c129945ccb8b
PSQL_2 192.168.1.2 7176dd381f583d83
PSQL_3 192.168.1.3 e3d5ef565a5bb46c

En exécutant la commande journalctl -fu etcd depuis le serveur PSQL_1, on obtient les logs suivants :

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

Ces logs indiquent que la connexion du serveur PSQL_1 vers le serveur d'adresse IP 192.168.1.2 (PSQL_2) et d'ID etcd 7176dd381f583d83, sur le port TCP/2380, n'a pas abouti : elle a expiré. On en déduit que le flux du serveur PSQL_1 vers le serveur PSQL_2 est bloqué (DROP) par un pare-feu.

Ce flux peut être bloqué (DROP) par le pare-feu local de l'appliance PostgreSQL : vérifiez la configuration du pare-feu de l'appliance sur les nœuds concernés. Si cette configuration est correcte, c'est un pare-feu de l'infrastructure qui bloque (DROP) le flux TCP/2380 entre les deux nœuds.

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

Lorsqu'une connexion entre deux nœuds est refusée, etcd l'indique par les logs suivants :

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

Où <PEER_PSQL_NODE_ID> est l'ID attribué par etcd au nœud cible, et <PEER_IP_PSQL_NODE> l'adresse IP du nœud cible.

Ce refus peut avoir plusieurs causes :

  • Le service etcd est dysfonctionnel ou arrêté sur le nœud cible. Consultez dans ce cas l'état (systemctl status etcd) et les logs du service etcd sur ce nœud.
  • Un pare-feu rejette (REJECT) le flux TCP/2380 entre les deux nœuds. Il peut s'agir du pare-feu local de l'appliance ou d'un pare-feu de l'infrastructure.
Exemple

Dans notre exemple, la configuration du cluster PostgreSQL est la suivante :

Nœud IP du nœud ID etcd
PSQL_1 192.168.1.1 53d2c129945ccb8b
PSQL_2 192.168.1.2 7176dd381f583d83
PSQL_3 192.168.1.3 e3d5ef565a5bb46c

En exécutant la commande journalctl -fu etcd depuis le serveur PSQL_1, on obtient les logs suivants :

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

Ces logs indiquent que la connexion du serveur PSQL_1 vers le serveur d'adresse IP 192.168.1.3 (PSQL_3) et d'ID etcd e3d5ef565a5bb46c, sur le port TCP/2380, a été refusée.

Sur le serveur PSQL_3, la commande systemctl status etcd montre que etcd est arrêté :

 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.

Une fois etcd démarré, le problème est résolu.

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

Si les certificats du cluster PostgreSQL ont expiré, ou s'ils n'ont pas été correctement installés ou renouvelés sur le nœud depuis lequel on consulte les logs, l'erreur suivante apparaît dans les 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")

Où <PEER_IP_PSQL_NODE> est l'adresse IP de l'un des nœuds du cluster.

Ce log indique que, lorsque le nœud sur lequel on est connecté a tenté d'établir une connexion avec les autres nœuds du cluster (<PEER_IP_PSQL_NODE>), ceux-ci l'ont refusée en signalant une erreur sur le certificat du nœud actuel.

Il convient donc de vérifier la validité des certificats du cluster sur le nœud sur lequel on est connecté.

Attention

Si l'autorité de certification configurée sur un nœud distant (dans /etc/etcd/ca.crt) est incorrecte, l'erreur apparaît aussi sur le nœud depuis lequel on consulte les logs : elle indique alors que le nœud distant ne parvient pas à valider le certificat présenté, faute de disposer de la bonne AC.

Exemple

Dans notre exemple, la configuration du cluster PostgreSQL est la suivante :

Nœud IP du nœud ID etcd
PSQL_1 192.168.1.1 53d2c129945ccb8b
PSQL_2 192.168.1.2 7176dd381f583d83
PSQL_3 192.168.1.3 e3d5ef565a5bb46c

En exécutant la commande journalctl -fu etcd depuis le serveur PSQL_1, on obtient les logs suivants :

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")

Ces logs indiquent que les nœuds PSQL_2 et PSQL_3 ont refusé la connexion du nœud PSQL_1, parce que le certificat de PSQL_1 n'est pas valide dans ce contexte.

On vérifie donc la validité des certificats du nœud PSQL_1 en suivant la procédure de vérification des certificats du cluster :

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

Le retour montre que le certificat du nœud a expiré :

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

Il est donc nécessaire dans ce cas de renouveler les certificats du cluster PostgreSQL.

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

Si etcd n'a pas les bons droits sur le répertoire /var/lib/etcd/cleanroom, le service refuse de démarrer et écrit les logs suivants :

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

Pour résoudre ce problème, attribuez les bons droits au répertoire avec la commande suivante :

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