Skip to main content

etcd | Banco de Dados

  • etcd | Banco de Dados

O etcd é um banco de dados key-value distribuído, fortemente consistente, usado para armazenar dados críticos de sistemas distribuídos. Ele é muito conhecido por ser o storage do Kubernetes, mas também pode ser usado para service discovery, coordenação distribuída, feature flags, locks distribuídos, configuração dinâmica e controle de estado de clusters. A própria documentação define o etcd como um key-value store distribuído, confiável e fortemente consistente para dados críticos de sistemas distribuídos. (etcd)

Quando usar etcd

Use etcd quando você precisa de:

CenárioFaz sentido?Observação
Configuração distribuídaSimExemplo: /config/api/rate-limit = 1000
Service discoverySimServiços registram presença com TTL
Leader electionSimUm nó assume liderança por lease/lock
Locks distribuídosSimÚtil para evitar execução concorrente
Estado de clusterSimExemplo: membros, workers, partições
Feature flags simplesSimSe precisar de consistência forte
Cache de alta volumetriaNãoUse Redis
Banco transacional de negócioNãoUse PostgreSQL, MySQL, MongoDB etc.
Fila/mensageriaNãoUse RabbitMQ, Kafka, NATS etc.
Eventos de grande volumeNãoetcd não é event store

Regra prática:

etcd é para metadados críticos e coordenação, não para dados de negócio volumosos.

Conceitos principais

Key-value store

O modelo é simples:

chave -> valor

Exemplo:

/config/app/theme -> dark
/services/api-01/status -> healthy
/locks/job-conciliacao -> node-01

As chaves normalmente seguem uma estrutura parecida com diretórios:

/config/api/database/url
/config/api/database/max-connections
/services/payment-api/instance-01
/services/payment-api/instance-02

Isso facilita busca por prefixo.

Consistência forte

O etcd usa o algoritmo Raft para consenso distribuído. Isso significa que o cluster precisa concordar sobre as alterações antes de considerar uma escrita como confirmada.

Em termos práticos:

  • existe um leader
  • os outros nós são followers
  • escritas passam pelo leader
  • o cluster precisa de quorum
  • se perder quorum, o cluster não consegue aceitar escrita

O etcd foi projetado para lidar com eleição de leader e falhas de máquina, inclusive falha do nó líder. (etcd)

Quorum no etcd

O quorum é a maioria dos membros do cluster.

Quantidade de membrosQuorumPode perder quantos nós?
110
220
321
532
743

Por isso, em produção, normalmente se usa 3 ou 5 membros.

Evite cluster com 2 membros. Se um cair, sobra apenas 1, e 1 de 2 não forma maioria.

Instalação com Docker

Para ambiente local:

docker run -d \
--name etcd-node-1 \
-p 2379:2379 \
-p 2380:2380 \
-v etcd-data:/etcd-data \
quay.io/coreos/etcd:v3.6.0 \
etcd \
--name=etcd-node-1 \
--data-dir=/etcd-data \
--listen-client-urls=http://0.0.0.0:2379 \
--advertise-client-urls=http://localhost:2379 \
--listen-peer-urls=http://0.0.0.0:2380 \
--initial-advertise-peer-urls=http://etcd-node-1:2380 \
--initial-cluster=etcd-node-1=http://etcd-node-1:2380 \
--initial-cluster-token=etcd-cluster-1 \
--initial-cluster-state=new

Testando:

docker exec -it etcd etcdctl endpoint health

ou no terminal próprio

etcdctl --endpoints=http://localhost:2379 endpoint health

Saída esperada:

127.0.0.1:2379 is healthy

Portas principais

PortaUso
2379Comunicação dos clients
2380Comunicação entre membros do cluster

A porta 2379 é usada por aplicações, etcdctl e clients.

A porta 2380 é usada internamente entre os nós do cluster.

Instalação local do etcdctl

O etcdctl é a CLI oficial para interagir com o etcd.

Verifique a versão:

etcdctl version

Para usar a API v3:

export ETCDCTL_API=3

Nas versões modernas, a API v3 é o padrão prático. A documentação atual destaca que a API v2 foi depreciada no etcd v3.5, enquanto a API v3 é baseada em gRPC. (etcd)

