Monitoramento como serviço: um sistema modular para arquitetura de microsserviços

Hoje, além do código monolítico, nosso projeto inclui dezenas de microsserviços. Cada um deles precisa ser monitorado. Fazer isso em tal escala usando engenheiros de DevOps é problemático. Desenvolvemos um sistema de monitoramento que funciona como um serviço para desenvolvedores. Eles podem gravar métricas de forma independente no sistema de monitoramento, usá-las, criar painéis com base nelas e anexar alertas a elas que serão acionadas quando os valores limite forem atingidos. Para engenheiros de DevOps, apenas infraestrutura e documentação.

Este post é uma transcrição do meu discurso com nosso seção no RIT++. Muitas pessoas nos pediram para fazer versões em texto dos relatórios a partir daí. Se você esteve na conferência ou assistiu ao vídeo, não encontrará nada de novo. E todos os outros - bem-vindos ao gato. Vou lhe contar como chegamos a esse sistema, como ele funciona e como planejamos atualizá-lo.

Monitoramento como serviço: um sistema modular para arquitetura de microsserviços

O passado: esquemas e planos

Como chegamos ao sistema de monitoramento atual? Para responder a esta pergunta, você precisa ir até 2015. Era assim que parecia então:

Monitoramento como serviço: um sistema modular para arquitetura de microsserviços

Tínhamos cerca de 24 nós responsáveis ​​pelo monitoramento. Existe um pacote completo de diferentes coroas, scripts, daemons que de alguma forma monitoram algo, enviam mensagens e executam funções. Pensávamos que quanto mais avançássemos, menos viável seria esse sistema. Não adianta desenvolvê-lo: é muito complicado.
Decidimos escolher os elementos de monitorização que iremos manter e desenvolver e aqueles que iremos abandonar. Eram 19. Restaram apenas grafites, agregadores e Grafana como dashboard. Mas como será o novo sistema? Assim:

Monitoramento como serviço: um sistema modular para arquitetura de microsserviços

Temos um armazenamento de métricas: são grafites, que serão baseados em drives SSD rápidos, são certos agregadores de métricas. Próximo - Grafana para exibição de dashboards e Moira para alertas. Também queríamos desenvolver um sistema de busca de anomalias.

Padrão: Monitoramento 2.0

Assim eram os planos em 2015. Mas tivemos que preparar não só a infraestrutura e o serviço em si, mas também a documentação para o mesmo. Desenvolvemos um padrão corporativo para nós mesmos, que chamamos de monitoramento 2.0. Quais eram os requisitos do sistema?

  • disponibilidade constante;
  • intervalo de armazenamento de métricas = 10 segundos;
  • armazenamento estruturado de métricas e dashboards;
  • SLA > 99,99%
  • coleta de métricas de eventos via UDP (!).

Precisávamos do UDP porque temos um grande fluxo de tráfego e eventos que geram métricas. Se você escrever todos eles em grafite de uma vez, o armazenamento entrará em colapso. Também escolhemos prefixos de primeiro nível para todas as métricas.

Monitoramento como serviço: um sistema modular para arquitetura de microsserviços

Cada um dos prefixos possui alguma propriedade. Existem métricas para servidores, redes, contêineres, recursos, aplicativos e assim por diante. Foi implementada uma filtragem clara, rigorosa e digitada, onde aceitamos métricas de primeiro nível e simplesmente descartamos o resto. Foi assim que planejamos esse sistema em 2015. O que há no presente?

Presente: diagrama de interação dos componentes de monitoramento

Em primeiro lugar, monitoramos aplicações: nosso código PHP, aplicações e microsserviços – em suma, tudo o que nossos desenvolvedores escrevem. Todas as aplicações enviam métricas via UDP para o agregador Brubeck (statsd, reescrito em C). Acabou sendo o mais rápido em testes sintéticos. E envia as métricas já agregadas para o Graphite via TCP.

