Ir para o conteúdo

Resolução de problemas do etcd

Info

Todo o procedimento deve ser realizado como root. Para elevar os seus privilégios a root, pode utilizar o comando su -.

O etcd é um armazenamento chave-valor distribuído (distributed key-value store) utilizado como ponto de coordenação entre os nós do cluster PostgreSQL. Centraliza e partilha de forma fiável o estado do cluster, nomeadamente a identidade do líder, o estado dos membros e os mecanismos de bloqueio.

O patroni apoia-se no etcd para conduzir a eleição do nó líder e desencadear automaticamente as comutações em caso de incidente. Instalado em todos os nós, o etcd garante a coerência global do cluster, sem participar no armazenamento nem no tratamento dos dados do PostgreSQL.

Por conseguinte, o patroni depende do etcd e não pode funcionar corretamente se o etcd não estiver a funcionar.

Info

A configuração do etcd é armazenada no ficheiro /etc/default/etcd de cada nó.

Logs

Todo o procedimento se baseia nos logs do serviço etcd, que obtém com o comando abaixo:

1
journalctl -u etcd

Sugestão

Para acompanhar os logs em tempo real, adicione a opção -f ao comando:

1
journalctl -fu etcd

Info

Os logs do etcd também estão disponíveis em /var/log/syslog.

Explicação dos logs de erro

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

Se o fluxo TCP/2380 não estiver aberto entre dois nós, a ligação excede o tempo limite e o etcd escreve os seguintes 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

Em que <PEER_PSQL_NODE_ID> é o ID atribuído pelo etcd ao nó de destino e <PEER_IP_PSQL_NODE> o endereço IP do nó de destino.

Exemplo

No nosso exemplo, o cluster PostgreSQL está configurado da seguinte forma:

Nó IP do nó ID do etcd
PSQL_1 192.168.1.1 53d2c129945ccb8b
PSQL_2 192.168.1.2 7176dd381f583d83
PSQL_3 192.168.1.3 e3d5ef565a5bb46c

Ao executar o comando journalctl -fu etcd a partir do servidor PSQL_1, obtêm-se os seguintes 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

Estes logs indicam que a ligação do servidor PSQL_1 ao servidor com o endereço IP 192.168.1.2 (PSQL_2) e o ID etcd 7176dd381f583d83, na porta TCP/2380, não foi bem-sucedida: excedeu o tempo limite. Deduz-se que o fluxo do servidor PSQL_1 para o servidor PSQL_2 é descartado (DROP) por um firewall.

Este fluxo pode ser descartado (DROP) pelo firewall local da appliance PostgreSQL: verifique a configuração do firewall da appliance nos nós em causa. Se esta configuração estiver correta, é um firewall da infraestrutura que está a descartar (DROP) o fluxo TCP/2380 entre os dois nós.

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

Quando uma ligação entre dois nós é recusada, o etcd indica-o com os seguintes 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

Em que <PEER_PSQL_NODE_ID> é o ID atribuído pelo etcd ao nó de destino e <PEER_IP_PSQL_NODE> o endereço IP do nó de destino.

A recusa pode ter várias causas:

  • O serviço etcd está em falha ou parado no nó de destino. Neste caso, verifique o estado (systemctl status etcd) e os logs do serviço etcd nesse nó.
  • Um firewall rejeita (REJECT) o fluxo TCP/2380 entre os dois nós. Pode tratar-se do firewall local da appliance ou de um firewall da infraestrutura.
Exemplo

No nosso exemplo, o cluster PostgreSQL está configurado da seguinte forma:

Nó IP do nó ID do etcd
PSQL_1 192.168.1.1 53d2c129945ccb8b
PSQL_2 192.168.1.2 7176dd381f583d83
PSQL_3 192.168.1.3 e3d5ef565a5bb46c

Ao executar o comando journalctl -fu etcd a partir do servidor PSQL_1, obtêm-se os seguintes 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

Estes logs indicam que a ligação do servidor PSQL_1 ao servidor com o endereço IP 192.168.1.3 (PSQL_3) e o ID etcd e3d5ef565a5bb46c, na porta TCP/2380, foi recusada.

No servidor PSQL_3, o comando systemctl status etcd mostra que o etcd está parado:

 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.

Depois de o etcd ser iniciado, o problema fica resolvido.

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

Se os certificados do cluster PostgreSQL tiverem expirado, ou se não tiverem sido corretamente instalados ou renovados no nó a partir do qual está a ler os logs, surge o seguinte erro nos logs do 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")

Em que <PEER_IP_PSQL_NODE> é o endereço IP de um dos nós do cluster.

Este log indica que, quando o nó ao qual está ligado tentou estabelecer uma ligação com os outros nós do cluster (<PEER_IP_PSQL_NODE>), estes a recusaram, assinalando um erro no certificado do nó atual.

Deve, por isso, verificar a validade dos certificados do cluster no nó ao qual está ligado.

Atenção

Se a autoridade de certificação configurada num nó remoto (em /etc/etcd/ca.crt) estiver incorreta, o erro também surge no nó a partir do qual está a ler os logs: indica então que o nó remoto não consegue validar o certificado apresentado, por não dispor da CA correta.

Exemplo

No nosso exemplo, o cluster PostgreSQL está configurado da seguinte forma:

Nó IP do nó ID do etcd
PSQL_1 192.168.1.1 53d2c129945ccb8b
PSQL_2 192.168.1.2 7176dd381f583d83
PSQL_3 192.168.1.3 e3d5ef565a5bb46c

Ao executar o comando journalctl -fu etcd a partir do servidor PSQL_1, obtêm-se os seguintes 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")

Estes logs indicam que os nós PSQL_2 e PSQL_3 recusaram a ligação do nó PSQL_1, porque o certificado de PSQL_1 não é válido neste contexto.

Verifica-se, portanto, a validade dos certificados do nó PSQL_1 seguindo o procedimento de verificação dos certificados do cluster:

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

O resultado mostra que o certificado do nó expirou:

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

Neste caso, é necessário renovar os certificados do cluster PostgreSQL.

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

Se o etcd não tiver as permissões corretas sobre o diretório /var/lib/etcd/cleanroom, o serviço recusa-se a iniciar e escreve os seguintes 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, atribua as permissões corretas ao diretório com o seguinte comando:

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