Comandos básicos com etcdctl

Inserir uma chave

etcdctl put /config/app/name "minha-api"

Buscar uma chave

etcdctl get /config/app/name

Saída:

/config/app/name
minha-api

Buscar apenas o valor

etcdctl get /config/app/name --print-value-only

Deletar uma chave

etcdctl del /config/app/name

Buscar por prefixo

etcdctl get /config/ --prefix

Exemplo:

etcdctl put /config/api/port "8080"
etcdctl put /config/api/env "production"
etcdctl put /config/api/database "postgres"

etcdctl get /config/api/ --prefix

Saída:

/config/api/database
postgres
/config/api/env
production
/config/api/port
8080

Organização de chaves

Um padrão comum é separar por domínio:

/config/<app>/<chave>
/services/<service>/<instance>
/locks/<resource>
/features/<feature-name>
/tenants/<tenant-id>/<config>

Exemplo:

etcdctl put /config/payment-api/database/host "postgres.internal"
etcdctl put /config/payment-api/database/port "5432"
etcdctl put /config/payment-api/cache/ttl "300"

Watch

O watch permite observar alterações em uma chave ou prefixo.

Observar uma chave

Terminal 1:

etcdctl watch /config/api/env

Terminal 2:

etcdctl put /config/api/env "production"

O Terminal 1 recebe o evento.

Observar por prefixo

etcdctl watch /config/api/ --prefix

Isso é útil para:

  • recarregar configuração em runtime
  • detectar mudança de feature flag
  • atualizar estado de serviços
  • reagir à entrada/saída de instâncias

A API v3 do etcd possui suporte a watch, lease, transactions e operações key-value, com modelo MVCC para histórico de revisões. (etcd)

Revisions

Cada alteração no etcd gera uma revision.

Exemplo:

etcdctl put /config/app/version "1"
etcdctl put /config/app/version "2"
etcdctl put /config/app/version "3"

Buscar metadados:

etcdctl get /config/app/version -w json

Exemplo de campos importantes:

{
"header": {
"revision": 10
},
"kvs": [
{
"key": "L2NvbmZpZy9hcHAvdmVyc2lvbg==",
"value": "Mw==",
"create_revision": 8,
"mod_revision": 10,
"version": 3
}
]
}
CampoSignificado
revisionrevision global do cluster
create_revisionrevision em que a chave foi criada
mod_revisionúltima revision em que a chave foi alterada
versionquantidade de alterações na chave

O etcd usa MVCC, permitindo visualizar versões anteriores enquanto o histórico ainda não foi compactado. (etcd)

Buscar uma revision antiga

etcdctl get /config/app/version --rev=8

Isso só funciona se a revision ainda não foi compactada.

Compactação

O etcd mantém histórico de alterações por um tempo. Para evitar crescimento infinito, é necessário compactar revisions antigas.

Exemplo:

etcdctl compact 1000

Depois disso, revisions anteriores a 1000 não ficam mais disponíveis.

Defrag

Compactar remove histórico lógico, mas pode não reduzir imediatamente o tamanho físico do banco. Para recuperar espaço em disco, use defrag.

etcdctl defrag

Em cluster:

etcdctl --endpoints=http://node1:2379 defrag
etcdctl --endpoints=http://node2:2379 defrag
etcdctl --endpoints=http://node3:2379 defrag

Leases

Lease é um TTL associado a uma ou mais chaves.

Quando o lease expira, as chaves associadas são removidas automaticamente.

Criar lease

etcdctl lease grant 30

Saída:

lease 694d... granted with TTL(30s)

Associar chave ao lease

etcdctl put /services/api/instance-01 "10.0.0.10:8080" --lease=694d...

Ver lease

etcdctl lease timetolive 694d...

Manter lease vivo

etcdctl lease keep-alive 694d...

Revogar lease

etcdctl lease revoke 694d...

Uso comum:

/services/payment-api/instance-01 -> 10.0.0.10:8080
/services/payment-api/instance-02 -> 10.0.0.11:8080

Cada instância registra sua presença com lease. Se a aplicação morrer e parar de renovar o lease, a chave desaparece.

Service discovery com etcd

Exemplo registrando uma instância:

