Análise pós-incidente do caso da Kagi da semana passada
(status.kagi.com)Resolução do problema de instabilidade do serviço Kagi.com
- Investigando - Após o deploy, surgiu um problema e a equipe está trabalhando na correção. (12 de janeiro, 16:45 UTC)
- Monitorando - A alteração de configuração considerada a provável causa do problema foi revertida, e o retorno do serviço ao normal está sendo monitorado continuamente. (12 de janeiro, 18:30 UTC)
- Atualização - Para restaurar totalmente a estabilidade, o tráfego será interrompido temporariamente e os usuários serão redirecionados para esta página. Mais detalhes serão fornecidos conforme a situação evoluir enquanto o serviço for restaurado de forma controlada. (12 de janeiro, 20:26 UTC)
- Monitorando - O tráfego foi restaurado, e o retorno completo do serviço ao normal continua sendo monitorado. (12 de janeiro, 21:14 UTC)
- Resolvido - Todos os serviços estão operando normalmente. Agradecemos aos usuários pela paciência enquanto o problema era resolvido.
Análise pós-incidente
- Zac, líder técnico da Kagi, compartilhou uma análise detalhada do incidente de indisponibilidade do serviço da semana passada.
- Em resposta a esse incidente, o engenheiro sênior Seth e o engenheiro de DevOps Luan trabalharam juntos.
- Houve agentes que abusaram do serviço e exploraram gargalos da infraestrutura, e medidas imediatas de mitigação foram tomadas, enquanto melhorias em várias áreas do código e da comunicação estão em andamento.
Cronologia do incidente
- Por volta das 17h30 de 12 de janeiro, foi identificado um problema de infraestrutura por meio do monitoramento interno e de relatos de usuários.
- A natureza do problema causava carregamento lento ou timeout de páginas para usuários em várias regiões.
- A resolução levou um tempo considerável, e são explicados o contexto, o andamento e os próximos passos.
Processo técnico de resolução
- No início, o problema aconteceu por coincidência ao mesmo tempo em que os recursos extras de RAM da VM eram ampliados.
- O monitoramento reportou alta latência e problemas no pool de conexões com o banco de dados da aplicação.
- O pool de conexões chegou à saturação, o que significava que o número total de conexões excedia o limite máximo configurado.
- Enquanto a saúde interna do banco de dados e o desempenho das queries eram avaliados, algumas instâncias foram substituídas para testar o efeito de reduzir o congestionamento.
- Como a substituição de parte das instâncias pareceu ajudar, o tráfego de usuários foi pausado para redefinir completamente todos os pools de conexão de uma só vez.
- Ao analisar o estado do banco de dados, ficou claro que a alta contenção em linhas da tabela de usuários era a causa raiz.
- Essa contenção aumentou drasticamente a latência de escrita, gerando backpressure no pool de conexões da aplicação e, por fim, esgotando todas as conexões disponíveis.
- Até então, a Kagi vinha usando o banco de dados single-core mais barato disponível no GCP, o que carregava o risco de paralisar facilmente o banco.
- Após identificar os agentes maliciosos, foram encontradas contas criadas em menos de 24 horas e uma única conta de usuário que realizou mais de 60.000 buscas em pouco tempo.
- A funcionalidade de busca dessa conta foi removida, e foi publicado um hotfix para desativar a escrita específica que causava o problema.
- Até a meia-noite, o problema foi totalmente resolvido, e continua havendo monitoramento atento de sinais de retorno desses agentes.
Próximas ações
- Muito foi aprendido com esse incidente, e já estão em andamento planos imediatos para fortalecer ainda mais o sistema e melhorar o processo de comunicação em casos de incidentes.
- Primeiro, foi reconhecido que as atualizações da página de status não foram rápidas o suficiente.
- Haverá migração para uma plataforma de página de status que permita expor com mais facilidade o monitoramento interno automatizado aos usuários, para que eles possam acompanhar em tempo real a saúde da plataforma.
- Estão sendo executadas ações para mitigar diretamente as queries problemáticas e testes de carga para verificar se existem outras falhas semelhantes.
- Também será instalado monitoramento adicional para apontar mais rapidamente para os locais corretos na infraestrutura, evitando desperdício de tempo seguindo sinais incorretos como aconteceu desta vez.
- O sistema de detecção desse tipo de abuso está sendo reforçado e, como isso gera impacto não apenas em desempenho, mas também diretamente em custos, é necessário definir limites automatizados para sua aplicação.
- Os novos limites já estavam em vigor no momento desta publicação, e seu impacto será monitorado, com ajustes contínuos conforme necessário.
- Caso alguém acredite que o acesso à Kagi foi bloqueado por engano, é solicitado que entre em contato com support@kagi.com.
Opinião do GN⁺
- A Kagi enfrentou um problema de latência de escrita causado por contenção em linhas da tabela de usuários, o que gerou backpressure no pool de conexões da aplicação e levou à indisponibilidade do serviço.
- Esse problema foi resultado do risco envolvido no uso, pela Kagi, do banco de dados single-core mais barato do GCP.
- Com esse incidente, a equipe da Kagi demonstrou esforço para aumentar a estabilidade e a transparência do serviço ao fortalecer o sistema, melhorar a comunicação com os usuários e definir limites automatizados para evitar abusos. Esses esforços refletem o compromisso da Kagi em oferecer um serviço mais confiável aos usuários.
1 comentários
Opiniões no Hacker News
No começo, descobriu-se que foi pura coincidência a atualização de infraestrutura para adicionar RAM à VM ter acontecido exatamente no mesmo horário da falha, mas essas “coincidências” acontecem com muita frequência e fazem você duvidar da própria existência delas enquanto investiga o problema
Se você entra em pânico nesse estado, acaba empurrando um hotfix que quebra outra coisa, e daí em diante fica muito mais doloroso
A Lei de Murphy é cruel com administradores de sistemas e desenvolvedores
Tenho uma frase de que gosto: “se você não sabe por que/como consertou, talvez na verdade não tenha consertado”
“Felizmente” não tinha relação com a minha consulta, mas quando duas coincidências dessas se sobrepõem, dá muito medo
Depois de passar por isso muitas vezes, criei o hábito de questionar mais pressupostos e de não marcar como dados confirmados aquilo que ainda não foi verificado
Não eliminei completamente vieses e conclusões precipitadas, mas ajudou, e manter a mente aberta é algo bem difícil
Uma habilidade importante para um engenheiro é conseguir raciocinar criticamente sobre mudanças feitas durante a resposta a incidentes, depurá-las e “testá-las de forma isolada”. É muito mais difícil do que parece e, em geral, se aproxima de uma competência de nível sênior
Fui um dos usuários que reportou esse problema no Discord. Gosto do Kagi, mas foi bem decepcionante a página de status indicar que tudo estava normal
Foi preocupante parecer que a página de status não era prioridade mesmo durante uma falha que afetava usuários reais, e espero que ela seja atualizada corretamente no futuro
Serviços dos quais eu dependia bastante no passado, como o GitHub, atualizavam a página de status imediatamente, então eu ficava tranquilo sabendo que o problema não era no meu dispositivo, mas algo reconhecido do lado do serviço
Desta vez eu precisava encontrar um mercado próximo que estivesse aberto antes de nevar naquele dia, e acabei tendo que ir para o Google, o que foi um pouco decepcionante
Ainda assim, em 99,9% do tempo em que usei o Kagi ele foi melhor que o Google, então vou continuar usando, e espero que, como dito na análise pós-incidente, eles movam o código da página de status para outro serviço/plataforma
No fim, colocar algo na página de status vira uma conversa em si, e essa conversa consome tempo e atenção dos engenheiros, atrasando a resolução do incidente na mesma medida
É preciso equilibrar comunicação e recuperação de fato, e a resposta certa nem sempre é clara
Se houver gente suficiente, um Technical Incident Manager pode assumir a comunicação e dá para alocar mais engenheiros também na parte de comunicação, mas isso nem sempre é possível. Alguns sistemas são especializados, pouco documentados e também pouco instrumentados
Pessoalmente, prefiro publicar um aviso grande e vago do tipo “investigando um possível problema” assim que aparecerem sinais de problema, e depois preencher os detalhes ou retirar o aviso. Mas as empresas em que trabalhei não gostavam dessa ideia
Naquele momento fiquei muito atraído pelo Kagi e passei a usar alguns tipos de consulta alternando entre eles, mas, à medida que LLMs, Perplexity e o Google passaram a responder muitas coisas diretamente na página de busca, não sobraram tantas consultas para o Kagi
Seria bem interessante se o Kagi de alguma forma se juntasse ao Perplexity
Muitas vezes ela nem chega a indicar até o fim
Essa falha é tão familiar que chega a ser surpreendente
Pessoalmente, já lidei mais vezes do que gostaria de admitir com exatamente esse tipo de falha e, assim como a equipe do Kagi, caí na toca do coelho do estado do pool de conexões do banco de dados, tentei as mesmas mitigações, como jogar novas instâncias no problema ou acreditar que “resetar” o tráfego resolveria, mas foi tudo em vão
Nesse tipo de falha, também não ajuda o fato de os indicadores comuns de saturação do banco de dados, como uso de CPU, IOPS etc., quase não se mexerem. A latência das consultas parece alta, mas você pensa “tem folga de CPU e IOPS...” e acaba deixando passar, como sempre, que há contenção de locks escondida
Pela minha experiência, 98% dos sinais estranhos no pool de conexões do DB vêm de anomalias no próprio DB. Não sei qual banco de dados relacional o Kagi usa, mas recomendo fortemente colocar em gráfico a latência global de I/O do DB (segundos/segundo), o tempo global de aquisição de locks (segundos/segundo) e o tempo de execução por consulta normalizada (segundos/segundo)
Somando a isso um gráfico de uso de CPU, você tem um dashboard capaz de identificar rapidamente a maioria dos problemas de desempenho em larga escala
Separadamente, é um pouco surpreendente que consultas de busca provoquem escritas em banco de dados relacional. Eu imaginava que o banco relacional fosse usado apenas para coisas como configurações de usuário e gerenciamento de login
Se o Kagi está fazendo agregação de uso, por exemplo incremento de contadores, em um banco de dados relacional, esse é um modo de falha muito típico que aparece quando a escala aumenta
Pode haver escritas indiretas por causa de buscas, como quando alguém bloqueia resultados de busca, e obviamente também deve haver histórico de visitas ou analytics
Mesmo assim, não está claro o que poderia causar contenção de locks de escrita a cada busca
É algo que toda startup acaba enfrentando em algum momento. Já passei por isso e é realmente doloroso
Às vezes falta tempo ou recursos para criar a capacidade de evitar esse tipo de problema; outras vezes você nem imagina que um problema específico possa de fato acontecer e acaba sendo pego de surpresa
Transparência é importante, assim como aprendizado, mas às vezes compensação também é importante. A Kagi deveria considerar oferecer créditos de busca pelo tempo em que o serviço não pôde ser usado
Especialmente porque eles próprios reconheceram que faltou resposta em tempo real
Uma indisponibilidade em um serviço pago não é igual à de um serviço em que “o usuário é o produto”
Isso mostra muita coisa sobre o nível de observabilidade dos sistemas internos
É fácil dizer que deveriam ter percebido mais cedo, mas, com dashboards adequados no Datadog e consultas no Splunk, isso teria ficado claro muito mais rápido
Espero que usem esse episódio como oportunidade de aprendizado e invistam em monitoramento melhor
Isso foi 100% uma experiência de aprendizado, mas posso dar um pouco mais de contexto sobre observabilidade
A Kagi é uma equipe pequena, e as pessoas capazes de responder a eventos como esse são, na prática, 3, espalhadas por 3 fusos horários. Para mim e para o desenvolvedor principal, este é o começo da carreira na web, não somos veteranos do Vale do Silício que já passaram por tudo isso
É claro que temos muito a aprender, mas, tendo construído a Kagi do zero, tenho orgulho do caminho que percorremos até aqui e da direção para onde estamos indo
Começamos a tratar observabilidade com mais seriedade há cerca de 6 meses. Hoje temos muitos dashboards, além de alertas que entram direto no canal de chat da empresa e chamam as pessoas relevantes
Como principal responsável pelo DB, o Query Insights do GCP ajuda bastante. Durante a indisponibilidade, o monitoramento disparou e o Query Insights também mostrou a consulta “culpada”, mas, mesmo com todo o monitoramento do mundo, pode faltar experiência para interpretar a causa raiz ou a mitigação mais eficiente
Em outras palavras, ainda nos falta a sabedoria para não sermos gaslighted pelo que nossos próprios sistemas estão mostrando, se não tivermos cuidado. Em retrospecto, posso dizer que o GCP Query Insights estava 100% correto e que não era um bug no espaço da aplicação
Graças ao crescimento, agora conseguimos expandir bastante a equipe; já recebemos consultoria de SRE antes e pretendemos continuar melhorando com mais apoio em tempo integral ou parcial
Quer dizer que um único usuário rodou um scraper e derrubou o serviço por 7 horas? Sei que é fácil dizer de fora “vocês deveriam ter previsto”, mas acho estranho que, nos testes, ninguém tenha perguntado “o que acontece se ocorrerem buscas em volume enorme?”
https://news.ycombinator.com/item?id=39019936
Resumindo, somos uma equipe jovem, com pouquíssimas pessoas-chave, e todos acumulam várias funções. Ainda não temos uma equipe dedicada de SRE
Sobre “o que acontece se ocorrerem buscas em volume enorme?”, se você olhar https://kagi.com/stats, verá que já temos “muitas buscas”, chegando perto de 400 mil por dia. No dia a dia, o sistema opera com bastante capacidade de folga e temos algumas medidas de autoescalonamento
O problema estava nos detalhes de alguns usuários explorando um caso patológico. Por falta de experiência, não sabíamos que tipo de tráfego natural ou patológico poderíamos ter previsto e simulado com antecedência
Simular carga de 20 mil usuários pesquisando simultaneamente soa como um experimento inicial razoável, e fizemos algo parecido. Mas, olhando para esta indisponibilidade, ainda assim isso não teria detectado este problema
Até agora, cerca de 10 pessoas rodaram scanners de segurança no serviço em produção, e o tráfego gerado nessas ocasiões foi maior do que o desta indisponibilidade
Equilibrar esse tipo de desenvolvimento enquanto também precisamos criar funcionalidades é muito difícil, e sem dúvida deveríamos ter feito mais. Como mencionei em outro texto, pretendemos expandir a equipe em breve para não ficarmos tão espalhados nesses esforços
Em retrospecto, há muita coisa que dá para dizer, mas espero ter transmitido com mais transparência como chegamos até aqui
Especialmente se foi a primeira vez que alguém os atingiu dessa forma
Para comparar, o sistema com que trabalho não está na escala de uma FAANG, mas é certamente maior que a Kagi em taxa de requisições. A Kagi também vai aprender rápido e, nesse meio-tempo, se problemas assim voltarem a acontecer, até acho que isso é aceitável em certa medida. Também é um sinal de que estão se movendo na direção certa
Como usuário pagante da Kagi, depois de passar pelo downtime percebi o quanto eu dava como garantida a confiabilidade do Google
Nos últimos 20 anos, com uma exceção talvez, o Google nunca ficou fora do ar para mim. Perder acesso a um mecanismo de busca é bem crítico
Eu gosto muito da Kagi e pago por ela, mas enfrentar downtime no segundo mês de uso foi bem desconfortável. Gosto de postmortems, mas prefiro não ter motivo para lê-los
Ainda assim, espero que essa experiência torne a Kagi um serviço mais resiliente e confiável
Um mecanismo de busca não é um serviço com lock-in como um provedor de e-mail ou um ISP
Eu claramente dependia de a Kagi ser rápida e funcionar bem em qualquer lugar
Isso me lembra de quando estávamos rodando uma prova de conceito de uma nova ferramenta de networking em um cliente. Cerca de 2 minutos depois de executá-la, toda a rede do cliente caiu
Estávamos em uma área de sandbox isolada, então não havia como nosso produto causar uma falha na rede inteira, mas, na minha cabeça, eu pensava: “não pode ser isso, né... né?!?!”
“Mais tarde, conseguimos contato com a conta que havia sido bloqueada, e ela alegou que usou a conta para fazer scraping automático dos nossos resultados, algo que não é permitido pelos termos de uso.”
É preciso impor limites de QPS a todas as possíveis entradas RPC/API/HTTP, especialmente às requisições públicas
Havia um recurso de busca com autocompletar e, para dar suporte a usuários que digitavam rapidamente, removi de propósito o limite de velocidade daquele endpoint
Um dia, por volta das 6h da manhã, alguém no Tennessee chegou ao trabalho e deixou a carteira em cima do teclado; a carteira ficou pressionando uma tecla e começou a chamar a API a cada entrada de tecla
Como era de se esperar, depois de uns 15 minutos o DB ficou muito instável, e a latência do DB aumentou tanto que um dos servidores web caiu. As falhas em cascata continuaram e derrubaram todo o cluster de produção
Nem é preciso dizer que naquele dia o limite de velocidade foi adicionado de volta