Data de expiração 6/4/2021

Em 6 de abril de 2021, tivemos um certificado TLS curinga que expirou inesperadamente. É constrangedor quando um certificado expira, mas sentimos que era importante compartilhar nossa história aqui, na esperança de que outros também possam aproveitar nosso aprendizado e melhorar seus sistemas. Se você ou sua organização estiver usando monitoramento de certificados, este pode ser um bom lembrete para verificar se há lacunas nesses sistemas.

O certificado que expirou era usado em muitos serviços internos da Epic — na verdade, até demais. Apesar de nos esforçarmos ao máximo para monitorar a expiração dos nossos certificados, não cobrimos totalmente todas as áreas onde os certificados estavam sendo usados. Depois da expiração e renovação do certificado, uma série de eventos inesperados ocorreram e prolongaram a interrupção. Este post traz mais detalhes sobre isso.

Componentes fundamentais, como nossos sistemas de identidade e autenticação, foram afetados, e esses serviços afetam diversos outros serviços em todo o nosso ecossistema. Os seguintes impactos foram observados ou relatados:

  • Os logins da conta da Epic falharam em qualquer produto que usasse esta forma de autenticação, incluindo Fortnite, Rocket League, Houseparty, Epic Online Services ou a Epic Games Store
  • Desconexões de jogos ao vivo ou serviços de todas as plataformas
  • Falha na compra de itens no inicializador da Epic Games
  • Comportamento inesperado no inicializador da Epic Games, como falha no carregamento de conteúdos ou no funcionamento do modo offline
  • As páginas de produtos e marketing da Epic Games ficaram indisponíveis ou com funcionamento falho, incluindo páginas do Unreal Engine
  • Vários problemas com ferramentas internas que afetaram a capacidade dos funcionários da Epic de resolver ou gerenciar problemas

Este post tem como objetivo fornecer informações detalhadas sobre o que aconteceu, o que aprendemos e as ações que tomaremos no futuro.


O que aconteceu?


Três sequências principais de eventos ocorreram:

  1. Um certificado expirado causou uma interrupção em uma grande parte das chamadas internas de serviço a serviço de back-end e ferramentas de gerenciamento internas
  2. Aumentos inesperados e significativos de tráfego no inicializador da Epic Games, serviço interrompido no inicializador da Epic Games e em recursos de distribuição de conteúdo
  3. Uma versão incorreta da página da Epic Games Store com referência a artefatos e recursos inválidos foi utilizada como parte do escalonamento automático, impactando negativamente a experiência na Epic Games Store

 

1) Certificado expirado

Em 6 de abril às 12h00 UTC, um certificado TLS expirou. Esse certificado era usado em uma grande quantidade de comunicações exclusivamente internas na plataforma de back-end da Epic. Usamos criptografia TLS entre nossos serviços de back-end para chamadas de API entre serviços e ferramentas de gerenciamento interno. Esse certificado serve para uma zona de DNS interna, que não é voltada para o público. 

Às 12h00 UTC, o tráfego foi efetivamente interrompido entre os sistemas de back-end. Seis minutos depois, às 12h06 UTC, o incidente foi relatado e nosso processo de incidentes foi iniciado. Embora vários alarmes tenham disparado, também sempre incentivamos todos na empresa a relatar quaisquer problemas de amplo impacto com os quais possam se deparar. Cada incidente passa por uma triagem por nossa equipe de Live Ops, disponível 24 horas por dia, 7 dias por semana, e a qual dá início ao nosso processo de gerenciamento de incidentes. Quando o primeiro relatório interno chegou, nossas ferramentas e processos de gerenciamento de incidentes automaticamente criaram um canal do Slack, e as pessoas relevantes foram convidadas ou notificadas sobre o incidente.

Às 12h12 UTC, confirmamos a expiração de um certificado, que acreditamos ser a fonte dos problemas, e iniciamos o processo de renovação. Às 12h37 UTC, o certificado foi reemitido, e o certificado atualizado começou a ser implantado em nossos serviços de back-end. Ao longo dos 5 a 15 minutos seguintes, os balanceadores de carga começaram a implantar automaticamente o novo certificado em endpoints internos, e nossas chamadas HTTPS de serviço a serviço foram recuperadas junto com nossas interfaces de gerenciamento.