LEASE_ID=$(etcdctl lease grant 30 | awk '{print $2}')

etcdctl put /services/catalog-api/instance-01 "http://10.0.0.10:8080" --lease=$LEASE_ID

etcdctl lease keep-alive $LEASE_ID

Consumidor buscando instâncias:

etcdctl get /services/catalog-api/ --prefix

Aplicação pode manter um watch no prefixo:

etcdctl watch /services/catalog-api/ --prefix

Assim, quando uma instância entra ou sai, os consumidores são notificados.

Locks distribuídos

O etcd pode ser usado para evitar que dois processos executem a mesma tarefa crítica ao mesmo tempo.

Exemplo:

etcdctl lock /locks/job-conciliacao

Enquanto esse comando estiver ativo, outro processo tentando adquirir o mesmo lock ficará bloqueado.

Uso típico:

Somente um worker pode executar o job X por vez.

Exemplos:

  • conciliação financeira
  • processamento de lote
  • migração de dados
  • eleição de leader
  • execução de scheduler distribuído

Transactions

Transactions permitem executar operações condicionais.

Exemplo conceitual:

SE /config/app/version ainda for revision X
ENTÃO atualize para Y
SENÃO falhe

Isso é útil para controle de concorrência otimista.

Exemplo com etcdctl txn:

etcdctl txn

Fluxo interativo:

compares:
value("/config/app/env") = "dev"

success requests:
put /config/app/env prod

failure requests:
get /config/app/env

Transactions são importantes para:

  • compare-and-swap
  • locks
  • leader election
  • atualização segura de configuração
  • evitar sobrescrita concorrente

A API do etcd organiza operações em grupos como key-value, watch e lease; também oferece transações na API v3. (etcd)

Cluster etcd com 3 nós

Exemplo de topologia:

Client URLPeer URL
etcd-1http://10.0.0.1:2379http://10.0.0.1:2380
etcd-2http://10.0.0.2:2379http://10.0.0.2:2380
etcd-3http://10.0.0.3:2379http://10.0.0.3:2380

etcd-1

etcd \
--name etcd-1 \
--data-dir /var/lib/etcd \
--listen-client-urls http://10.0.0.1:2379,http://127.0.0.1:2379 \
--advertise-client-urls http://10.0.0.1:2379 \
--listen-peer-urls http://10.0.0.1:2380 \
--initial-advertise-peer-urls http://10.0.0.1:2380 \
--initial-cluster etcd-1=http://10.0.0.1:2380,etcd-2=http://10.0.0.2:2380,etcd-3=http://10.0.0.3:2380 \
--initial-cluster-token cluster-prod-01 \
--initial-cluster-state new

etcd-2

etcd \
--name etcd-2 \
--data-dir /var/lib/etcd \
--listen-client-urls http://10.0.0.2:2379,http://127.0.0.1:2379 \
--advertise-client-urls http://10.0.0.2:2379 \
--listen-peer-urls http://10.0.0.2:2380 \
--initial-advertise-peer-urls http://10.0.0.2:2380 \
--initial-cluster etcd-1=http://10.0.0.1:2380,etcd-2=http://10.0.0.2:2380,etcd-3=http://10.0.0.3:2380 \
--initial-cluster-token cluster-prod-01 \
--initial-cluster-state new

etcd-3

etcd \
--name etcd-3 \
--data-dir /var/lib/etcd \
--listen-client-urls http://10.0.0.3:2379,http://127.0.0.1:2379 \
--advertise-client-urls http://10.0.0.3:2379 \
--listen-peer-urls http://10.0.0.3:2380 \
--initial-advertise-peer-urls http://10.0.0.3:2380 \
--initial-cluster etcd-1=http://10.0.0.1:2380,etcd-2=http://10.0.0.2:2380,etcd-3=http://10.0.0.3:2380 \
--initial-cluster-token cluster-prod-01 \
--initial-cluster-state new

Verificar saúde do cluster

etcdctl \
--endpoints=http://10.0.0.1:2379,http://10.0.0.2:2379,http://10.0.0.3:2379 \
endpoint health

Ver status dos endpoints

etcdctl \
--endpoints=http://10.0.0.1:2379,http://10.0.0.2:2379,http://10.0.0.3:2379 \
endpoint status --write-out=table

