Incidente · Sênior
Reddit Pi-Day 2023: upgrade do Kubernetes quebra o Calico
Incidente real. Pontos centrais: deploy progressivo.
Resposta curta
Incidente real. Pontos centrais: deploy progressivo. No Pi Day, 14 de março, o Reddit ficou fora do ar por 314 minutos. O post-mortem público da equipe de engenharia é a fonte deste caso. O gatilho foi um upgrade de Kubernetes, operação que a própria equipe reconhece como um ponto de risco para a disponibilidade.
01 · CONTEXTO
Um cluster legado no caminho de quase tudo
No Pi Day, 14 de março, o Reddit ficou fora do ar por 314 minutos. O post-mortem público da equipe de engenharia é a fonte deste caso. O gatilho foi um upgrade de Kubernetes, operação que a própria equipe reconhece como um ponto de risco para a disponibilidade.
Os upgrades passam primeiro por clusters dedicados a testes e depois chegam à produção, do ambiente menos crítico ao mais crítico. O cluster atualizado nesse dia era um dos mais importantes da empresa: rodava a parte legada da pilha.
Nem tudo caiu. As camadas de API modernas continuaram no ar, mas o impacto atingiu o nó legado mais crítico do grafo de dependências, e por isso a maior parte dos fluxos de usuário foi afetada.
No diagrama, a borda de CDN fica na frente do site; ela é separada do cluster de propósito, e o gráfico de tráfego citado no post vem dela.
As camadas de API modernas continuaram no ar e resilientes.
O impacto atingiu o nó legado mais crítico do grafo de dependências, e a área afetada ainda cobriu a maior parte dos fluxos de usuário.
02 · A QUEDA
Tudo parecia bem, até que o site parou de uma vez
O engenheiro iniciou o upgrade logo depois das 19:00 UTC e tudo pareceu normal por cerca de dois minutos. O upgrade era da versão 1.23 para a 1.24 do Kubernetes, e a equipe diz que o problema nunca tinha aparecido em upgrades anteriores nem em testes em ambientes não produtivos.
O cluster afetado perdeu todas as métricas. Um sintoma se destacava: o DNS não funcionava. Registros do Consul e do DNS interno do cluster não resolviam, enquanto os registros públicos resolviam normalmente.
| Sintoma | O que o post relata | |
|---|---|---|
| Observabilidade | Sem métricas | O cluster afetado perdeu todas as métricas |
| DNS interno | Não resolvia | Registros do Consul e do cluster falhavam |
| DNS público | Funcionava | Registros públicos resolviam normalmente |
| Pods | Lentos | Muito tempo para iniciar e parar |
| API server | Timeouts | Chamadas aos admission controllers expiravam |
03 · TENTAR CORRIGIR OU VOLTAR
Por que reverter não era simples
Reverter é o plano A de qualquer falha de deploy, e a equipe considerou isso de imediato. O problema é que o Kubernetes não tem procedimento de downgrade suportado. Como o upgrade executa migrações de esquema e de dados automaticamente, não existe caminho reverso definido, e voltar exige restaurar um backup e recarregar o estado.
O upgrade já incluía um backup por padrão. O restore tinha sido testado em clusters piloto, mas não acompanhava as mudanças do ambiente e nunca tinha sido usado em um cluster de produção. As estimativas iniciais eram de horas de indisponibilidade garantida, e a decisão inicial foi continuar investigando.
Durante a investigação, a equipe notou timeouts no API server ao chamar os admission controllers. O único admission controller generalizado era o OPA; apagar suas configurações de webhook fez os timeouts sumirem, mas o cluster não se recuperou.
| Tentativa | Resultado relatado |
|---|---|
| Apagar pods do calico-typha | Os novos pods não foram criados |
| Reinício em cadeia do plano de controle | Nenhuma mudança |
| Desligar e religar todo o plano de controle | Não resolveu |
| Apagar webhooks do OPA | Timeouts sumiram, mas o cluster não se recuperou |
04 · A CAUSA
Rotas que sumiram: o Calico e os route reflectors
O Calico, a interface de rede de contêineres do cluster, não funcionava bem e seus pods não estavam saudáveis. Três componentes importam. O calico-kube-controllers atribui faixas de IP aos nós. O calico-typha é um proxy agregador com cache entre o Calico e o plano de controle, para reduzir a carga na API do Kubernetes. O calico-node roda em cada nó e gera e registra as interfaces de rede dos pods.
Depois que a queda acabou, a equipe ainda não sabia o motivo, e a investigação seguiu pelos logs. Os logs estavam preservados porque o agente de logs não foi afetado. Neles, dois segundos antes do caos, o calico-node em todo o cluster começou a descartar rotas para o primeiro nó do plano de controle atualizado, o que é comportamento normal e esperado. O inesperado foi que as rotas de todos os nós também começaram a ser descartadas.
Por padrão, no Calico cada nó faz peering direto com todos os outros, em malha. Em clusters maiores isso se torna pesado, e a alternativa são os route reflectors: poucos nós fazem peering com todos e os demais só com os refletores.
O calico-node roda em cada nó e gera e registra as interfaces de rede dos pods.
O calico-typha fica entre os componentes do Calico e o plano de controle, para reduzir a carga na API do Kubernetes.
Neste cluster, os nós do plano de controle eram os refletores de rota e todos os outros nós os usavam.
Com o primeiro nó do plano de controle offline para o upgrade, o calico-node passou a descartar rotas para ele, comportamento normal e esperado.
Mas o calico-node também passou a descartar as rotas de todos os nós, o que não era esperado.
Ninguém mais sabia que os refletores existiam: todos que sabiam tinham mudado de função ou saído da empresa. Parte da configuração exigia baixar dados específicos do Calico, gerenciados só pela CLI, editá-los à mão e enviá-los de volta, e a equipe não tinha escrito ferramenta própria para tratar isso como código. Assim, a configuração não estava registrada em lugar nenhum.
Os seletores de nó e de par dos refletores apontavam para o rótulo node-role.kubernetes.io/master. Na versão 1.24 o Kubernetes removeu as referências a master, mesmo em clusters em execução, e a equipe aponta isso como a causa da queda.
05 · RESTAURAÇÃO
Voltar do backup, passo a passo
Com a queda passando de duas horas, a equipe decidiu restaurar do backup. Como a maioria dos nós de trabalho seria invalidada pelo restore, eles foram terminados, o que levou cerca de 20 minutos de chamadas de API. Ninguém envolvido tinha executado o procedimento de restore antes, e ele foi escrito para uma versão de Kubernetes já fora de suporte e anterior ao CRI-O, com instruções pensadas para Docker.
Antes do restore, os nós de trabalho foram terminados, porque a maioria seria invalidada por ele.
O procedimento terminava os outros nós do plano de controle, restaurava o backup no primeiro e o subia como plano de controle de nó único.
Após o restore do primeiro nó, nós de trabalho começaram a voltar com o autoscaler, sinal de que a rede funcionava de novo.
A capacidade da AWS para o tipo de instância do plano de controle estava esgotada, o que atrasou a subida dos novos nós.
Os novos nós não entravam: não conseguiam se conectar ao etcd do primeiro nó. O backup podia ser executado em qualquer nó do plano de controle, mas o restore tinha de ser feito no mesmo nó, e não foi.
Com novos certificados gerados por causa da diferença de hostname, os novos nós entraram e o plano de controle de alta disponibilidade voltou.
A diferença estava entre os dois procedimentos: o backup podia ser executado em qualquer nó do plano de controle, mas o restore tinha de ser feito no mesmo nó, e não foi. Por causa da diferença de hostname, foi preciso gerar novos certificados, apesar da falta de documentação.
O tráfego voltou de forma conservadora, em degraus a partir de 1% até 100%. O Reddit depende de muitos caches e há pontos onde um thundering herd pode se formar se o tráfego voltar de uma vez a 100%. Alguns serviços legados mais sensíveis foram parados manualmente e religados com cuidado.
06 · LIÇÕES
O que o desenho precisa provar
A equipe diz que vai usar a queda para mudar decisões de arquitetura e de processo e tornar os upgrades de cluster seguros. Entre as ações descritas: padronizar e compartilhar mais componentes entre ambientes, manter mais clusters de pré-produção para testar com confiança e codificar o que for possível, para aplicar de forma consistente e manter um registro histórico das escolhas.
Perguntas frequentes
O que é Reddit Pi-Day 2023: upgrade do Kubernetes quebra o Calico?
Incidente real. Pontos centrais: deploy progressivo.
O que o design de Reddit Pi-Day 2023: upgrade do Kubernetes quebra o Calico cobre?
Ele está organizado nestas seções: Um cluster legado no caminho de quase tudo, Tudo parecia bem, até que o site parou de uma vez, Por que reverter não era simples, Rotas que sumiram: o Calico e os route reflectors, Voltar do backup, passo a passo e O que o desenho precisa provar.
Quanto tempo leva Reddit Pi-Day 2023: upgrade do Kubernetes quebra o Calico e qual é o nível?
Leva cerca de 14 minutos para ler e tem nível Sênior.
Agora projete você mesmo
Rode este caso como uma entrevista na escola de System Design: você toma as decisões, o tutor as questiona e você vê a nota do seu desenho.