# OpenAI (2024): como um novo serviço de telemetria derrubou o control plane do Kubernetes

Em dezembro de 2024, a OpenAI implantou um novo agente de telemetria em toda a sua frota Kubernetes simultaneamente. A sobrecarga resultante nos API servers cascateou para uma indisponibilidade global do ChatGPT, da API e do Sora por várias horas — e o próprio control plane saturado impediu o rollback. Uma análise de como a separação entre control plane e data plane, rollouts graduais e desacoplamento de observabilidade não eram opcionais.

- URL: https://fernando.moretes.com/studies/openai-2024-kubernetes-control-plane

- Markdown: https://fernando.moretes.com/studies/openai-2024-kubernetes-control-plane/study.md?lang=pt

- Type: Post-mortem

- Company: OpenAI

- Domain: Kubernetes/Resiliência

- Date: 2024-12-11

- Tags: kubernetes, postmortem, control-plane, telemetry, openai, resiliência, dns, rollout

- Reading time: 11 min

---

Um único DaemonSet implantado sem canário. Milhões de usuários sem serviço. O control plane tão saturado que não conseguia processar o próprio rollback. O incidente da OpenAI de dezembro de 2024 não é uma história sobre software defeituoso — é uma história sobre a ausência de guardrails arquiteturais que qualquer sistema na escala de produção deveria ter por padrão.

## Ficha do Incidente

- **Empresa / Sistema:** OpenAI — ChatGPT, API pública, Sora
- **Data do incidente:** 11 de dezembro de 2024
- **Duração total:** ~3 horas de degradação severa; recuperação completa em ~4h15
- **Impacto:** Indisponibilidade global do ChatGPT, API OpenAI e Sora para todos os usuários
- **Causa raiz:** Novo agente de telemetria implantado simultaneamente em toda a frota sobrecarregou os API servers do Kubernetes
- **Fator agravante:** Cache de DNS mascarou o impacto inicial; saturação do control plane bloqueou o rollback
- **Stack relevante:** Kubernetes (frota de larga escala), DaemonSet, DNS interno, API servers, etcd
- **Classificação:** P0 — Indisponibilidade total, impacto global

## O que aconteceu

No dia 11 de dezembro de 2024, a equipe de infraestrutura da OpenAI iniciou o rollout de um novo serviço de coleta de telemetria. A intenção era legítima e comum: melhorar a observabilidade interna da frota Kubernetes, que sustenta toda a infraestrutura de inferência do ChatGPT, da API pública e do Sora. O agente foi empacotado como um DaemonSet — o mecanismo padrão do Kubernetes para rodar um pod em cada nó da frota — e a implantação foi disparada de forma ampla, atingindo um número muito grande de nós simultaneamente.

O problema não estava no código do agente em si. Estava no comportamento emergente de milhares de instâncias desse agente inicializando ao mesmo tempo e, ao fazê-lo, cada uma delas estabelecendo conexões persistentes com os API servers do Kubernetes para observar o estado do cluster — o padrão `watch` da API do Kubernetes. Em uma frota de escala de produção da OpenAI, isso significa que centenas ou milhares de conexões `watch` foram abertas em uma janela de tempo muito curta. Os API servers, que são o ponto central de controle de todo o cluster, começaram a ser saturados.

O que torna esse incidente particularmente instrutivo é o papel do cache de DNS. Durante os primeiros minutos após o início do rollout, o impacto não foi imediatamente visível nos indicadores de saúde dos serviços de usuário final. O DNS interno do cluster ainda estava resolvendo endereços a partir de entradas em cache, o que significa que o tráfego de aplicação continuou fluindo normalmente por um período. Isso criou uma janela de falsa segurança — os alertas de latência e erro dos serviços de produto não dispararam imediatamente, o que atrasou o reconhecimento de que algo estava fundamentalmente errado na camada de infraestrutura.

