O etcd é o armazenamento distribuído de chave-valor no coração de cada cluster Kubernetes, armazenando todo o estado do cluster, desde definições de pods até secrets. Quando o etcd fica indisponível ou perde dados, todo o plano de controle para de funcionar. Este guia orienta você na implantação do etcd como um serviço standalone e como um cluster de três nós, na proteção com TLS mútuo, na criação e restauração de snapshots, e no entendimento de como o Kubernetes o utiliza — para que você possa operá-lo com confiança em produção.
Pré-requisitos
- Servidor(es) Linux executando Ubuntu 22.04 ou posterior (um para nó único, três para cluster)
- Acesso root ou sudo
- Familiaridade básica com gerenciamento de serviços systemd
curletarinstalados- Para TLS:
cfsslouopenssldisponíveis - Portas 2379 (cliente) e 2380 (peer) abertas entre os nós etcd
O Que É o etcd e Como Funciona
O etcd é um armazenamento distribuído de chave-valor de código aberto e altamente consistente, originalmente desenvolvido pela CoreOS e agora um projeto graduado da Cloud Native Computing Foundation (CNCF). Ele usa o algoritmo de consenso Raft para garantir que todos os nós concordem com o estado atual, mesmo quando ocorrem partições de rede ou falhas de nós.
As propriedades principais que você precisa entender:
- Consistência forte: cada leitura retorna a última gravação confirmada, nunca um valor desatualizado
- Watch API: os clientes assinam alterações de chave e recebem notificações em tempo real
- Transações atômicas: operações de compare-and-swap permitem construir bloqueios distribuídos
- Leases: as chaves podem expirar automaticamente, habilitando a eleição de líderes baseada em heartbeat
O Kubernetes depende do etcd para cada parte do estado do cluster. O servidor de API é o único componente que lê e grava no etcd diretamente — todos os outros componentes (scheduler, controller manager, kubelet) se comunicam através do servidor de API.
| Funcionalidade | etcd | Redis | Consul | ZooKeeper |
|---|---|---|---|---|
| Consenso | Raft | Nenhum (standalone) | Raft | ZAB |
| Consistência forte | Sim | Não (eventual) | Sim | Sim |
| Watch API | Sim | Apenas pub/sub | Sim | Sim |
| Nativo do Kubernetes | Sim | Não | Não | Não |
| TLS integrado | Sim | Opcional | Sim | Opcional |
| Complexidade operacional | Baixa | Muito baixa | Média | Alta |
O etcd se destaca para o Kubernetes porque foi desenvolvido especificamente para casos de uso de plano de controle: valores pequenos, alta taxa de leitura, gravações pouco frequentes e correção em detrimento do throughput bruto.
Instalando o etcd
Baixe a versão mais recente do repositório oficial do GitHub. No momento da escrita, a série 3.5.x é a série estável recomendada para Kubernetes 1.29+.
ETCD_VER=v3.5.12
DOWNLOAD_URL=https://github.com/etcd-io/etcd/releases/download
curl -L ${DOWNLOAD_URL}/${ETCD_VER}/etcd-${ETCD_VER}-linux-amd64.tar.gz \
-o /tmp/etcd-${ETCD_VER}-linux-amd64.tar.gz
tar xzvf /tmp/etcd-${ETCD_VER}-linux-amd64.tar.gz -C /tmp/
sudo mv /tmp/etcd-${ETCD_VER}-linux-amd64/etcd /usr/local/bin/
sudo mv /tmp/etcd-${ETCD_VER}-linux-amd64/etcdctl /usr/local/bin/
sudo mv /tmp/etcd-${ETCD_VER}-linux-amd64/etcdutl /usr/local/bin/
etcd --version
etcdctl version
Crie o diretório de dados e um usuário de sistema dedicado:
sudo groupadd --system etcd
sudo useradd -s /sbin/nologin --system -g etcd etcd
sudo mkdir -p /var/lib/etcd
sudo chown -R etcd:etcd /var/lib/etcd
sudo chmod 700 /var/lib/etcd
Gerando Certificados TLS
Nunca execute o etcd sem TLS em qualquer ambiente além de um laptop local. O etcd armazena secrets e credenciais — qualquer listener não criptografado representa um risco imediato de segurança.
Instale o cfssl:
curl -Lo /usr/local/bin/cfssl \
https://github.com/cloudflare/cfssl/releases/latest/download/cfssl_linux-amd64
curl -Lo /usr/local/bin/cfssljson \
https://github.com/cloudflare/cfssl/releases/latest/download/cfssljson_linux-amd64
chmod +x /usr/local/bin/cfssl /usr/local/bin/cfssljson
Crie uma CA e um certificado de servidor. Salve o seguinte como ca-config.json:
{
"signing": {
"default": { "expiry": "87600h" },
"profiles": {
"etcd": {
"expiry": "87600h",
"usages": ["signing","key encipherment","server auth","client auth"]
}
}
}
}
Gere os certificados de CA e servidor:
# CA
cfssl gencert -initca ca-csr.json | cfssljson -bare ca
# Certificado de servidor + peer (adicione todos os IPs/hostnames dos nós no array hosts do CSR)
cfssl gencert \
-ca=ca.pem -ca-key=ca-key.pem \
-config=ca-config.json \
-profile=etcd \
etcd-csr.json | cfssljson -bare etcd
sudo mkdir -p /etc/etcd/pki
sudo cp ca.pem etcd.pem etcd-key.pem /etc/etcd/pki/
sudo chown -R etcd:etcd /etc/etcd/pki
sudo chmod 600 /etc/etcd/pki/*-key.pem
Configurando um Cluster etcd de Três Nós
Um cluster etcd de produção precisa de três ou cinco membros. Com três membros, ele tolera uma falha e ainda mantém o quórum. Com cinco, tolera duas falhas simultâneas.
Considere três nós com os seguintes IPs:
etcd-1: 10.0.0.11etcd-2: 10.0.0.12etcd-3: 10.0.0.13
Crie /etc/etcd/etcd.conf.yml em cada nó, substituindo os valores específicos do nó:
# /etc/etcd/etcd.conf.yml — exemplo para etcd-1
name: etcd-1
data-dir: /var/lib/etcd
listen-peer-urls: https://10.0.0.11:2380
listen-client-urls: https://10.0.0.11:2379,https://127.0.0.1:2379
advertise-client-urls: https://10.0.0.11:2379
initial-advertise-peer-urls: https://10.0.0.11:2380
initial-cluster: >-
etcd-1=https://10.0.0.11:2380,
etcd-2=https://10.0.0.12:2380,
etcd-3=https://10.0.0.13:2380
initial-cluster-token: etcd-cluster-prod-01
initial-cluster-state: new
client-transport-security:
cert-file: /etc/etcd/pki/etcd.pem
key-file: /etc/etcd/pki/etcd-key.pem
trusted-ca-file: /etc/etcd/pki/ca.pem
client-cert-auth: true
peer-transport-security:
cert-file: /etc/etcd/pki/etcd.pem
key-file: /etc/etcd/pki/etcd-key.pem
trusted-ca-file: /etc/etcd/pki/ca.pem
peer-client-cert-auth: true
Crie a unidade systemd /etc/systemd/system/etcd.service em todos os nós:
[Unit]
Description=etcd distributed key-value store
Documentation=https://etcd.io
After=network.target
[Service]
User=etcd
Group=etcd
Type=notify
ExecStart=/usr/local/bin/etcd --config-file /etc/etcd/etcd.conf.yml
Restart=on-failure
RestartSec=5
LimitNOFILE=65536
[Install]
WantedBy=multi-user.target
Inicie o cluster — todos os três nós devem iniciar dentro do timeout de eleição (padrão 1 segundo) para que o bootstrap inicial seja bem-sucedido:
# Execute em todos os três nós em rápida sucessão
sudo systemctl daemon-reload
sudo systemctl enable --now etcd
Verifique se o cluster foi formado corretamente:
export ETCDCTL_API=3
export ETCDCTL_ENDPOINTS=https://10.0.0.11:2379,https://10.0.0.12:2379,https://10.0.0.13:2379
export ETCDCTL_CACERT=/etc/etcd/pki/ca.pem
export ETCDCTL_CERT=/etc/etcd/pki/etcd.pem
export ETCDCTL_KEY=/etc/etcd/pki/etcd-key.pem
etcdctl endpoint health
etcdctl endpoint status --write-out=table
etcdctl member list --write-out=table
Backup e Restauração de Snapshot do etcd
O backup do etcd é obrigatório em produção. Um snapshot captura todo o armazenamento de chave-valor em um determinado momento. Sempre faça backup antes de atualizar o etcd ou o Kubernetes.
Tirando um Snapshot
ETCDCTL_API=3 etcdctl snapshot save /backup/etcd-snapshot-$(date +%Y%m%d-%H%M%S).db \
--endpoints=https://127.0.0.1:2379 \
--cacert=/etc/etcd/pki/ca.pem \
--cert=/etc/etcd/pki/etcd.pem \
--key=/etc/etcd/pki/etcd-key.pem
# Verificar o snapshot
ETCDCTL_API=3 etcdctl snapshot status /backup/etcd-snapshot-*.db --write-out=table
Automatize com um cron job que rotaciona snapshots antigos:
# /etc/cron.d/etcd-backup
0 2 * * * etcd /usr/local/bin/etcdctl snapshot save \
/backup/etcd-$(date +\%Y\%m\%d).db \
--endpoints=https://127.0.0.1:2379 \
--cacert=/etc/etcd/pki/ca.pem \
--cert=/etc/etcd/pki/etcd.pem \
--key=/etc/etcd/pki/etcd-key.pem && \
find /backup/ -name "etcd-*.db" -mtime +7 -delete
Restaurando a Partir de um Snapshot
A restauração substitui o diretório de dados. Execute isso em cada membro do cluster:
# 1. Pare o etcd em TODOS os nós primeiro
sudo systemctl stop etcd
# 2. Restaure em cada nó (use um --name e --initial-advertise-peer-urls únicos por nó)
ETCDCTL_API=3 etcdutl snapshot restore /backup/etcd-snapshot.db \
--name etcd-1 \
--initial-cluster "etcd-1=https://10.0.0.11:2380,etcd-2=https://10.0.0.12:2380,etcd-3=https://10.0.0.13:2380" \
--initial-cluster-token etcd-cluster-prod-01 \
--initial-advertise-peer-urls https://10.0.0.11:2380 \
--data-dir /var/lib/etcd-restored
# 3. Troque o diretório de dados
sudo mv /var/lib/etcd /var/lib/etcd-old
sudo mv /var/lib/etcd-restored /var/lib/etcd
sudo chown -R etcd:etcd /var/lib/etcd
# 4. Inicie o etcd em TODOS os nós
sudo systemctl start etcd
Cenário Real: Recuperando um Plano de Controle do Kubernetes
Você tem um cluster Kubernetes de três nós onde um nó do plano de controle perdeu seu disco. O membro etcd naquele nó desapareceu e kubectl get nodes agora trava porque o servidor de API não consegue atingir quórum nas gravações.
Aqui está o caminho de recuperação:
- Verifique os membros atuais a partir de um nó saudável:
etcdctl member list. Você verá o membro com falha com uma URL vazia. - Remova o membro morto:
etcdctl member remove <MEMBER_ID> - Provisione um novo nó com o mesmo hostname e IP (ou atualize o DNS).
- Adicione o substituto:
etcdctl member add etcd-1-new --peer-urls=https://10.0.0.11:2380 - Inicie o etcd no novo nó com
ETCD_INITIAL_CLUSTER_STATE=existingna configuração — não usenew. - Acompanhe a sincronização do novo membro:
etcdctl endpoint statusmostrará o número de revisão se aproximando em tempo real.
Todo o processo normalmente leva de cinco a dez minutos para um cluster com menos de 1 GB de dados etcd. Durante a remoção e antes que o novo membro atinja o quórum, o Kubernetes continua a servir leituras, mas bloqueia gravações.
Armadilhas e Casos Especiais
Nunca execute um número par de membros etcd. Um cluster de dois membros não tem tolerância a falhas — perder um membro imediatamente perde o quórum. Um cluster de quatro membros tolera apenas uma falha, igual a três membros, mas requer um nó extra. Mantenha 3 ou 5.
O I/O de disco é o principal gargalo do etcd. O etcd chama fdatasync a cada gravação. Se a latência do disco exceder consistentemente 10ms, você verá eleições de líderes e erros de request timeout no Kubernetes. Use armazenamento SSD ou NVMe. Verifique a latência do disco com: fio --rw=write --ioengine=sync --fdatasync=1 --directory=/var/lib/etcd --size=22m --bs=2300 --name=etcd-bench.
O etcd não é um banco de dados de propósito geral. A cota de armazenamento padrão é 2 GB. Clusters Kubernetes com muitos objetos ou uso intenso de recursos personalizados podem atingir esse limite. Monitore etcd_mvcc_db_total_size_in_bytes no Prometheus e compacte/desfragmente regularmente:
# Compactar revisões antigas (manter as últimas 1000)
rev=$(etcdctl endpoint status --write-out=json | jq '.[0].Status.header.revision')
etcdctl compact $((rev - 1000))
etcdctl defrag --cluster
O desvio de relógio causa eleições de líderes. O etcd usa o horário do relógio de parede para expiração de lease. Se os nós divergirem por mais de algumas centenas de milissegundos, você verá eleições de líderes espúrias. Execute NTP (chrony ou systemd-timesyncd) em todos os nós etcd e verifique com chronyc tracking.
A restauração de snapshot limpa a associação do cluster. Após a restauração, todos os membros são tratados como um novo cluster com a associação codificada no snapshot. Nunca restaure um snapshot em um cluster em execução sem parar todos os membros primeiro — você criará uma situação de split-brain.
Solução de Problemas
etcdserver: request timed out — Geralmente latência de disco. Verifique iostat -x 1 nos nós etcd. Verifique também a conectividade de peer: etcdctl endpoint health em cada nó individualmente.
etcdserver: mvcc: database space exceeded — A cota de armazenamento de 2 GB foi atingida. Execute compactação e desfragmentação conforme mostrado acima, ou aumente a cota com --quota-backend-bytes=4294967296 (4 GB) na configuração do etcd.
raft: failed to send message — Firewall bloqueando a porta 2380 entre peers, ou incompatibilidade de CN no certificado de peer. Verifique com openssl s_client -connect 10.0.0.12:2380 a partir de outro nó etcd.
certificate has expired — Os certificados de peer e cliente do etcd precisam de rotação antes de expirarem. Clusters Kubernetes gerenciados pelo kubeadm rotacionam automaticamente esses certificados em intervalos de 90 dias a 1 ano, mas clusters gerenciados manualmente não. Verifique a expiração: openssl x509 -in /etc/etcd/pki/etcd.pem -noout -dates.
etcd usando muita memória — O etcd armazena em cache o conjunto de trabalho na memória. Em clusters com muitos objetos, o RSS pode exceder 8 GB. Isso é normal. Defina --snapshot-count=5000 (padrão 100000) para acionar snapshots mais frequentes e reduzir o tamanho do log raft na memória.
Resumo
- O etcd armazena todo o estado do cluster Kubernetes; é o serviço mais crítico no plano de controle
- Sempre implante três ou cinco membros para produção — apenas números ímpares
- Habilite TLS mútuo nas portas de cliente e peer; nunca exponha o etcd sem autenticação
- Tire snapshots diários com
etcdctl snapshot savee verifique-os comsnapshot status - Restaure parando todos os membros, executando
etcdutl snapshot restoreem cada um com parâmetros de nó únicos, trocando o diretório de dados e reiniciando - Monitore a latência do disco (mantenha abaixo de 10ms), o tamanho do banco de dados (compacte ao se aproximar de 2 GB) e a estabilidade do líder
- Use
etcdctl member remove+member addpara substituir um nó com falha sem uma restauração completa