Nossa equipe de Live Ops que fez a triagem desse incidente também cuidou de seu gerenciamento nesta etapa — comunicando-se com os funcionários e envolvendo as pessoas certas — e, às 12h38 UTC, uma reunião pelo Zoom foi iniciada para coordenar as pessoas que estavam colaborando no Slack. Embora o Slack seja uma boa ferramenta de comunicação, em situações urgentes, nada supera a comunicação ao vivo em tempo real por voz ou vídeo. Atualizações sobre o incidente eram enviadas regularmente para as partes internas interessadas por meio de nossas ferramentas e processos para manter todos a par do que estava acontecendo. Nesse ponto, havia mais de 25 pessoas diretamente envolvidas e trabalhando no problema, com muitas outras observando: do Suporte ao Jogador, da Comunidade, da Engenharia e da Produção, em muitos de nossos diferentes produtos e equipes.

Um gráfico de contagens de solicitacões por minuto para um único microsserviço, com uma queda no momento da interrupção do certificado e uma subida no momento da recuperação total.

 

Fatores que contribuíram


As zonas de DNS para essa comunicação interna de serviço a serviço não eram monitoradas ativamente por nossos serviços de monitoramento de certificados, um descuido nosso. Nossos serviços de monitoramento de certificados focam em namespaces DNS inteiros, não em endpoints ou certificados individuais, e a configuração para esta zona interna estava faltando. Desde então, mudamos esta zona para a nossa solução de monitoramento mais recente, que preenche essa lacuna. Antes desse incidente, também havíamos iniciado um projeto para habilitar e configurar o AWS Config globalmente em nossas várias contas. Com essa configuração global, podemos adicionar facilmente uma regra do AWS Config, permitindo o alarme de defesa aprofundada para a expiração de certificado

As renovações automáticas não foram habilitadas para este certificado interno, e o trabalho necessário para realizar isso não havia sido priorizado quando identificado no início deste ano. Nós temos os sistemas e serviços adequados em vigor para facilitar a renovação automática, mas a migração para usar esses recursos não foi concluída antes desse incidente. Com os nossos sistemas de monitoramento existentes, acreditávamos estar mais protegidos contra os perigos da expiração de certificados do que estávamos de fato. Vamos continuar trabalhando para transferir este certificado e outros para renovações automatizadas. Nesse ínterim, concluímos uma auditoria manual de todos os nossos certificados.

O certificado curinga de serviço a serviço usado estava instalado em centenas de serviços de produção diferentes e, por causa disso, o impacto foi muito amplo. Usamos o AWS ACM (AWS Certificate Manager) para gerenciar esse certificado, o que nos permitiu renová-lo e aplicá-lo rapidamente em centenas de serviços de produção em questão de minutos. O problema de expiração não teve nada a ver com o AWS ACM em si, mas com o nosso gerenciamento do nosso próprio certificado. Vamos trabalhar na separação do raio de explosão de nossos certificados, e parte disso se dará com a atualização de nossos processos para uso de certificado com o AWS ACM.

 

2) Aumentos significativos de tráfego para o serviço do inicializador da Epic Games

Embora a maioria dos serviços tenha se recuperado imediatamente após a renovação do certificado, nossos serviços do inicializador da Epic Games continuaram indisponíveis.

Às 12h46 UTC, após a emissão do certificado, um aumento na taxa de solicitação sobrecarregou o serviço do inicializador da Epic Games, um serviço de back-end-chave que oferece suporte ao cliente do inicializador da Epic Games. O aumento da taxa de solicitação foi causado por uma lógica de novas tentativas inesperada em clientes, vista apenas em cenários de falha. Embora tenhamos trabalhado muito na resiliência do inicializador da Epic Games ao longo dos anos, esse caso de aumento de solicitações foi inesperado. Os limites de rastreamento de conexão foram atingidos em nossos hosts e pacotes foram descartados em toda a frota, tornando a recuperação mais difícil, mesmo com a expansão de nossa frota de aplicativos de back-end em 250%. Os serviços do inicializador da Epic Games sofreram uma falha em cascata e interrupção total, e a recuperação exigiu a limitação do tráfego para o back-end e, em seguida, a adição incremental de tráfego de volta ao sistema, aumentando simultaneamente nossos limites de rastreamento de conexão.