Quando os caches de DNS começaram a expirar e as novas resoluções precisaram passar pelos mecanismos de descoberta de serviço do Kubernetes (que dependem dos API servers já saturados), o impacto cascateou rapidamente para o plano de dados. Pods não conseguiam ser agendados, serviços não conseguiam ser descobertos, e o tráfego de usuário começou a falhar em escala global.

## Linha do Tempo

1. **T+0 — Início do rollout** — A equipe de infraestrutura inicia o deploy do novo agente de telemetria como DaemonSet em toda a frota Kubernetes. O rollout não é graduado por anéis ou percentual de nós — é aplicado de forma ampla.

2. **T+~5min — Saturação silenciosa do control plane** — Milhares de instâncias do agente inicializam simultaneamente e abrem conexões `watch` contra os API servers. A carga nos API servers e no etcd começa a subir rapidamente. Os serviços de produto ainda não reportam erros — o cache de DNS está mascarando o impacto.

3. **T+~15-20min — Expiração do cache de DNS e cascata** — As entradas de DNS em cache começam a expirar. As novas resoluções dependem da descoberta de serviço do Kubernetes, que por sua vez depende dos API servers saturados. O tráfego de usuário começa a falhar. Alertas de P0 disparam. ChatGPT, API e Sora ficam indisponíveis globalmente.

4. **T+~25min — Tentativa de rollback bloqueada** — A equipe identifica o DaemonSet como causa e tenta reverter o deploy. O próprio rollback requer que os API servers do Kubernetes processem as operações de controle — mas eles estão saturados demais para aceitar novos comandos de forma confiável. O rollback falha ou demora muito mais do que o esperado.

5. **T+~60-90min — Recuperação parcial** — À medida que alguns nós conseguem processar o rollback do DaemonSet, a pressão sobre os API servers começa a diminuir gradualmente. Alguns serviços começam a se recuperar de forma intermitente.

6. **T+~4h15 — Recuperação completa** — O rollback é concluído em toda a frota. Os API servers retornam à operação normal. ChatGPT, API e Sora são declarados totalmente operacionais. Post-mortem público é publicado no status page.

## Fluxo de Falha: Telemetria → Saturação do Control Plane → Cascata

O diagrama mostra como o DaemonSet de telemetria sobrecarregou os API servers, como o cache de DNS mascarou o impacto inicial e como a saturação do control plane bloqueou o próprio mecanismo de recuperação.

### 👤 Usuários / Clientes

- Usuários ChatGPT / API / Sora (user)

### 🌐 Data Plane — Serviços de Produto

- ChatGPT Frontend (frontend)
- OpenAI API Inferência (compute)
- Sora Video Gen (compute)

### 🔍 Observabilidade — Novo Agente (causa)

- DaemonSet Telemetria (novo) (compute)
- Backend Telemetria (data)

### ⚙️ Kubernetes Control Plane

- API Server (saturado) (compute)
- etcd (sobrecarga de leitura) (storage)
- Scheduler (bloqueado) (compute)
- Controller Manager (bloqueado) (compute)

### 🌐 DNS Interno do Cluster

- CoreDNS (cache expirando) (network)

### 🖥️ Nós do Cluster (frota)

- N Nós (frota completa) (compute)

### Fluxos

- users -> chatgpt: requisições
- users -> api_svc: requisições
- users -> sora: requisições
- chatgpt -> coredns: resolução DNS
- api_svc -> coredns: resolução DNS
- coredns -> apiserver: cache expirado → depende do control plane
- nodes -> daemonset: DaemonSet instanciado em todos os nós
- daemonset -> apiserver: milhares de watch connections simultâneas ⚠️
- daemonset -> telemetry_backend: métricas
- apiserver -> etcd: leituras de estado
- apiserver -> scheduler: bloqueado
- apiserver -> controller: bloqueado
- controller -> apiserver: rollback bloqueado ⛔