Saída típica:

+-----------------------+------------------+---------+---------+-----------+------------+-----------+------------+--------------------+--------+
| ENDPOINT | ID | VERSION | DB SIZE | IS LEADER | IS LEARNER | RAFT TERM | RAFT INDEX | RAFT APPLIED INDEX | ERRORS |
+-----------------------+------------------+---------+---------+-----------+------------+-----------+------------+--------------------+--------+
| http://10.0.0.1:2379 | abc... | 3.6.0 | 20 MB | true | false | 8 | 12345 | 12345 | |
| http://10.0.0.2:2379 | def... | 3.6.0 | 20 MB | false | false | 8 | 12345 | 12345 | |
| http://10.0.0.3:2379 | ghi... | 3.6.0 | 20 MB | false | false | 8 | 12345 | 12345 | |
+-----------------------+------------------+---------+---------+-----------+------------+-----------+------------+--------------------+--------+

Campos importantes:

CampoO que olhar
IS LEADERQual nó é o líder
RAFT TERMTermo atual do Raft
RAFT INDEXÍndice replicado
RAFT APPLIED INDEXÍndice aplicado
DB SIZETamanho do banco
ERRORSProblemas no endpoint

Adicionar membro ao cluster

No cluster existente:

etcdctl member add etcd-4 --peer-urls=http://10.0.0.4:2380

O comando retorna uma configuração que deve ser usada para iniciar o novo membro.

Exemplo para o novo nó:

etcd \
--name etcd-4 \
--data-dir /var/lib/etcd \
--listen-client-urls http://10.0.0.4:2379,http://127.0.0.1:2379 \
--advertise-client-urls http://10.0.0.4:2379 \
--listen-peer-urls http://10.0.0.4:2380 \
--initial-advertise-peer-urls http://10.0.0.4:2380 \
--initial-cluster etcd-1=http://10.0.0.1:2380,etcd-2=http://10.0.0.2:2380,etcd-3=http://10.0.0.3:2380,etcd-4=http://10.0.0.4:2380 \
--initial-cluster-state existing

Remover membro

Listar membros:

etcdctl member list

Remover:

etcdctl member remove <member-id>

Backup

Backup no etcd é feito com snapshot.

etcdctl \
--endpoints=http://127.0.0.1:2379 \
snapshot save snapshot.db

Verificar snapshot:

etcdutl snapshot status snapshot.db --write-out=table

A documentação de disaster recovery do etcd informa que uma única snapshot db é suficiente para restaurar um cluster, e que todos os membros devem restaurar usando a mesma snapshot. (etcd)

Restore

Exemplo restaurando snapshot para 3 membros.

Restaurar etcd-1

etcdutl snapshot restore snapshot.db \
--name etcd-1 \
--data-dir /var/lib/etcd-restored \
--initial-cluster etcd-1=http://10.0.0.1:2380,etcd-2=http://10.0.0.2:2380,etcd-3=http://10.0.0.3:2380 \
--initial-advertise-peer-urls http://10.0.0.1:2380

Restaurar etcd-2

etcdutl snapshot restore snapshot.db \
--name etcd-2 \
--data-dir /var/lib/etcd-restored \
--initial-cluster etcd-1=http://10.0.0.1:2380,etcd-2=http://10.0.0.2:2380,etcd-3=http://10.0.0.3:2380 \
--initial-advertise-peer-urls http://10.0.0.2:2380

Restaurar etcd-3

etcdutl snapshot restore snapshot.db \
--name etcd-3 \
--data-dir /var/lib/etcd-restored \
--initial-cluster etcd-1=http://10.0.0.1:2380,etcd-2=http://10.0.0.2:2380,etcd-3=http://10.0.0.3:2380 \
--initial-advertise-peer-urls http://10.0.0.3:2380

Depois, subir cada membro apontando para o novo data-dir.

A restauração sobrescreve metadados como member ID e cluster ID, evitando que o membro restaurado tente entrar acidentalmente no cluster antigo. (etcd)

Segurança

Em produção, não use etcd aberto sem autenticação e sem TLS.

