Saltar para o conteúdo
EuroVPSEuroVPS

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.

Por EuroVPS Engineering

5 min de leitura
The failure domain map, and the handover test that proves it

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:

CamadaMembroHostChassisArray
databasedb-ahost 1enclosure 1array A
databasedb-bhost 2enclosure 2array B
databasedb-chost 3enclosure 1array C
cachecache-ahost 2enclosure 2array 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çãoEsperadoMedidoO que os clientes viram
parar o writer da base de dadoso proxy move as escritas para um sobreviventesegundos até as escritas retomarem
parar o primário da cacheo Sentinel promove uma réplicasegundos até à promoção
derrubar um nó de edgeo endereço flutuante move-se para o peersegundos, em cada direção
desligar um hostos seus membros reconstroem-se noutro lado, o quorum mantém-se
desligar um caminho do arrayo 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.

Fale com um engenheiro

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