4.1 Introdução
Quando um sistema de machine learning é colocado em produção, o trabalho da equipe não termina. Na verdade, é nesse momento que começa uma fase igualmente importante: garantir que o sistema continue funcionando corretamente ao longo do tempo.
Retomando a figura que apresentamos no início deste livro, estamos falando do item 6. Ou seja, conseguimos colocar a aplicação em ambiente de produção, e agora queremos saber se é necessário alguma ação para retomar o ciclo DevOps.

Em ambientes reais, aplicações raramente operam isoladamente. Mesmo um sistema aparentemente simples envolve vários componentes trabalhando juntos. No exemplo construído nos capítulos anteriores, temos contêineres executando servidores web, aplicações em Flask, um servidor WSGI, um sistema de mensageria baseado em Kafka e processos consumidores que executam modelos de machine learning. Todos esses elementos precisam funcionar corretamente para que o serviço final esteja disponível para os usuários.
Se qualquer um desses componentes falhar, o sistema inteiro pode ser afetado. Um contêiner pode parar inesperadamente, um serviço pode deixar de responder, um servidor pode ficar sobrecarregado ou um processo pode consumir mais memória do que o esperado. Sem um mecanismo de monitoramento, esses problemas podem passar despercebidos por longos períodos, impactando diretamente a qualidade do serviço oferecido.
O monitoramento permite acompanhar continuamente o estado do sistema em produção. Em vez de depender de verificações manuais, ferramentas automatizadas coletam informações sobre os serviços em execução e analisam diferentes indicadores operacionais. Entre esses indicadores estão, por exemplo:
se os serviços estão ativos e respondendo corretamente;
quanto de CPU e memória os processos estão utilizando;
quantas requisições estão sendo recebidas por uma API;
quanto tempo os serviços levam para responder;
se há filas ou atrasos em sistemas de processamento de mensagens.
Essas informações permitem identificar rapidamente situações anormais, como quedas de serviço, sobrecarga de recursos ou degradação de desempenho. Quando algum problema é detectado, alertas podem ser gerados para que a equipe responsável intervenha antes que o impacto para os usuários se torne significativo.
No contexto de sistemas baseados em machine learning, o monitoramento é ainda mais importante porque os serviços frequentemente fazem parte de pipelines de dados e de aplicações distribuídas. Um modelo pode depender de dados recebidos por uma API, processados por um consumidor de mensagens ou armazenados em um banco de dados remoto. Qualquer falha nessa cadeia pode comprometer o funcionamento do sistema.
Por esse motivo, o monitoramento é considerado um dos pilares das práticas modernas de DevOps e MLOps. Ele permite não apenas detectar problemas, mas também compreender como o sistema se comporta em produção, identificar gargalos de desempenho e apoiar decisões sobre escalabilidade e melhorias de arquitetura.
Diversas ferramentas podem ser utilizadas para implementar esse tipo de monitoramento automatizado. Historicamente, uma das mais conhecidas é o Nagios, uma plataforma bastante tradicional para monitoramento de infraestrutura. O Nagios permite verificar se serviços estão ativos, se servidores estão respondendo e se determinados recursos do sistema ultrapassaram limites definidos. Ele possui uma versão comercial com interface gráfica e uma versão gratuita, chamada Nagios Core, configurada principalmente por arquivos de configuração. Apesar de ser uma solução robusta e amplamente utilizada por muitos anos, o Nagios foi concebido em um contexto anterior à popularização de arquiteturas baseadas em contêineres e microserviços.
Com a adoção crescente de ambientes baseados em contêineres, pipelines de dados e aplicações distribuídas, surgiram ferramentas mais modernas voltadas para o monitoramento de sistemas cloud-native. Um dos exemplos mais importantes é o Prometheus, um sistema de monitoramento e coleta de métricas amplamente utilizado em ambientes de produção. O Prometheus coleta métricas expostas por aplicações e serviços, armazena essas informações em um banco de dados de séries temporais e permite realizar consultas e análises sobre o comportamento do sistema ao longo do tempo.
Para facilitar a visualização dessas métricas, é comum utilizar ferramentas de dashboard como o Grafana. O Grafana permite construir painéis interativos que mostram, por exemplo, uso de CPU e memória, quantidade de requisições recebidas por um serviço, latência média das respostas e diversos outros indicadores operacionais importantes para o acompanhamento da saúde do sistema.
Além disso, existem componentes auxiliares chamados exporters, responsáveis por coletar métricas específicas de determinados serviços ou recursos do sistema. Por exemplo, o Node Exporter coleta métricas do sistema operacional, como uso de CPU, memória e disco do host. Já o cAdvisor, desenvolvido pelo Google, coleta métricas de contêineres Docker, como consumo de recursos e atividade de rede. No caso de sistemas de mensageria, como o Apache Kafka, também existem exporters que permitem monitorar filas, consumers, brokers e o fluxo de mensagens no sistema.
Nesse capítulo iremos explorar essas ferramentas modernas de monitoramento aplicadas a um ambiente baseado em contêineres. O objetivo será observar o comportamento dos serviços que colocamos em produção no capítulo anterior, verificando se eles estão ativos, como estão utilizando os recursos do sistema e se estão operando dentro de níveis aceitáveis de desempenho.
Faremos isso em cima do ambiente que construímos até agora. No Capítulo 3 fizemos o deploy de nossas aplicações. Para isso foram criados vários contêineres, e em várias configurações diferentes:
Na Seção 3.2, criamos um contêiner para executar uma tarefa offline, ou seja, um script que começa e termina assim que seu trabalho é concluído.
Na Seção 3.3, fizemos de duas maneiras diferentes:
Primeiro subimos um servidor web (nginx) e um servidor WSGI (gunicorn + Flask) em um mesmo contêiner.
Depois subimos dois contêineres: um para o nginx e outro para o servidor WSGI. Colocamos os dois na mesma rede Docker para que eles pudessem se comunicar entre si.
Na Seção 3.4, criamos três contêineres:
Um para o zookeeper, que controla os brokers do Kafka
Um broker, responsável por lidar com a fila de eventos
Um consumidor, que faz a tarefa de analisar o sentimentos das mensagens enviadas pelo usuário do chatbot.
Para reconstruir o mesmo ambiente sem precisar recorrer a cada seçao isoladamente, você pode fazer o download de todas as pastas desse link aqui. Você deve ter os seguintes diretórios (entre outros que não iremos utilizar):
http-api-classificacao-produtos-container-unico:Tarefa online para classificação de produtos via API HTTP (contêiner único)
http-api-classificacao-produtos-dois-containers:Tarefa online para classificação de produtos via API HTTP (dois contêineres)
analise-sentimentos:Consumidor Kafka que analisa sentimentos
chatbot:Produtor Kafka que produz conversas com um chatbot (ATENÇÃO! Você precisará inserir sua chave da OpenAI aqui para poder rodar este exemplo)
Estando no diretório anterior a todos estes, basta executar os seguintes comandos para construir todas as imagens necessárias:
Os seguintes comandos instanciam todos os contêineres. Não iremos executar o classificador offline, pois ele irá rodar e encerrar sozinho, portanto não faz sentido monitorar sua execução neste momento. Além disso, iremos executar o consumidor Kafka em modo desacoplado, apenas para não ocupar o terminal. Não veremos as mensagens sendo consumidas, mas não importa, pois já vimos isso rodando no capítulo anterior. E iremos colocar todos os contêineres na mesma rede, chamada minharede. Os comandos a seguir executam as ações descritas.
Se tudo rodar corretamente, devemos ter as seguintes imagens sendo exibidas após um comando docker image ls:

Exceto pela primeira tarefa, que é offline, todas essas imagens estarão rodando em contêineres, como mostra a saída do comando docker container ps:

Alguns desses têm portas abertas para o host, outros tem portas internas, disponíveis apenas para outros contêineres que rodam na mesma rede. A figura abaixo ilustra o ambiente de produção onde será incluído o Servidor de Monitoramento.

Animados para mais esse desafio? Então vamos dar início ao monitoramento desse ambiente.
Atualizado