> **Causa Raiz: o control plane como ponto único de falha operacional:** O agente de telemetria foi implantado como DaemonSet em toda a frota simultaneamente, sem rollout gradual. Cada instância do agente estabeleceu conexões `watch` persistentes com os API servers do Kubernetes no momento da inicialização. A carga agregada dessas conexões — multiplicada pela escala da frota — saturou os API servers e o etcd subjacente. O fator crítico e frequentemente subestimado: o próprio mecanismo de rollback (kubectl, operadores de deploy) depende dos mesmos API servers saturados. Quando o control plane cai, você perde simultaneamente o plano de dados E a capacidade de remediar. O cache de DNS atuou como um atenuador temporal que atrasou os alertas de produto, reduzindo a janela de reação antes da cascata completa.

## A Dinâmica do Cache de DNS: um atenuador que virou armadilha

Um dos aspectos mais tecnicamente interessantes desse incidente é o papel do cache de DNS interno do cluster — e como ele transformou um problema detectável em um problema que se revelou tarde demais para uma resposta rápida.

Em um cluster Kubernetes, a resolução de nomes de serviço é feita pelo CoreDNS (ou equivalente). Quando um pod precisa se comunicar com outro serviço, ele resolve o nome DNS do serviço, que aponta para o ClusterIP correspondente. Essas resoluções são cacheadas localmente nos pods e nos resolvers intermediários com um TTL definido — tipicamente entre 5 e 30 segundos para DNS de cluster, mas a implementação real depende de como o `ndots`, `search` e os TTLs do CoreDNS estão configurados.

No momento em que o DaemonSet de telemetria começou a saturar os API servers, o tráfego de aplicação entre os serviços de produto (ChatGPT, API, Sora) continuou funcionando normalmente porque as resoluções DNS já estavam em cache. Os pods não precisavam consultar o CoreDNS para cada requisição — eles já tinham os endereços IP resolvidos. Isso criou uma janela de tempo — estimada em 15 a 20 minutos com base na progressão do incidente — durante a qual o control plane estava degradando severamente, mas os SLIs de produto (taxa de erro, latência) permaneciam dentro dos limites normais.

Essa janela de falsa normalidade é uma armadilha clássica em sistemas distribuídos: a camada de caching absorve o impacto inicial e mascara a degradação da camada subjacente. Quando os caches expiraram e as novas resoluções precisaram passar pelo CoreDNS — que por sua vez depende dos endpoints do Kubernetes atualizados pelos API servers saturados — o impacto se tornou imediato e total. Não houve degradação gradual visível para os usuários finais: foi uma transição abrupta de "tudo funcionando" para "nada funcionando".

Isso tem implicações diretas para o design de alertas: monitorar apenas SLIs de produto não é suficiente quando existe uma camada de caching entre o usuário e a infraestrutura. É necessário monitorar a saúde do control plane de forma independente, com alertas que disparem muito antes de o cache expirar — não depois.

## Remediação: quando o remédio precisa do paciente acordado

A fase de remediação desse incidente expõe uma das propriedades mais perigosas de falhas no control plane do Kubernetes: o sistema que você usa para corrigir o problema é o mesmo sistema que está quebrado.

Quando a equipe identificou o DaemonSet de telemetria como a causa e tentou executar o rollback — seja via `kubectl rollout undo`, via um operador de GitOps como ArgoCD ou Flux, ou via chamadas diretas à API — todas essas operações precisam que os API servers do Kubernetes aceitem e processem requisições de escrita. Um API server saturado por milhares de conexões `watch` ativas não tem capacidade de processamento disponível para aceitar novos comandos de controle de forma confiável. As requisições de rollback eram enfileiradas, atingiam timeouts ou falhavam completamente.

Isso não é um bug do Kubernetes — é uma consequência arquitetural esperada de um design centralizado de control plane. O etcd, que persiste o estado do cluster, também estava sob pressão de leitura elevada devido ao volume de `watch` connections, o que degradou ainda mais a capacidade dos API servers de processar qualquer coisa.