Possui um tipo de métrica chamada temporizadores. Isso é uma coisa muito conveniente. Por exemplo, para cada conexão do usuário ao serviço, você envia uma métrica com tempo de resposta para o Brubeck. Chegou um milhão de respostas, mas o agregador retornou apenas 10 métricas. Você tem o número de pessoas que compareceram, o tempo máximo, mínimo e médio de resposta, a mediana e 4 percentis. Depois os dados são transferidos para o Graphite e vemos tudo ao vivo.

Também temos agregação de métricas de hardware, software, métricas de sistema e nosso antigo sistema de monitoramento Munin (funcionou para nós até 2015). Coletamos tudo isso através do daemon C CollectD (ele possui vários plug-ins diferentes integrados, pode pesquisar todos os recursos do sistema host no qual está instalado, basta especificar na configuração onde gravar os dados) e escreva os dados no Graphite por meio dele. Ele também suporta plug-ins python e scripts de shell, para que você possa escrever suas próprias soluções personalizadas: CollectD coletará esses dados de um host local ou remoto (assumindo Curl) e os enviará para o Graphite.

Em seguida, enviamos todas as métricas que coletamos para o Carbon-c-relay. Esta é a solução Carbon Relay da Graphite, modificada em C. Este é um roteador que coleta todas as métricas que enviamos de nossos agregadores e as encaminha para os nós. Ainda na fase de roteamento, verifica a validade das métricas. Em primeiro lugar, devem corresponder ao esquema de prefixos que mostrei anteriormente e, em segundo lugar, são válidos para o grafite. Caso contrário, eles cairão.

O Carbon-c-relay então envia as métricas para o cluster Graphite. Usamos Carbon-cache, reescrito em Go, como principal armazenamento de métricas. O Go-carbon, devido ao seu multithreading, supera em muito o Carbon-cache. Ele recebe dados e os grava em discos usando o pacote Whisper (padrão, escrito em python). Para ler os dados de nossos armazenamentos, usamos a API Graphite. É muito mais rápido que o Graphite WEB padrão. O que acontece com os dados a seguir?

Eles vão para Grafana. Utilizamos nossos clusters de grafite como principal fonte de dados, além de termos o Grafana como interface web para exibição de métricas e construção de dashboards. Para cada um de seus serviços, os desenvolvedores criam seu próprio painel. Em seguida, eles constroem gráficos com base neles, que exibem as métricas que eles escrevem em seus aplicativos. Além do Grafana, também temos o SLAM. Este é um demônio python que calcula o SLA com base em dados de grafite. Como já disse, temos várias dezenas de microsserviços, cada um com seus próprios requisitos. Usando o SLAM, vamos até a documentação e comparamos com o que está no Graphite e comparamos até que ponto os requisitos correspondem à disponibilidade dos nossos serviços.

Vamos mais longe: alertar. É organizado através de um sistema forte - Moira. É independente porque possui seu próprio grafite sob o capô. Desenvolvido pela galera da SKB "Kontur", escrito em python e Go, totalmente open source. Moira recebe o mesmo fluxo que vai para o grafite. Se por algum motivo seu armazenamento acabar, seu alerta ainda funcionará.

Implantamos o Moira no Kubernetes; ele usa um cluster de servidores Redis como banco de dados principal. O resultado foi um sistema tolerante a falhas. Ele compara o fluxo de métricas com a lista de gatilhos: se não houver menções nele, a métrica será descartada. Portanto, é capaz de digerir gigabytes de métricas por minuto.

Também anexamos a ele um LDAP corporativo, com a ajuda do qual cada usuário do sistema corporativo pode criar notificações para si mesmo com base em gatilhos existentes (ou recém-criados). Como Moira contém Grafite, ele suporta todos os seus recursos. Então você primeiro pega a linha e a copia no Grafana. Veja como os dados são exibidos nos gráficos. E então você pega a mesma linha e copia para Moira. Você pendura com limites e recebe um alerta na saída. Para fazer tudo isso, você não precisa de nenhum conhecimento específico. Moira pode alertar via SMS, email, Jira, Slack... Também suporta a execução de scripts personalizados. Quando um gatilho acontece com ela e ela está inscrita em um script ou binário personalizado, ela o executa e envia JSON para stdin para esse binário. Conseqüentemente, seu programa deve analisá-lo. O que você fará com este JSON depende de você. Se quiser, mande para o Telegram, se quiser, abra tarefas no Jira, faça o que for.