Nossa grande pegada de clientes do inicializador da Epic Games estava gerando dezenas de milhões de conexões com o serviço de back-end do inicializador da Epic Games e componentes dos sistemas do inicializador ficaram degradados com a carga. Precisávamos drenar o tráfego para o back-end para permitir que os sistemas se recuperassem. Embora normalmente tenhamos capacidade de pico disponível para este serviço, ela não permitiu que o serviço aguentasse nem mesmo a carga de 28x que observamos no início da interrupção.

Um gráfico de contagens de solicitações por minuto para o nosso balanceador de carga de back-end do inicializador da Epic Games. O tráfego cresceu 28x inicialmente, e a explosão final às 15h12 UTC foi 40x a taxa normal.


Embora nossa contagem de solicitações tenha sido superior a 28x o normal, o grande número de conexões com o serviço de back-end do inicializador da Epic Games esgotou o espaço de rastreamento de conexão disponível, resultando em perda de pacotes e, por fim, na degradação da conectividade dos nós de back-end. Nossa carga de conexão de back-end aumentou em 3200x a nossa taxa normal. O aumento nas conexões TCP foi significativamente maior do que a quantidade de solicitações.

Um gráfico de novas contagens de conexão por minuto com o nosso balanceador de carga de back-end do inicializador da Epic Games com um aumento de 3200x nas conexões em comparação com o pico normal.

 

Fatores que contribuíram


O certificado TLS que expirou criou uma interrupção que desencadeou um comportamento inesperado em nosso cliente do inicializador. Nossa investigação revelou que as novas tentativas do cliente estavam usando a lógica linear de novas tentativas em vez do backoff exponencial que esperávamos. Um outro bug inesperado também fez com que o padrão de solicitação de milhões de clientes do inicializador da Epic Games fizesse novas tentativas contínua e indefinidamente, até que uma resposta bem-sucedida fosse recebida. Esses dois bugs em nossa base de instalação de clientes criaram um padrão de chamada não-intencional e imprevisto. Sofremos, de fato, um ataque DDoS (ataque distribuído de negação de serviço) por parte de nossos próprios clientes, e estamos trabalhando urgentemente para corrigir esses bugs em uma atualização do inicializador da Epic Games. 

Um fator interessante que contribui para essa parte do incidente é a duração da interrupção inicial. Quanto mais a interrupção durava, maior era a probabilidade de mais clientes utilizarem a lógica de novas tentativas defeituosa e chamarem continuamente o nosso back-end. Se a interrupção inicial tivesse sido mais curta, talvez não tivéssemos acumulado clientes suficientes fazendo chamadas de novas tentativas contínuas a ponto de sobrecarregar o sistema, e somente uma interrupção com tal duração teria revelado esse caso. Vamos resolver isso por meio de nossas mudanças de padrão de chamada.

Nosso alarme para rastreamento de conexão não foi bem compreendido. Este alarme disparou durante o incidente com o serviço do inicializador da Epic Games e, embora várias equipes estejam familiarizadas com o significado desse alarme, sua descrição e notificação não eram claras o suficiente, e não se sabia que essa condição causaria a perda de pacotes para qualquer conexão que estes hosts fariam, incluindo conectividade com um cluster Redis interno. Esse foi um momento estressante para a equipe que investigava o que poderia estar acontecendo com a degradação da conectividade com o cluster Redis. Suspeita-se que nossos mecanismos de cache sejam parte da causa. Posteriormente, descobriu-se que isso se deveu à perda de pacotes causada pela tabela de rastreamento de conexão cheia, com várias centenas de milhares de conexões em uso. Mais à frente, no incidente, aumentamos nossos limites de rastreamento de conexão para mais de um milhão por nó, mas os aumentos de rastreamento de conexão em nossa infraestrutura não são instantâneos e demoram algum tempo. Trabalharemos na atualização de nosso alarme para deixar mais claro que isso causará grandes problemas de rede até que seja resolvido. 

