Top fakapov Ciano

Top fakapov Ciano

Bom para todos! 

Meu nome é Nikita, sou o líder da equipe de engenharia Cian. Uma das minhas responsabilidades na empresa é reduzir a zero o número de incidentes relacionados à infraestrutura em produção.
O que será discutido a seguir nos trouxe muita dor, e o objetivo deste artigo é evitar que outras pessoas repitam nossos erros ou pelo menos minimizar seu impacto. 

Preâmbulo

Há muito tempo, quando Cian consistia em monólitos e ainda não havia indícios de microsserviços, medimos a disponibilidade de um recurso verificando de 3 a 5 páginas. 

Eles respondem - está tudo bem, se não responderem por muito tempo - alerta. Quanto tempo eles teriam que ficar fora do trabalho para que isso fosse considerado um incidente foi decidido pelas pessoas em reuniões. Uma equipe de engenheiros sempre esteve envolvida na investigação do incidente. Terminada a investigação, escreveram um post mortem - uma espécie de relatório por e-mail no formato: o que aconteceu, quanto tempo durou, o que fizemos no momento, o que faremos no futuro. 

As páginas principais do site ou como entendemos que chegamos ao fundo

 
Para entender de alguma forma a prioridade do erro, identificamos as páginas do site mais críticas para a funcionalidade do negócio. Usando-os, contamos o número de solicitações e tempos limite bem-sucedidos/malsucedidos. É assim que medimos o tempo de atividade. 

Digamos que descobrimos que existem várias seções superimportantes no site que são responsáveis ​​​​pelo serviço principal - busca e envio de anúncios. Se o número de solicitações com falha exceder 1%, este é um incidente crítico. Se dentro de 15 minutos durante o horário nobre a taxa de erro exceder 0,1%, isso também será considerado um incidente crítico. Esses critérios cobrem a maioria dos incidentes; o restante está além do escopo deste artigo.

Top fakapov Ciano

Principais melhores incidentes Cian

Portanto, definitivamente aprendemos a determinar o fato de um incidente ter acontecido. 

Agora cada incidente é descrito em detalhes e refletido no épico Jira. A propósito: para isso iniciamos um projeto separado, chamado FAIL - apenas épicos podem ser criados nele. 

Se você coletar todas as falhas dos últimos anos, os líderes são: 

  • incidentes relacionados ao mssql;
  • incidentes causados ​​por fatores externos;
  • erros de administração.

Vejamos com mais detalhes os erros dos administradores, bem como algumas outras falhas interessantes.

Quinto lugar - “Colocando ordem no DNS”

Foi uma terça-feira tempestuosa. Decidimos restaurar a ordem no cluster DNS. 

Eu queria transferir servidores DNS internos de bind para powerdns, alocando servidores completamente separados para isso, onde não há nada além de DNS. 

Colocamos um servidor DNS em cada local de nossos DCs e chegou o momento de mover zonas de bind para powerdns e mudar a infraestrutura para novos servidores. 

No meio da mudança, de todos os servidores especificados nos vínculos de cache local em todos os servidores, apenas um permaneceu, que estava no data center em São Petersburgo. Este DC foi inicialmente declarado não crítico para nós, mas de repente se tornou um ponto único de falha.
Foi durante esse período de realocação que o canal entre Moscou e São Petersburgo desabou. Na verdade, ficamos sem DNS por cinco minutos e voltamos quando o hoster resolveu o problema. 

Conclusões:

Se antes negligenciávamos os fatores externos durante a preparação para o trabalho, agora eles também estão incluídos na lista para o que nos preparamos. E agora nos esforçamos para garantir que todos os componentes sejam reservados para n-2 e, durante o trabalho, podemos diminuir esse nível para n-1.

  • Ao traçar um plano de ação, marque com antecedência os pontos onde o serviço pode falhar e pense antecipadamente em um cenário onde tudo fosse “de mal a pior”.
  • Distribua servidores DNS internos em diferentes geolocalizações/data centers/racks/switches/entradas.
  • Em cada servidor, instale um servidor DNS de cache local, que redireciona as solicitações para os servidores DNS principais e, caso não esteja disponível, responderá a partir do cache. 

Quarto lugar - “Colocando as coisas em ordem no Nginx”

Um belo dia, nossa equipe decidiu que “já estamos fartos disso” e o processo de refatoração das configurações do nginx começou. O objetivo principal é trazer as configurações para uma estrutura intuitiva. Anteriormente, tudo estava “estabelecido historicamente” e não carregava nenhuma lógica. Agora cada server_name foi movido para um arquivo com o mesmo nome e todas as configurações foram distribuídas em pastas. A propósito, a configuração contém 253949 linhas ou 7836520 caracteres e ocupa quase 7 megabytes. Nível superior de estrutura: 

Estrutura Nginx

├── access
│   ├── allow.list
...
│   └── whitelist.conf
├── geobase
│   ├── exclude.conf
...
│   └── geo_ip_to_region_id.conf
├── geodb
│   ├── GeoIP.dat
│   ├── GeoIP2-Country.mmdb
│   └── GeoLiteCity.dat
├── inc
│   ├── error.inc
...
│   └── proxy.inc
├── lists.d
│   ├── bot.conf
...
│   ├── dynamic
│   └── geo.conf
├── lua
│   ├── cookie.lua
│   ├── log
│   │   └── log.lua
│   ├── logics
│   │   ├── include.lua
│   │   ├── ...
│   │   └── utils.lua
│   └── prom
│       ├── stats.lua
│       └── stats_prometheus.lua
├── map.d
│   ├── access.conf
│   ├── .. 
│   └── zones.conf
├── nginx.conf
├── robots.txt
├── server.d
│   ├── cian.ru
│   │   ├── cian.ru.conf
│   │   ├── ...
│   │   └── my.cian.ru.conf
├── service.d
│   ├── ...
│   └── status.conf
└── upstream.d
    ├── cian-mcs.conf
    ├── ...
    └── wafserver.conf