Também utilizamos nosso próprio desenvolvimento para alertas - Imagotag. Adaptamos o painel, normalmente utilizado em etiquetas eletrônicas de preços nas lojas, para atender às nossas necessidades. Trouxemos gatilhos de Moira para isso. Indica em que estado eles se encontram e quando ocorreram. Alguns dos desenvolvedores abandonaram as notificações no Slack e e-mail em favor deste painel.

Monitoramento como serviço: um sistema modular para arquitetura de microsserviços

Pois bem, como somos uma empresa progressista, também monitoramos o Kubernetes neste sistema. Incluímos no sistema usando o Heapster, que instalamos no cluster, ele coleta os dados e envia para o Graphite. Como resultado, o diagrama fica assim:

Monitoramento como serviço: um sistema modular para arquitetura de microsserviços

Componentes de monitoramento

Aqui está uma lista de links para os componentes que usamos para esta tarefa. Todos eles são de código aberto.

Grafite:

Relé carbono-c:

github.com/grobian/carbon-c-relay

Brubeque:

github.com/github/brubeck

Coletado:

collectd.org

Moira:

github.com/moira-alert

Grafana:

grafana.com

Heapster:

github.com/kubernetes/heapster

Estatísticas

E aqui estão alguns números sobre como o sistema funciona para nós.

Agregador (brubeck)

Número de métricas: aproximadamente 300/seg
Intervalo para envio de métricas para Graphite: 30 seg.
Uso de recursos do servidor: ~ 6% CPU (estamos falando de servidores completos); ~ 1Gb de RAM; ~3Mbps LAN

Grafite (go-carbono)

Número de métricas: ~ 1/min
Intervalo de atualização de métricas: 30 segundos
Esquema de armazenamento de métricas: 30seg 35d, 5min 90d, 10min 365d (dá uma compreensão do que acontece com o serviço durante um longo período de tempo)
Uso de recursos do servidor: ~10% CPU; ~ 20 GB de RAM; ~30 Mbps LAN

Flexibilidade

Nós da Avito valorizamos muito a flexibilidade em nosso serviço de monitoramento. Por que ele realmente ficou assim? Em primeiro lugar, os seus componentes são intercambiáveis: tanto os próprios componentes como as suas versões. Em segundo lugar, suportabilidade. Como todo o projeto é de código aberto, você mesmo pode editar o código, fazer alterações e implementar funções que não estão disponíveis imediatamente. São usadas pilhas bastante comuns, principalmente Go e Python, então isso é feito de forma bastante simples.

Aqui está um exemplo de um problema real. Uma métrica em Graphite é um arquivo. Tem um nome. Nome do arquivo = nome da métrica. E há uma maneira de chegar lá. Os nomes de arquivos no Linux são limitados a 255 caracteres. E temos (como “clientes internos”) pessoal do departamento de banco de dados. Eles nos dizem: “Queremos monitorar nossas consultas SQL. E não têm 255 caracteres, mas 8 MB cada. Queremos exibi-los no Grafana, ver os parâmetros dessa solicitação e, melhor ainda, queremos ver o topo dessas solicitações. Será ótimo se for exibido em tempo real. Seria muito legal colocá-los em alerta.”

Monitoramento como serviço: um sistema modular para arquitetura de microsserviços
O exemplo de consulta SQL é tomado como exemplo de site postgrespro.ru

Montamos um servidor Redis e utilizamos nossos plugins Collectd, que vão para o Postgres e pegam todos os dados de lá, enviando métricas para o Graphite. Mas substituímos o nome da métrica por hashes. Enviamos simultaneamente o mesmo hash para o Redis como uma chave e toda a consulta SQL como um valor. Tudo o que precisamos fazer é garantir que o Grafana possa ir ao Redis e obter essas informações. Estamos abrindo a API Graphite porque... esta é a interface principal para a interação de todos os componentes de monitoramento com o grafite, e lá inserimos uma nova função chamada aliasByHash() - do Grafana obtemos o nome da métrica e a usamos em uma solicitação ao Redis como chave, em resposta obtemos o valor da chave, que é a nossa “consulta SQL” " Assim, exibimos no Grafana a exibição de uma consulta SQL, que em teoria era impossível de exibir ali, junto com estatísticas sobre ela (chamadas, linhas, total_time, ...).

