Vai al contenuto

Risoluzione dei problemi di etcd

Info

L'intera procedura deve essere eseguita come root. Per elevare i propri privilegi a root, è possibile utilizzare il comando su -.

etcd è un archivio chiave-valore distribuito utilizzato come punto di coordinamento tra i nodi del cluster PostgreSQL. Centralizza e condivide in modo affidabile lo stato del cluster, in particolare l'identità del leader, lo stato dei membri e i meccanismi di blocco.

patroni si basa su etcd per gestire l'elezione del nodo leader e attivare automaticamente i failover in caso di incidente. Installato su tutti i nodi, etcd garantisce la coerenza complessiva del cluster, senza partecipare all'archiviazione né all'elaborazione dei dati PostgreSQL.

patroni dipende quindi da etcd e non può funzionare correttamente se etcd non funziona.

Info

La configurazione di etcd è memorizzata nel file /etc/default/etcd su ciascun nodo.

Log

L'intera procedura si basa sui log del servizio etcd, che si ottengono con il comando seguente:

1
journalctl -u etcd

Suggerimento

Per seguire i log in tempo reale, aggiungere l'opzione -f al comando:

1
journalctl -fu etcd

Info

I log di etcd sono disponibili anche in /var/log/syslog.

Spiegazione dei log di errore

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

Se il flusso TCP/2380 non è aperto tra due nodi, la connessione va in timeout e etcd scrive i log seguenti:

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

Dove <PEER_PSQL_NODE_ID> è l'ID assegnato da etcd al nodo di destinazione e <PEER_IP_PSQL_NODE> l'indirizzo IP del nodo di destinazione.

Esempio

Nel nostro esempio, il cluster PostgreSQL è configurato come segue:

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

L'esecuzione del comando journalctl -fu etcd dal server PSQL_1 produce i log seguenti:

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

Questi log indicano che la connessione dal server PSQL_1 al server con indirizzo IP 192.168.1.2 (PSQL_2) e ID etcd 7176dd381f583d83, sulla porta TCP/2380, non è riuscita: è andata in timeout. Se ne deduce che il flusso dal server PSQL_1 al server PSQL_2 viene scartato (DROP) da un firewall.

Questo flusso può essere scartato (DROP) dal firewall locale dell'appliance PostgreSQL: verificare la configurazione del firewall dell'appliance sui nodi interessati. Se questa configurazione è corretta, è un firewall dell'infrastruttura a scartare (DROP) il flusso TCP/2380 tra i due nodi.

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

Quando una connessione tra due nodi viene rifiutata, etcd lo segnala con i log seguenti:

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

Dove <PEER_PSQL_NODE_ID> è l'ID assegnato da etcd al nodo di destinazione e <PEER_IP_PSQL_NODE> l'indirizzo IP del nodo di destinazione.

Il rifiuto può avere diverse cause:

  • Il servizio etcd non funziona correttamente o è arrestato sul nodo di destinazione. In questo caso, verificare lo stato (systemctl status etcd) e i log del servizio etcd su quel nodo.
  • Un firewall rifiuta (REJECT) il flusso TCP/2380 tra i due nodi. Può trattarsi del firewall locale dell'appliance o di un firewall dell'infrastruttura.
Esempio

Nel nostro esempio, il cluster PostgreSQL è configurato come segue:

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

L'esecuzione del comando journalctl -fu etcd dal server PSQL_1 produce i log seguenti:

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

Questi log indicano che la connessione dal server PSQL_1 al server con indirizzo IP 192.168.1.3 (PSQL_3) e ID etcd e3d5ef565a5bb46c, sulla porta TCP/2380, è stata rifiutata.

Sul server PSQL_3, il comando systemctl status etcd mostra che etcd è arrestato:

 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 volta avviato etcd, il problema è risolto.

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

Se i certificati del cluster PostgreSQL sono scaduti, oppure non sono stati installati o rinnovati correttamente sul nodo da cui si consultano i log, nei log di etcd compare l'errore seguente:

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

Dove <PEER_IP_PSQL_NODE> è l'indirizzo IP di uno dei nodi del cluster.

Questo log indica che, quando il nodo a cui si è connessi ha tentato di stabilire una connessione con gli altri nodi del cluster (<PEER_IP_PSQL_NODE>), questi l'hanno rifiutata segnalando un errore sul certificato del nodo corrente.

Occorre quindi verificare la validità dei certificati del cluster sul nodo a cui si è connessi.

Attenzione

Se l'autorità di certificazione configurata su un nodo remoto (in /etc/etcd/ca.crt) non è corretta, l'errore compare anche sul nodo da cui si consultano i log: indica allora che il nodo remoto non riesce a convalidare il certificato presentato, perché non dispone della CA corretta.

Esempio

Nel nostro esempio, il cluster PostgreSQL è configurato come segue:

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

L'esecuzione del comando journalctl -fu etcd dal server PSQL_1 produce i log seguenti:

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

Questi log indicano che i nodi PSQL_2 e PSQL_3 hanno rifiutato la connessione dal nodo PSQL_1, perché il certificato di PSQL_1 non è valido in questo contesto.

Si verifica quindi la validità dei certificati del nodo PSQL_1 seguendo la procedura di verifica dei certificati del cluster:

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

Il risultato mostra che il certificato del nodo è scaduto:

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

In questo caso, è necessario rinnovare i certificati del cluster PostgreSQL.

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

Se etcd non dispone delle autorizzazioni corrette sulla directory /var/lib/etcd/cleanroom, il servizio rifiuta di avviarsi e scrive i log seguenti:

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

Per risolvere questo problema, assegnare le autorizzazioni corrette alla directory con il comando seguente:

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