O aumento de escala resultou em novos nós atingindo instantaneamente os limites de rastreamento de conexão. Como nossa frota estava sobrecarregada com conexões, causando graves perdas de pacotes, precisávamos reduzir o tráfego geral para a frota e aumentar lentamente o tráfego permitido. Primeiro, tentamos usar o AWS WAF (Web Application Firewall) para limitar o tráfego a um subconjunto do tráfego de entrada, mas nossa configuração não limitou o tráfego o suficiente. O problema não era com o AWS WAF, mas sim com o nosso próprio conjunto de regras especificado. Por questão de tempo, usamos nossos pesos-alvo do balanceador de carga do AWS para mover parte do tráfego, o que, junto com o aumento de nossos limites de rastreamento de conexão, foi exitoso. O uso do WAF neste cenário atrasou nossa recuperação dos serviços do inicializador da Epic Games, mas não foi culpa do AWS. Desenvolveremos um processo padrão para descarte de carga de tráfego com urgência em situações críticas como esta usando AWS WAF, pesos-alvo do balanceador de carga ou outras tecnologias AWS.

 

3) Recursos inválidos no site da Epic Games Store

Às 15h12 UTC, com o nosso certificado renovado e nosso serviço do inicializador da Epic Games recuperado, procedemos ao desbloqueio de todos os clientes que chamavam a nossa Epic Games Store. Devido à duração da interrupção, havia significativamente mais clientes do que o normal solicitando conteúdo da nossa Epic Games Store, o que começou a aumentar naturalmente. Começamos a avaliar os impactos remanescentes por volta das 15h30 UTC.

Tudo parecia normal no início, mas começamos a receber relatórios internos de problemas de layout e erros na Loja, que pudemos confirmar e reproduzir. Ao investigar os detalhes, percebemos que o cliente web (como um usuário navegando em epicgames.com interagiria com a Loja) estava tentando buscar um ID de recurso exclusivo que não estava presente em nossa CDN. Verificamos nossas versões de contêiner implantadas em toda a frota e eram todas iguais, mas se isso fosse verdade, como a mesma versão do aplicativo poderia estar retornando valores de recursos estáticos que eram diferentes? 

Algo não estava certo. Este foi um período muito confuso do incidente e, no final das contas, muitos dos sinais que tínhamos disponíveis (como versões implementadas) se revelaram falsos. Conseguimos correlacionar o escalonamento do back-end da Epic Games Store a um aumento de 403s em nossa CDN, o que nos levou a um caminho de investigação das novas instâncias com mais detalhes. Ao transferir o conteúdo (curling) localmente nas novas instâncias, descobrimos que o conteúdo retornado era inválido. Conseguimos rastrear isso a um envio inesperado de contêiner para um novo fluxo de trabalho de CI/CD, feito no dia anterior e totalmente não-relacionado a tudo o que havíamos encontrado até então durante o incidente. Esses resultados ainda eram surpreendentes, mas depois de finalmente descobrir isso, pudemos reverter rapidamente a versão do contêiner, encerrar as instâncias inválidas e restaurar o tráfego.

Este problema poderia ter se apresentado durante qualquer aumento de grande escala ocorrido neste período, mas como normalmente mantemos bastante espaço livre em toda a frota, esse problema não surgiu até o aumento em grande escala da Epic Games Store ocorrido devido ao tráfego no inicializador da Epic Games.

 

Fatores contribuintes


A interrupção do certificado levou a problemas do inicializador da Epic Games, que, após a recuperação, criaram uma tempestade de solicitações para a Epic Games Store, o que resultou em um escalonamento dos sistemas da Epic Games Store. Isso é esperado e bem-vindo.

Nossos sinais e dados sobre o estado das versões em nossa frota de aplicativos nos levaram a acreditar que a implantação de nossa frota era uniforme. Mudamos nosso esquema de controle de versão para ajudar a evitar diagnósticos incorretos no futuro.

Uma mudança recente no pipeline de CI/CD para a Epic Games Store apresentava uma configuração incorreta, que atualizou o artefato do aplicativo inesperadamente. Isso foi corrigido com uma modificação em nosso pipeline de CI/CD, revertendo as mudanças inesperadas. Nossa mudança no esquema de controle de versão nos protegerá se isso acontecer novamente.