Checklist mínimo:

  • habilitar TLS para client
  • habilitar TLS para peer
  • habilitar autenticação
  • criar usuários e roles
  • limitar acesso às portas 2379 e 2380
  • não expor etcd publicamente na internet
  • fazer backup recorrente
  • monitorar saúde do cluster

Autenticação

Criar usuário root

etcdctl user add root

Criar role root

etcdctl role add root

Dar permissão root

etcdctl user grant-role root root

Habilitar autenticação

etcdctl auth enable

Depois disso, chamadas precisam de usuário e senha:

etcdctl \
--user=root:minha-senha \
get /config/api/env

Roles e permissões

Criar role:

etcdctl role add app-config-reader

Permitir leitura em um prefixo:

etcdctl role grant-permission app-config-reader read /config/api/ --prefix

Criar usuário:

etcdctl user add minha-api

Associar role:

etcdctl user grant-role minha-api app-config-reader

Usar:

etcdctl \
--user=minha-api:senha \
get /config/api/ --prefix

TLS para clients

Exemplo de chamada com certificados:

etcdctl \
--endpoints=https://10.0.0.1:2379 \
--cacert=/etc/etcd/pki/ca.crt \
--cert=/etc/etcd/pki/client.crt \
--key=/etc/etcd/pki/client.key \
endpoint health

Configuração do servidor:

etcd \
--name etcd-1 \
--data-dir /var/lib/etcd \
--listen-client-urls https://10.0.0.1:2379 \
--advertise-client-urls https://10.0.0.1:2379 \
--client-cert-auth \
--trusted-ca-file /etc/etcd/pki/ca.crt \
--cert-file /etc/etcd/pki/server.crt \
--key-file /etc/etcd/pki/server.key

TLS entre peers

Para cluster em produção, também proteja a comunicação entre os membros:

etcd \
--name etcd-1 \
--listen-peer-urls https://10.0.0.1:2380 \
--initial-advertise-peer-urls https://10.0.0.1:2380 \
--peer-client-cert-auth \
--peer-trusted-ca-file /etc/etcd/pki/ca.crt \
--peer-cert-file /etc/etcd/pki/peer.crt \
--peer-key-file /etc/etcd/pki/peer.key

Exemplo com Docker Compose local

services:
etcd:
image: quay.io/coreos/etcd:v3.6.0
container_name: etcd-node-1
ports:
- "2379:2379"
- "2380:2380"
volumes:
- etcd-data:/etcd-data
command:
- etcd
- --name=etcd-node-1
- --data-dir=/etcd-data
- --listen-client-urls=http://0.0.0.0:2379
- --advertise-client-urls=http://localhost:2379
- --listen-peer-urls=http://0.0.0.0:2380
- --initial-advertise-peer-urls=http://etcd-node-1:2380
- --initial-cluster=etcd-node-1=http://etcd-node-1:2380
- --initial-cluster-token=etcd-cluster-1
- --initial-cluster-state=new

volumes:
etcd-data:

Subir:

docker compose up -d

Testar:

docker exec -it etcd etcdctl endpoint health

Exemplo usando etcd em aplicação .NET

Pacote comum:

dotnet add package dotnet-etcd

Exemplo básico:

using dotnet_etcd;

var client = new EtcdClient("http://localhost:2379");

await client.PutAsync("/config/minha-api/database", "postgres");

var result = await client.GetValAsync("/config/minha-api/database");

Console.WriteLine(result);

Buscar configurações por prefixo em .NET

using dotnet_etcd;
using Etcdserverpb;
using Mvccpb;

var client = new EtcdClient("http://localhost:2379");

var response = await client.GetRangeAsync("/config/minha-api/");

foreach (var kv in response.Kvs)
{
var key = kv.Key.ToStringUtf8();
var value = kv.Value.ToStringUtf8();

Console.WriteLine($"{key} = {value}");
}

Usar etcd para feature flag

Gravar flag:

etcdctl put /features/new-checkout/enabled "true"

Ler na aplicação:

var enabled = await client.GetValAsync("/features/new-checkout/enabled");

if (enabled == "true")
{
Console.WriteLine("Novo checkout habilitado");
}
else
{
Console.WriteLine("Novo checkout desabilitado");
}

Usar watch em .NET

Exemplo conceitual:

using dotnet_etcd;