Ficou muito melhor, mas no processo de renomeação e distribuição de configurações, algumas delas tinham a extensão errada e não foram incluídas na diretiva include *.conf. Como resultado, alguns hosts ficaram indisponíveis e retornaram 301 à página principal. Devido ao fato do código de resposta não ser 5xx/4xx, isso não foi percebido imediatamente, mas apenas pela manhã. Depois disso, começamos a escrever testes para verificar os componentes da infraestrutura.

Conclusões: 

  • Estruture suas configurações corretamente (não apenas nginx) e pense na estrutura no estágio inicial do projeto. Dessa forma você os tornará mais compreensíveis para a equipe, o que por sua vez reduzirá o TTM.
  • Escreva testes para alguns componentes da infraestrutura. Por exemplo: verificar se todas as chaves server_names fornecem o status correto + corpo da resposta. Bastará ter em mãos apenas alguns scripts que verifiquem as funções básicas do componente, para não lembrar freneticamente às 3 da manhã o que mais precisa ser verificado. 

Terceiro lugar - “De repente ficou sem espaço em Cassandra”

Os dados cresceram de forma constante e tudo estava bem até o momento em que o reparo de grandes casespaces começou a falhar no cluster Cassandra, porque a compactação não funcionou neles. 

Num dia de tempestade o cacho quase se transformou em uma abóbora, a saber:

  • restavam cerca de 20% do espaço total no cluster;
  • É impossível adicionar nós totalmente, pois a limpeza não ocorre após a adição de um nó devido à falta de espaço nas partições;
  • a produtividade cai gradualmente à medida que a compactação não funciona; 
  • O cluster está em modo de emergência.

Top fakapov Ciano

Saída - adicionamos mais 5 nós sem limpeza, após o que começamos a removê-los sistematicamente do cluster e a inseri-los novamente, como nós vazios que ficaram sem espaço. Foi gasto muito mais tempo do que gostaríamos. Havia risco de indisponibilidade parcial ou total do cluster. 

Conclusões:

  • Em todos os servidores cassandra, não mais que 60% do espaço em cada partição deve ser ocupado. 
  • Eles não devem ser carregados com mais de 50% da CPU.
  • Você não deve se esquecer do planejamento de capacidade e precisa pensá-lo para cada componente, com base em suas especificidades.
  • Quanto mais nós no cluster, melhor. Os servidores que contêm uma pequena quantidade de dados ficam sobrecarregados mais rapidamente e é mais fácil reviver esse cluster. 

Segundo lugar - “Dados desapareceram do armazenamento de valores-chave do cônsul”

Para descoberta de serviços, nós, como muitos, usamos cônsul. Mas também usamos seu valor-chave para o layout azul esverdeado do monólito. Ele armazena informações sobre upstreams ativos e inativos, que mudam de lugar durante a implantação. Para tanto, foi escrito um serviço de implantação que interagia com o KV. Em algum momento, os dados do KV desapareceram. Restaurado da memória, mas com vários erros. Como resultado, durante o upload, a carga nos upstreams foi distribuída de forma desigual e recebemos muitos erros 502 devido à sobrecarga dos back-ends na CPU. Como resultado, passamos do cônsul KV para o postgres, de onde não é mais tão fácil removê-los.  

Conclusões:

  • Serviços sem qualquer autorização não deverão conter dados críticos ao funcionamento do site. Por exemplo, se você não possui autorização no ES, seria melhor negar o acesso no nível da rede de qualquer lugar onde não seja necessário, deixar apenas os necessários e também definir action.destructive_requires_name: true.
  • Pratique seu mecanismo de backup e recuperação com antecedência. Por exemplo, crie um script com antecedência (por exemplo, em python) que possa fazer backup e restauração.

Primeiro lugar - “Capitão Não Óbvio” 

Em algum momento, notamos uma distribuição desigual de carga nos upstreams do nginx nos casos em que havia mais de 10 servidores no back-end. Devido ao fato de que o round-robin enviava solicitações do primeiro ao último upstream em ordem, e cada recarga do nginx era reiniciada, os primeiros upstreams sempre recebiam mais solicitações do que os demais. Como resultado, eles funcionavam mais lentamente e todo o site sofria. Isso se tornou cada vez mais perceptível à medida que a quantidade de tráfego aumentava. Simplesmente atualizar o nginx para habilitar random não funcionou - precisamos refazer um monte de código lua que não decolou na versão 1 (naquele momento). Tivemos que corrigir nosso nginx 1.15, introduzindo suporte aleatório nele. Isso resolveu o problema. Este bug vence a categoria “Capitão Não-Obviedade”.

Conclusões:

Foi muito interessante e emocionante explorar esse bug). 

  • Organize seu monitoramento para que ele o ajude a encontrar essas flutuações rapidamente. Por exemplo, você pode usar ELK para monitorar rps em cada backend de cada upstream, monitorar seu tempo de resposta do ponto de vista do nginx. Nesse caso, isso nos ajudou a identificar o problema. 

Como resultado, a maioria das falhas poderia ter sido evitada com uma abordagem mais escrupulosa do que você estava fazendo. Devemos sempre nos lembrar da lei de Murphy: Qualquer coisa que possa dar errado, dará errado, e construir componentes baseados nele. 

Fonte: habr.com

Adicionar um comentário