Construção de um Cluster Etcd com Alta Disponibilidade

  1. Introdução ao Etcd

O etcd é um sistema de armazenamento distribuído do tipo chave-valor, desenvolvido inicialmente pela CoreOS (atualmente parte da Red Hat), com foco em alta disponibilidade e consistência utilizando o protocolo de consenso Raft. Designado a centralizar configurações, gerenciar descoberta de serviços e coordenação em ambientes distribuídos, ele serve como mecanismo de armazenamento crítico em plataformas como Kubernetes e containerd.


  1. Planejamento e Implantação do Cluster

2.1 Arquitetura de Nodes

Nome do Host Endereço IP CPU RAM (GB)
etcd-1 10.220.43.206 2 4
etcd-2 10.220.43.207 2 4
etcd-3 10.220.43.208 2 4

Um cluster recomendado para produção deve conter um número ímpar de membros (ex: 3 ou 5) para atingir resiliência em caso de falhas.

2.2 Instalação do Binário

$ wget https://github.com/etcd-io/etcd/releases/download/v3.4.27/etcd-v3.4.27-linux-amd64.tar.gz
$ tar -xzf etcd-v3.4.27-linux-amd64.tar.gz
$ sudo cp etcd-v3.4.27-linux-amd64/etcd* /usr/local/bin/
$ sudo mkdir -p /var/lib/etcd /etc/etcd
$ sudo chmod 700 /var/lib/etcd

Nota: As portas 2379 (clientes) e 2380 (comunicação entre nós) devem estar liberadas nos firewalls de todos os servidores.


2.3 Configuração dos Membros do Cluster

Cada nó deve possuir sua própria configuração em /etc/etcd/etcd.conf.

Nó 1 (etcd-1)

ETCD_NAME="nodo1"
ETCD_DATA_DIR="/var/lib/etcd"
ETCD_LISTEN_PEER_URLS="http://10.220.43.206:2380"
ETCD_LISTEN_CLIENT_URLS="http://127.0.0.1:2379,http://10.220.43.206:2379"
ETCD_INITIAL_ADVERTISE_PEER_URLS="http://10.220.43.206:2380"
ETCD_INITIAL_CLUSTER="nodo1=http://10.220.43.206:2380,nodo2=http://10.220.43.207:2380,nodo3=http://10.220.43.208:2380"
ETCD_INITIAL_CLUSTER_STATE="new"
ETCD_INITIAL_CLUSTER_TOKEN="cluster_etcd_producao"
ETCD_ADVERTISE_CLIENT_URLS="http://10.220.43.206:2379"

Nó 2 (etcd-2)

ETCD_NAME="nodo2"
ETCD_DATA_DIR="/var/lib/etcd"
ETCD_LISTEN_PEER_URLS="http://10.220.43.207:2380"
ETCD_LISTEN_CLIENT_URLS="http://127.0.0.1:2379,http://10.220.43.207:2379"
ETCD_INITIAL_ADVERTISE_PEER_URLS="http://10.220.43.207:2380"
ETCD_INITIAL_CLUSTER="nodo1=http://10.220.43.206:2380,nodo2=http://10.220.43.207:2380,nodo3=http://10.220.43.208:2380"
ETCD_INITIAL_CLUSTER_STATE="new"
ETCD_INITIAL_CLUSTER_TOKEN="cluster_etcd_producao"
ETCD_ADVERTISE_CLIENT_URLS="http://10.220.43.207:2379"

Nó 3 (etcd-3)

ETCD_NAME="nodo3"
ETCD_DATA_DIR="/var/lib/etcd"
ETCD_LISTEN_PEER_URLS="http://10.220.43.208:2380"
ETCD_LISTEN_CLIENT_URLS="http://127.0.0.1:2379,http://10.220.43.208:2379"
ETCD_INITIAL_ADVERTISE_PEER_URLS="http://10.220.43.208:2380"
ETCD_INITIAL_CLUSTER="nodo1=http://10.220.43.206:2380,nodo2=http://10.220.43.207:2380,nodo3=http://10.220.43.208:2380"
ETCD_INITIAL_CLUSTER_STATE="new"
ETCD_INITIAL_CLUSTER_TOKEN="cluster_etcd_producao"
ETCD_ADVERTISE_CLIENT_URLS="http://10.220.43.208:2379"

Parâmetros principais

  • ETCD_NAME: nome único para identificação dentro do cluster.
  • ETCD_INITIAL_ADVERTISE_PEER_URLS: endereço usado pelos demais membros para comunicação entre nós.
  • ETCD_INITIAL_CLUSTER: lista explícita com todos os membros iniciais.
  • ETCD_INITIAL_CLUSTER_STATE: definir como "new" somente na primeira criação.
  • ETCD_INITIAL_CLUSTER_TOKEN: string única que separa clusters com nomes similares.

2.4 Serviço Systemd

Arquivo /usr/lib/systemd/system/etcd.service (idêntico em todos os nós):

[Unit]
Description=Etcd Distributed Key-Value Store
After=network.target

[Service]
Type=notify
User=root
EnvironmentFile=-/etc/etcd/etcd.conf
ExecStart=/usr/local/bin/etcd
Restart=on-failure
RestartSec=5s
LimitNOFILE=65536

[Install]
WantedBy=multi-user.target

A attivação e início em todos os nós:

$ sudo systemctl daemon-reexec
$ sudo systemctl daemon-reload
$ sudo systemctl enable etcd
$ sudo systemctl start etcd


2.5 Validação Inicial

Verificação de Membros

$ etcdctl member list
# Output esperado:
# a1b2c3d4e5f67890, started, nodo1, http://10.220.43.206:2380, http://10.220.43.206:2379
# b2c3d4e5f6a78901, started, nodo2, http://10.220.43.207:2380, http://10.220.43.207:2379
# c3d4e5f6a7b89012, started, nodo3, http://10.220.43.208:2380, http://10.220.43.208:2379

Identificação do Líder e Estado

$ etcdctl --endpoints=http://10.220.43.206:2379,http://10.220.43.207:2379,http://10.220.43.208:2379 endpoint status --write-out=table
+--------------------------+------------------+---------+---------+-----------+------------+-----------+------------+--------------------+--------+
|        ENDPOINT          |        ID        | VERSION | DB SIZE | IS LEADER | IS LEARNER | RAFT TERM | RAFT INDEX | RAFT APPLIED INDEX | ERRORS |
+--------------------------+------------------+---------+---------+-----------+------------+-----------+------------+--------------------+--------+
| http://10.220.43.206:2379| a1b2c3d4e5f67890 | 3.4.27  | 20 kB   | true      | false      |         5 |          8 |                  8 |        |
| http://10.220.43.207:2379| b2c3d4e5f6a78901 | 3.4.27  | 20 kB   | false     | false      |         5 |          8 |                  8 |        |
| http://10.220.43.208:2379| c3d4e5f6a7b89012 | 3.4.27  | 20 kB   | false     | false      |         5 |          8 |                  8 |        |
+--------------------------+------------------+---------+---------+-----------+------------+-----------+------------+--------------------+--------+

Verificação de Saúde do Endpoint

$ etcdctl --endpoints=http://10.220.43.206:2379,http://10.220.43.207:2379,http://10.220.43.208:2379 endpoint health
# Output:
# http://10.220.43.206:2379 is healthy: successfully committed proposal in 2.1ms
# http://10.220.43.207:2379 is healthy: successfully committed proposal in 2.3ms
# http://10.220.43.208:2379 is healthy: successfully committed proposal in 2.5ms


  1. Substituição de Nó com Falha

3.1 Remoção do Nó degradado

Suponha que nodo3 esteja inoperante.

$ etcdctl member remove c3d4e5f6a7b89012
# Output:
# Member c3d4e5f6a7b89012 removed from cluster cluster_etcd_producao

Verifique a saída de etcdctl member list para confirmar a remoção.

3.2 Limpeza do Nó degradado

No servidor com host etcd-3:

$ sudo rm -rf /var/lib/etcd/*
$ sudo mkdir -p /var/lib/etcd
$ sudo chmod 700 /var/lib/etcd

Edite /etc/etcd/etcd.conf, alterando o estado da configuração do cluster:

ETCD_INITIAL_CLUSTER_STATE="existing"
ETCD_INITIAL_CLUSTER="nodo1=http://10.220.43.206:2380,nodo2=http://10.220.43.207:2380"

3.3 Inclusão Reativa do Nó

No nodo1, adicione o novo nó com o nome nodo3:

$ etcdctl member add nodo3 --peer-urls=http://10.220.43.208:2380
# Output:
# Member 123abc456def789 added to cluster cluster_etcd_producao

# ETCD_NAME="nodo3"
# ETCD_INITIAL_CLUSTER="nodo1=http://10.220.43.206:2380,nodo2=http://10.220.43.207:2380,nodo3=http://10.220.43.208:2380"
# ETCD_INITIAL_ADVERTISE_PEER_URLS="http://10.220.43.208:2380"
# ETCD_INITIAL_CLUSTER_STATE="existing"

Atualize o arquivo etcd.conf em nodo3 com os valores acima e inicie o serviço:

$ sudo systemctl start etcd

Após breve sincronização:

$ etcdctl member list
# a1b2c3d4e5f67890, started, nodo1, ...
# b2c3d4e5f6a78901, started, nodo2, ...
# 123abc456def7890, started, nodo3, ...


  1. Operações com etcdctl

4.1 Modelo de Dados e Hierarquia de Chaves

O namespace do etcd é organizado como uma árvore de chave-valor, usando o caractere / como delimitador de níveis (semelhante a caminhos de arquivos), embora não representem diretórios reais.

Exemplos válidos:

  • /config/db/host
  • /services/auth/token
  • /scheduler/pods

Todas as entradas são armazenadas de forma plana, mas a estrutura facilita busca por prefixo.

4.2 Inserção e Atualização

$ etcdctl put /config/db/host db.internal.local
OK

$ etcdctl put /config/db/port 5432
OK

$ etcdctl put /config/db/host db.prod.local
# sobrescrevendo o valor anterior
OK

4.3 Consutla de Valores

$ etcdctl get /config/db/host
# db.prod.local

$ etcdctl get --prefix /config/db
# /config/db/host
# db.prod.local
# /config/db/port
# 5432

4.4 Remoção de Entradas

$ etcdctl del /config/db/port
# 1 (quantidade de chaves removidas)

$ etcdctl del --prefix /config/db
# 1
# (remoção em massa baseada em prefixo)


Tags: etcd distributed-system Raft kubernetes kv-store

Publicado em 9-21 03:42