var client = new EtcdClient("http://localhost:2379");

client.Watch("/features/new-checkout/enabled", watchEvent =>
{
foreach (var evt in watchEvent.Events)
{
var key = evt.Kv.Key.ToStringUtf8();
var value = evt.Kv.Value.ToStringUtf8();

Console.WriteLine($"Alteração detectada: {key} = {value}");
}
});

Uso prático:

Quando a flag muda no etcd, a aplicação atualiza o comportamento sem restart.

Padrão: configuração dinâmica

Estrutura:

/config/catalog-api/database/host
/config/catalog-api/database/port
/config/catalog-api/redis/host
/config/catalog-api/cache/default-ttl
/config/catalog-api/features/novo-fluxo

Aplicação:

  1. carrega configurações no startup
  2. mantém watch no prefixo /config/catalog-api/
  3. atualiza configuração em memória quando houver mudança
  4. usa fallback se etcd ficar indisponível

Ponto importante:

Não faça a aplicação depender de chamada ao etcd em toda requisição HTTP. Carregue em memória e atualize por watch.

Padrão: service discovery

Cada serviço registra a própria instância:

/services/payment-api/instance-01 -> http://10.0.0.10:8080
/services/payment-api/instance-02 -> http://10.0.0.11:8080

Com lease:

LEASE_ID=$(etcdctl lease grant 30 | awk '{print $2}')

etcdctl put /services/payment-api/instance-01 "http://10.0.0.10:8080" --lease=$LEASE_ID

etcdctl lease keep-alive $LEASE_ID

Consumers buscam:

etcdctl get /services/payment-api/ --prefix

Padrão: leader election

Ideia:

Vários nós tentam criar/adquirir uma chave de liderança.
Quem conseguir, vira leader.
Se o lease expirar, outro nó assume.

Estrutura:

/election/job-conciliacao/leader -> worker-03

Uso:

  • scheduler distribuído
  • processamento singleton
  • jobs críticos
  • orquestração de workers

Padrão: lock distribuído

Exemplo:

etcdctl lock /locks/fechamento-caixa

Enquanto o lock estiver ativo, outro processo não entra na seção crítica.

Uso típico:

Apenas um processo pode fazer fechamento de caixa por vez.

Observabilidade

Ver saúde:

etcdctl endpoint health

Ver status:

etcdctl endpoint status --write-out=table

Ver alarmes:

etcdctl alarm list

Ver membros:

etcdctl member list

Métricas Prometheus

O etcd expõe métricas HTTP normalmente no endpoint:

/metrics

Exemplo:

curl http://localhost:2379/metrics

Métricas importantes:

MétricaO que indica
etcd_server_has_leaderSe o nó enxerga leader
etcd_server_leader_changes_seen_totalTrocas de leader
etcd_disk_wal_fsync_duration_secondsLatência de escrita no WAL
etcd_disk_backend_commit_duration_secondsLatência de commit no backend
etcd_mvcc_db_total_size_in_bytesTamanho total do banco
etcd_network_peer_round_trip_time_secondsLatência entre peers
grpc_server_handled_totalRequisições gRPC processadas

Alertas úteis:

etcd_server_has_leader == 0
rate(etcd_server_leader_changes_seen_total[5m]) > 0
etcd_mvcc_db_total_size_in_bytes crescendo muito rápido

Manutenção

Rotina recomendada:

TarefaFrequência
Snapshot backuprecorrente
Teste de restorerecorrente
Compactaçãoconforme volume
Defragquando DB físico crescer
Monitorar leader changescontínuo
Monitorar latência de discocontínuo
Monitorar quorumcontínuo

O próprio guia de upgrade do etcd recomenda criar e baixar snapshot antes de upgrade, para permitir restauração em caso de problema. (etcd)

Boas práticas

Use número ímpar de membros

Prefira:

3 ou 5 membros

Evite:

2 membros

Use disco rápido

etcd é sensível a latência de disco porque depende de WAL e persistência.

Evite:

  • disco lento
  • disco compartilhado ruim
  • storage de rede instável
  • alta contenção de I/O

Não grave payload grande

Ruim:

/config/blob-gigante -> JSON de 10 MB

Melhor:

/config/blob-ref -> s3://bucket/config.json