A recuperação só foi possível de forma gradual: à medida que alguns nós conseguiam processar o rollback do DaemonSet (reduzindo o número de conexões `watch` ativas), a pressão sobre os API servers diminuía incrementalmente, liberando capacidade para processar mais operações de rollback. Foi um processo de recuperação auto-limitante — cada rollback bem-sucedido habilitava o próximo, mas o progresso era lento porque cada operação competia com as conexões `watch` remanescentes.

A lição operacional aqui é que qualquer plano de resposta a incidentes para um ambiente Kubernetes de larga escala precisa incluir mecanismos de remediação que não dependam exclusivamente dos API servers. Isso pode incluir: acesso direto aos nós via SSH ou SSM para remover manualmente pods do DaemonSet; scripts de emergência que operam fora do ciclo normal de reconciliação do Kubernetes; ou, em casos extremos, procedimentos de cordon e drain que podem ser executados com conectividade parcial ao control plane. Nenhum desses mecanismos substitui a prevenção — mas a ausência de um plano de remediação alternativo transforma um incidente grave em um incidente catastrófico.

## Lições Técnicas Extraídas

- **Control plane ≠ data plane**: a saúde dos API servers do Kubernetes deve ser monitorada de forma completamente independente dos SLIs de produto. Um control plane degradado pode não se manifestar imediatamente nos serviços de usuário final devido a caches e buffers intermediários.
- **DaemonSets são multiplicadores de carga**: um DaemonSet implantado em N nós gera N instâncias simultâneas. Em frotas de centenas ou milhares de nós, o comportamento de inicialização — especialmente conexões `watch` e chamadas de API — precisa ser projetado com rate limiting, backoff exponencial e inicialização em fases.
- **Rollouts sem canário em infraestrutura crítica são inaceitáveis**: qualquer mudança que afete todos os nós de uma frota deve passar por anéis de implantação progressivos — 1%, 5%, 25%, 100% — com métricas de saúde do control plane como gate automático entre cada anel.
- **Cache de DNS como sensor de falha tardia**: o TTL do DNS de cluster é um parâmetro de resiliência, não apenas de performance. TTLs muito longos aumentam a janela de falsa normalidade; TTLs muito curtos aumentam a carga no CoreDNS e nos API servers. O ponto de equilíbrio depende da sua capacidade de detectar falhas de control plane antes que o cache expire.
- **O rollback também precisa de um plano B**: em qualquer sistema onde o mecanismo de remediação depende do componente que falhou, é necessário ter procedimentos de emergência alternativos documentados, testados e executáveis sem dependência do caminho normal de controle.
- **Serviços de observabilidade devem ser desacoplados do plano de controle que observam**: um agente de telemetria que sobrecarrega os API servers do Kubernetes para reportar métricas sobre o Kubernetes é um antipadrão fundamental. Observabilidade não pode ser o vetor de falha do sistema que ela monitora.

> **Minha leitura sênior: o que eu faria diferente:** Esse incidente me incomoda por uma razão específica: ele não é um cenário exótico. É exatamente o tipo de falha que acontece quando uma equipe de engenharia competente cresce rápido demais para que suas práticas de rollout acompanhem a escala da infraestrutura.

O que eu implementaria, em ordem de prioridade:

**1. Limites de conexão por cliente nos API servers**: o Kubernetes permite configurar `--max-requests-inflight` e `--max-mutating-requests-inflight` nos API servers, mas isso não é suficiente sozinho. O que falta é um mecanismo de admission que limite o número de `watch` connections por ServiceAccount ou por label de workload. Um DaemonSet de telemetria não deveria conseguir abrir mais do que N conexões `watch` simultâneas, independentemente de quantos nós existam na frota.

**2. Alertas de control plane como SLO primário**: eu trataria a latência do API server (p99 de requisições `LIST` e `WATCH`) e a taxa de erros do etcd como SLOs de primeira classe — não como métricas de infraestrutura que alguém verifica quando algo já quebrou. Esses alertas precisam disparar antes que o cache de DNS expire.