Resultados de

Disponibilidade. Nosso serviço de monitoramento está disponível 24 horas por dia, 7 dias por semana, a partir de qualquer aplicativo e qualquer código. Se você tiver acesso a instalações de armazenamento, poderá gravar dados no serviço. A linguagem não é importante, as decisões não são importantes. Você só precisa saber abrir um soquete, colocar uma métrica ali e fechar o soquete.

Confiabilidade. Todos os componentes são tolerantes a falhas e lidam bem com nossas cargas.

Limiar de entrada baixo. Para utilizar este sistema, você não precisa aprender linguagens de programação e consultas no Grafana. Basta abrir sua aplicação, inserir nela um socket que irá enviar métricas para o Graphite, fechá-la, abrir o Grafana, criar lá dashboards e observar o comportamento de suas métricas, recebendo notificações através do Moira.

Independência. Você pode fazer tudo isso sozinho, sem a ajuda de engenheiros de DevOps. E isso é uma vantagem, porque você pode acompanhar seu projeto agora mesmo, não precisa pedir para ninguém – seja para começar a trabalhar ou para fazer alterações.

Para que estamos nos esforçando?

Tudo o que está listado abaixo não são apenas pensamentos abstratos, mas algo para o qual pelo menos os primeiros passos foram dados.

  1. Detector de anomalias. Queremos criar um serviço que irá até nossos armazenamentos de grafite e verificará cada métrica usando vários algoritmos. Já existem algoritmos que queremos visualizar, existem dados, sabemos como trabalhar com eles.
  2. Metadados. Temos muitos serviços, eles mudam com o tempo, assim como as pessoas que trabalham com eles. Manter constantemente a documentação manualmente não é uma opção. É por isso que agora estamos incorporando metadados em nossos microsserviços. Indica quem o desenvolveu, os idiomas com os quais interage, requisitos de SLA, para onde e para quem as notificações devem ser enviadas. Ao implementar um serviço, todos os dados da entidade são criados de forma independente. Como resultado, você obtém dois links - um para gatilhos e outro para painéis no Grafana.
  3. Monitoramento em todas as residências. Acreditamos que todos os desenvolvedores deveriam usar tal sistema. Nesse caso, você sempre entende onde está o seu tráfego, o que acontece com ele, onde ele cai, onde estão seus pontos fracos. Se, por exemplo, algo acontecer e travar seu serviço, você saberá disso não durante uma ligação do gerente, mas por meio de um alerta, e poderá abrir imediatamente os logs mais recentes e ver o que aconteceu lá.
  4. Alta performance. Nosso projeto está em constante crescimento e hoje processa cerca de 2 de valores métricos por minuto. Há um ano, esse número era de 000. E o crescimento continua, o que significa que depois de algum tempo o Graphite (sussurro) começará a carregar fortemente o subsistema do disco. Como já disse, este sistema de monitoramento é bastante universal devido à intercambialidade dos componentes. Alguém mantém e expande constantemente sua infraestrutura especificamente para Grafite, mas decidimos seguir um caminho diferente: usar clickhouse como um repositório para nossas métricas. Esta transição está quase completa, e muito em breve contarei com mais detalhes como isso foi feito: quais as dificuldades que surgiram e como foram superadas, como foi o processo de migração, descreverei os componentes escolhidos como vinculativos e suas configurações.

Obrigado pela sua atenção! Tire suas dúvidas sobre o tema, tentarei responder aqui ou nos próximos posts. Talvez alguém tenha experiência em construir um sistema de monitoramento semelhante ou mudar para Clickhouse em uma situação semelhante - compartilhe nos comentários.

Fonte: habr.com

Adicionar um comentário