O mapa de failure domains, e o teste de failover que o prova
A alta disponibilidade é uma afirmação até ser testada. Como mapear réplicas a hosts, arrays e chassis, como impor anti-affinity e como correr uma folha de testes de failover.

Todos os diagramas de plataforma têm três caixas de base de dados, dois load balancers e um par de cache, e cada um deles tem a etiqueta «alta disponibilidade». Se o é, depende de dois documentos que a maioria das construções nunca produz: um mapa de que coisas físicas cada réplica depende, e uma folha de testes que regista o que aconteceu quando cada uma delas foi retirada. Eis como escrevemos os dois.
O problema: três réplicas podem ser uma falha
A redundância conta cópias. A disponibilidade depende de essas cópias poderem falhar de forma independente. Três nós de base de dados em três máquinas virtuais que o scheduler por acaso colocou em dois hosts são, para uma falha de host, dois nós. Três nós em três hosts cujos discos vivem todos num único array de storage são, para uma falha de array, nenhum. Nada na aplicação ou no dashboard lhe diz isto. Tem de o escrever.
Passo um: liste os failure domains
Para uma plataforma típica, liste pelo menos:
- Host: o servidor físico ou o blade.
- Chassis ou enclosure: os blades partilham alimentação, refrigeração e interconnects.
- Array de storage: e, por baixo dele, o caminho do storage fabric.
- Rede: o par de switches top of rack, os uplinks, o edge.
- Site: alimentação elétrica, refrigeração, o próprio edifício.
Depois decida quais deles a plataforma tem de sobreviver. Sobreviver à perda de qualquer host e de qualquer array é uma base sensata. Sobreviver a um site inteiro precisa de um segundo site e é um desenho diferente.
Passo dois: desenhe o mapa
Faça uma tabela com uma linha por membro de cada camada redundante e uma coluna por failure domain:
| Camada | Membro | Host | Chassis | Array |
|---|---|---|---|---|
| database | db-a | host 1 | enclosure 1 | array A |
| database | db-b | host 2 | enclosure 2 | array B |
| database | db-c | host 3 | enclosure 1 | array C |
| cache | cache-a | host 2 | enclosure 2 | array A |
| ... |
A regra é simples: dentro de uma camada, nenhum failure domain que escolheu sobreviver pode deter a maioria dos membros. Leia cada coluna de cima a baixo para cada camada. Dois dos três membros da base de dados no enclosure 1 significa que uma falha de enclosure quebra o quorum. Corrija a colocação, ou aceite o risco por escrito.
Passo três: acerte a aritmética do quorum
Se precisa de sobreviver a duas falhas simultâneas de host, como uma camada de storage muitas vezes deve, precisa de cinco membros em cinco domínios separados, não de quatro: um quarto membro acrescenta custo sem acrescentar tolerância.
Passo quatro: faça o scheduler impor o mapa
Um mapa que depende de alguém colocar as máquinas corretamente estará errado depois da primeira manutenção. Faça a plataforma impô-lo.
Num gestor de virtualização como o OLVM, crie um affinity group negativo e enforcing por camada, para que dois membros nunca possam correr no mesmo host, mesmo depois de um host ser esvaziado.
Em Kubernetes, use required pod anti-affinity e um PodDisruptionBudget para cada carga de trabalho com quorum:
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
[ { labelSelector: { matchLabels: { app: galera } },
topologyKey: kubernetes.io/hostname } ]
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata: { name: galera }
spec:
minAvailable: 2
selector:
matchLabels: { app: galera }
O anti-affinity mantém os membros em nós diferentes. Etiquete os nós por chassis e acrescente uma segunda regra sobre essa label se os enclosures forem um domínio. O budget significa que uma atualização rolante de nós nunca pode expulsar um segundo membro enquanto um já está em baixo. Verifique o resultado, não a intenção:
kubectl get pods -l app=galera -o wide
Passo cinco: a folha de testes de failover
Agora prove-o. Para cada camada, retire um membro como uma falha real o faria, com a aplicação ligada e tráfego real a fluir, e registe o que aconteceu:
| Ação | Esperado | Medido | O que os clientes viram |
|---|---|---|---|
| parar o writer da base de dados | o proxy move as escritas para um sobrevivente | segundos até as escritas retomarem | |
| parar o primário da cache | o Sentinel promove uma réplica | segundos até à promoção | |
| derrubar um nó de edge | o endereço flutuante move-se para o peer | segundos, em cada direção | |
| desligar um host | os seus membros reconstroem-se noutro lado, o quorum mantém-se | ||
| desligar um caminho do array | o tráfego de storage continua pelo outro caminho |
Corra uma probe com timestamps a partir de fora durante cada teste, para que «o que os clientes viram» seja uma medição:
while true; do
printf '%s ' "$(date +%T.%N)"
curl -s -o /dev/null -w '%{http_code} %{time_total}\n' https://app.example.com/health
sleep 0.2
done | tee failover-$(date +%F).log
Depois reponha cada membro e registe que se juntou de novo de forma limpa, como réplica do novo primário e não como rival dele. Um teste que termina com dois primários encontrou o bug mais importante da folha.
Passo seis: peça a outra pessoa que o verifique
A pessoa que construiu uma plataforma lê as notas de construção quando a verifica, e as notas dizem o que foi pretendido. Peça a um segundo engenheiro que verifique o mapa contra a plataforma em produção a partir de outra máquina: consulte o gestor de virtualização quanto à colocação real, o storage quanto à localização real dos discos, o cluster quanto à composição real. As diferenças entre o mapa e a realidade são as descobertas que importam.
A sua lista de verificação
- Os failure domains a que vai sobreviver, escritos.
- Um mapa de cada membro de cada camada contra esses domínios, sem maioria num só domínio.
- Tamanhos de quorum escolhidos por aritmética, apenas números ímpares.
- Anti-affinity e disruption budgets impostos pela plataforma, e verificados.
- Uma folha de testes de failover com tempos medidos e resultados do lado dos clientes para cada camada.
- Verificação independente contra a plataforma em produção, não contra as notas.
Se quer uma segunda opinião sobre quão independente é realmente a sua redundância, teremos todo o gosto em mapeá-la consigo.
Relacionados: Construção de plataformas de alta disponibilidade · Bases de dados em cluster com Percona XtraDB Cluster · Object caching com failover automático
Publicado em 17 de agosto de 2026.
Todas as notas de campo