**3. Rollout rings obrigatórios para DaemonSets**: qualquer DaemonSet novo ou modificado deveria passar por um pipeline de promoção com gates automáticos: 1 nó → 1% → 10% → 100%, com pelo menos 10 minutos de estabilização entre cada fase e métricas de saúde do API server como condição de promoção.

**4. Runbook de emergência sem API server**: eu quero que minha equipe consiga remover um DaemonSet problemático de todos os nós mesmo que os API servers estejam inacessíveis. Isso significa ter scripts testados que operam via acesso direto aos nós (SSM, acesso de emergência), não apenas via kubectl.

**5. Isolamento de observabilidade**: agentes de telemetria que fazem `watch` no Kubernetes deveriam usar ServiceAccounts com permissões mínimas e, idealmente, operar contra um API server dedicado para workloads de observabilidade — separado dos API servers que servem o tráfego de produção. Isso é custo adicional, mas é o preço correto para evitar que sua observabilidade seja o vetor de falha da sua produção.

O que me preocupa mais nesse caso não é o que aconteceu — é que poderia ter sido muito pior. Se a frota fosse maior ou se o mecanismo de recuperação gradual não tivesse funcionado, o tempo de indisponibilidade poderia ter sido medido em dias, não em horas.

## Veredicto: escala sem maturidade operacional é risco sistêmico

O incidente da OpenAI de dezembro de 2024 é um caso de manual de como a escala amplifica falhas que seriam inofensivas em ambientes menores. Um DaemonSet com comportamento de inicialização agressivo em um cluster de 10 nós é um problema de performance. O mesmo DaemonSet em uma frota de milhares de nós é um P0 global.

A causa técnica é clara: conexões `watch` em massa saturaram os API servers do Kubernetes. Mas a causa sistêmica é mais profunda: a ausência de três propriedades arquiteturais que deveriam ser inegociáveis em qualquer sistema na escala da OpenAI.

Primeiro, **rollout gradual como invariante**, não como boa prática. Qualquer mudança que afeta todos os nós de uma frota deve ser fisicamente impossível de ser aplicada de forma simultânea sem aprovação explícita e excepcional. Isso não é processo — é uma restrição técnica no pipeline de deploy.

Segundo, **monitoramento independente do control plane**. O fato de que o impacto foi mascarado por 15-20 minutos pelo cache de DNS indica que os alertas de saúde do control plane não eram suficientemente sensíveis ou não eram monitorados com a mesma prioridade que os SLIs de produto. Em um sistema onde o control plane é o ponto de falha de tudo, ele deve ser o primeiro item no dashboard de on-call.

Terceiro, **desacoplamento entre observabilidade e o sistema observado**. Um agente de telemetria que depende dos API servers do Kubernetes para funcionar, e que ao mesmo tempo pode saturar esses API servers, cria um loop de falha que é estruturalmente inaceitável. Observabilidade deve ser projetada para ser o último sistema a falhar, não o primeiro.

A OpenAI publicou um post-mortem transparente e detalhado — o que é, por si só, uma prática de maturidade que muitas organizações não têm. O valor real desse incidente para a indústria é que ele documenta, de forma pública e específica, como a interação entre escala, caching e dependência de control plane pode criar falhas catastróficas a partir de mudanças aparentemente rotineiras. Qualquer equipe operando Kubernetes em escala deveria usar esse incidente como checklist de revisão arquitetural.

## Referências

- [OpenAI — API, ChatGPT & Sora outage post-mortem (Dec 11, 2024)](https://status.openai.com/incidents/ctrsv3lwd797)

## Fontes do caso

- [OpenAI — API, ChatGPT & Sora outage post-mortem (Dec 11, 2024)](https://status.openai.com/incidents/ctrsv3lwd797)