Linha do tempo

  • 12h00 UTC - Certificado interno expirado
  • 12h06 UTC - Incidente relatado e gerenciamento de incidente iniciado
  • 12h15 UTC - Primeira mensagem para o cliente preparada
  • 12h21 UTC - Confirmação de várias falhas grandes de serviço por várias equipes
  • 12h25 UTC - Confirmação de que o processo de reemissão do certificado foi iniciado
  • 12h37 UTC - Reemissão do certificado confirmada
  • 12h46 UTC - Recuperação de alguns serviços confirmada
  • 12h54 UTC - Rastreamento de conexão descoberto como um problema para o serviço do inicializador da Epic Games
  • 13h41 UTC - Nós do serviço do inicializador da Epic Games reiniciados
  • 15h05 UTC - Limites de rastreamento de conexão aumentados para o serviço do inicializador da Epic Games
  • 15h12 UTC - Primeiros sinais de recuperação do serviço do inicializador da Epic Games
  • 15h34 UTC - O serviço da web da Epic Games Store aumenta
  • 15h59 UTC - Primeiros relatos de recursos ausentes na Epic Games Store
  • 16h57 UTC - Problema com versões incompatíveis do serviço da web da Epic Games Store descoberto
  • 17h22 UTC - Versão do serviço da web da Epic Games Store corrigida
  • 17h35 UTC - Recuperação total


O que vem agora?

Nas seções acima, cobrimos os cenários que levaram às surpresas e, por fim, à interrupção em 6 de abril. Mencionamos nossas próximas etapas juntamente com nossos fatores contribuintes, mas vamos recapitulá-los aqui também. 

Não há uma causa-raiz única para esses problemas. Uma miríade de fatores, tanto tecnológicos quanto organizacionais, contribuíram para os eventos que se desenrolaram. O escopo e a duração da interrupção nos ajudaram a descobrir não apenas bugs explícitos em nossos sistemas — que trabalharemos para corrigir — mas também suposições anteriormente não questionadas em alguns de nossos processos internos, especialmente aqueles que regem o gerenciamento de certificados. 

Embora tenhamos agido imediatamente para cobrir esta zona com o nosso mais recente sistema de monitoramento de certificados e auditado todos os certificados conhecidos existentes, vamos analisar mais a fundo quaisquer lacunas adicionais em nosso monitoramento de certificados e adicionar medidas à prova de futuro, como monitoramento no AWS Config para todos os certificados baseados no AWS ACM. Também trabalharemos para reduzir o raio de explosão de qualquer certificado específico.

Vamos analisar mais atentamente os padrões de chamada dos nossos clientes do inicializador da Epic Games e corrigir urgentemente alguns dos bugs que identificamos como parte disso, bem como melhorar nossa capacidade de reagir a situações de tráfego significativamente aumentado. Com o aumento permanente de nossas tabelas de rastreamento de conexão para esta frota, devemos ser capazes de lidar com uma quantidade semelhante de carga sem grandes perdas de pacotes. Se você trabalha com frotas de grande escala, este pode ser um bom lembrete para que você verifique os limites da tabela de rastreamento de conexão e alarmes se você utiliza esta funcionalidade do netfilter. Além disso, temos o prazer em servir de exemplo para que vocês se lembrem de verificar a lógica de novas tentativas em seus clientes e, especialmente, como eles podem se comportar em conjunto após uma longa interrupção.

Para a Epic Games Store, implementamos uma correção que deve evitar a modificação de um objeto de aplicativo ativo e, como parte disso, descobrimos e corrigimos um bug em nossa geração de recursos.

Esperamos que este relatório de incidente tenha fornecido detalhes adicionais sobre o que aconteceu em 6 de abril. Esperamos que esses detalhes tenham lançado uma luz sobre as lições aprendidas por nós e nossos aprimoramentos, e ajudem outras pessoas a evitar problemas semelhantes.


Junte-se a nós!

Este post foi redigido por nossa equipe de Engenharia de Confiabilidade com muita ajuda de diversas outras equipes de engenharia incríveis aqui da Epic.

Você tem interesse nesses tipos de problema? Adora jogos e serviços de jogos? A Epic está sempre em busca de grandes talentos, e contratamos globalmente pessoas de toda gama de habilidades. Se quiser conferir nossas vagas em aberto, visite a Central de Carreiras da Epic Games.

Este post foi útil ou interessante? Mande sua opinião para public-incident-response@epicgames.com.