Armazene no etcd apenas metadados ou referências.

Não use como cache

Para cache:

Redis

Para coordenação:

etcd

Não exponha publicamente

Bloqueie:

0.0.0.0:2379 na internet
0.0.0.0:2380 na internet

Permita apenas:

aplicações internas
membros do cluster
rede privada

Tenha backup testado

Backup sem restore testado é só uma esperança.

Tenha:

  • snapshot automatizado
  • retenção
  • cópia externa
  • teste periódico de restore
  • runbook documentado

Erros comuns

Usar cluster com 2 nós

Problema:

Se um nó cair, o cluster perde quorum.

Use 3 membros.

Usar etcd como banco de negócio

Errado:

/orders/123
/customers/456
/invoices/789

Use banco relacional/documento para isso.

Fazer leitura no etcd a cada request

Errado:

Request HTTP -> busca config no etcd -> responde

Melhor:

Startup -> carrega config
Watch -> atualiza cache local
Request HTTP -> usa config em memória

Não configurar compactação

Problema:

Histórico cresce indefinidamente.

Configure rotina de compactação.

Não monitorar leader changes

Trocas frequentes de leader indicam problema:

  • rede instável
  • disco lento
  • CPU saturada
  • timeout mal configurado
  • nó com pausa de GC ou contenção

Comandos úteis

Inserir

etcdctl put /foo "bar"

Ler

etcdctl get /foo

Ler por prefixo

etcdctl get /foo --prefix

Deletar

etcdctl del /foo

Deletar por prefixo

etcdctl del /foo --prefix

Watch

etcdctl watch /foo

Watch por prefixo

etcdctl watch /foo --prefix

Criar lease

etcdctl lease grant 60

Listar lease

etcdctl lease list

Ver TTL

etcdctl lease timetolive <lease-id>

Renovar lease

etcdctl lease keep-alive <lease-id>

Revogar lease

etcdctl lease revoke <lease-id>

Lock

etcdctl lock /locks/minha-tarefa

Snapshot

etcdctl snapshot save snapshot.db

Status do snapshot

etcdutl snapshot status snapshot.db --write-out=table

Health

etcdctl endpoint health

Status

etcdctl endpoint status --write-out=table

Membros

etcdctl member list

Exemplo de runbook básico

Verificar se o cluster está saudável

etcdctl \
--endpoints=http://10.0.0.1:2379,http://10.0.0.2:2379,http://10.0.0.3:2379 \
endpoint health

Ver quem é o leader

etcdctl \
--endpoints=http://10.0.0.1:2379,http://10.0.0.2:2379,http://10.0.0.3:2379 \
endpoint status --write-out=table

Fazer backup manual

etcdctl \
--endpoints=http://10.0.0.1:2379 \
snapshot save /backup/etcd-$(date +%Y%m%d-%H%M%S).db

Verificar backup

etcdutl snapshot status /backup/etcd-20260522-120000.db --write-out=table

Compactar

REVISION=$(etcdctl endpoint status --write-out=json | jq '.[0].Status.header.revision')

etcdctl compact $REVISION

Defrag

etcdctl defrag

Checklist de produção

ItemObrigatório?
Cluster com 3 ou 5 membrosSim
TLS clientSim
TLS peerSim
AutenticaçãoSim
Backup automatizadoSim
Restore testadoSim
Métricas PrometheusSim
Alertas de leader/quorumSim
Disco rápidoSim
Rede privada entre peersSim
Firewall nas portas 2379 e 2380Sim
Compactação/defrag planejadosSim
Não armazenar payload giganteSim
Não usar como banco transacionalSim

Resumo mental

PerguntaResposta
etcd é banco de dados?Sim, key-value distribuído
É para dados de negócio?Não é o ideal
É para coordenação?Sim
Tem consistência forte?Sim
Usa Raft?Sim
Precisa de quorum?Sim
Pode usar com Kubernetes?Sim, Kubernetes usa etcd como storage do estado do cluster
Serve para service discovery?Sim
Serve para lock distribuído?Sim
Serve como Redis?Não
Serve como fila?Não
Precisa de backup?Sim
Precisa de TLS em produção?Sim
Cluster com 2 nós é bom?Não