Monitoramento de Microservices com Prometheus e Grafana

Navendu Pottekkat

Navendu Pottekkat

June 8, 2023

Ecosystem

O monitoramento contínuo é crucial para tornar os sistemas de microsserviços robustos. Sem o monitoramento adequado, os microsserviços podem rapidamente ficar sobrecarregados, levando a erros e perda de desempenho.

Através do monitoramento contínuo, os desenvolvedores podem detectar problemas com seus serviços assim que eles surgem e tomar medidas para evitar danos significativos. Ele também fornece insights sobre como seus serviços estão performando, permitindo que você tome decisões informadas.

Este artigo apresentará como você pode configurar o monitoramento em sua aplicação de microsserviços usando duas das ferramentas mais populares nesse espaço, Prometheus e Grafana.

O código-fonte e o arquivo Docker Compose para este tutorial estão disponíveis em pottekkat/monitoring-101.

Noções Básicas do Prometheus

O Prometheus é uma ferramenta de monitoramento e alerta de código aberto. Ele "puxa" métricas (medições) dos microsserviços enviando solicitações HTTP e armazena os resultados em um banco de dados de séries temporais.

Você pode instrumentar seus serviços usando as bibliotecas de cliente fornecidas pelo Prometheus. Isso permitirá que você crie e colete métricas personalizadas de seus serviços.

O Prometheus também possui exportadores que permitem que você puxe métricas que não estão no formato do Prometheus. Um exportador age como um intermediário e transforma os dados exportados em um formato legível pelo Prometheus.

1-prometheus-architecture.png

O Prometheus fornece uma poderosa linguagem de consulta, PromQL, para trabalhar com esses dados coletados. Você pode usar o PromQL para criar consultas complexas para filtrar, agregar e transformar os dados no formato desejado.

Além de puxar métricas, o Prometheus também pode acionar alertas quando os limites definidos são ultrapassados. O mecanismo de alerta é altamente configurável e pode enviar notificações para lugares como Slack ou e-mail.

O Prometheus possui uma interface gráfica que permite visualizar facilmente as métricas coletadas. Ele também se integra a outras ferramentas avançadas de visualização, como o Grafana.

prometheus-dashboard.png

Tipos de Métricas

O Prometheus oferece quatro tipos principais de métricas:

  1. Contador: representa um único contador monotonicamente crescente. Seu valor pode aumentar ou ser reiniciado para zero na reinicialização. Você pode usá-lo para representar métricas como o número de solicitações atendidas.
  2. Gauge: representa um valor numérico que pode subir ou descer. Você pode usá-lo para representar valores como uso de memória ou número de solicitações por segundo.
  3. Histograma: amostra dados em intervalos configuráveis. Use-o para representar valores como durações de solicitação ou tamanhos de resposta.
  4. Resumo: semelhante ao histograma, ele também calcula valores configuráveis em uma janela de tempo deslizante.

Você pode aprender mais sobre esses tipos de métricas e como usá-los na documentação oficial.

Aplicação de Exemplo

Nossa aplicação de exemplo consistirá em um gateway de API, um aplicativo Go e um aplicativo Python.

2-sample-app-flowchart.png

A aplicação retornará "Olá <nome>!" no idioma que você escolher com o <nome> que você fornecer. O Apache APISIX será o gateway de API que direciona o tráfego para seus serviços.

O diagrama abaixo mostra como o sistema funciona.

3-sample-app-sequence.png

  1. O usuário envia uma solicitação GET para o APISIX, o ponto de entrada da aplicação.
  2. O APISIX encaminha a solicitação para o serviço Go.
  3. O serviço Go envia uma solicitação GET para o serviço Python para obter "Olá" no idioma especificado.
  4. O serviço Python responde com a tradução necessária de "Olá".
  5. O serviço Go cria a resposta necessária usando o nome fornecido na consulta e a envia para o APISIX.
  6. O APISIX encaminha a resposta de volta ao usuário.

Configurando o Prometheus para Coletar Métricas

Vamos instrumentar e exportar métricas de todos os serviços em nossa aplicação e coletá-las no Prometheus. Começaremos com nosso gateway de API, Apache APISIX.

Exportando Métricas do APISIX

O Apache APISIX é um gateway de API nativo da nuvem e de código aberto.

Você não precisa saber sobre o APISIX para acompanhar, e pode usar o arquivo Docker Compose fornecido para configurar tudo. Para saber mais sobre o APISIX, visite api7.ai/apisix.

O APISIX oferece um Plugin prometheus que facilita a exportação de métricas no formato Prometheus. Você pode configurar o Plugin em seu arquivo de configuração do APISIX:

apisix:
  enable_admin: false # executa o APISIX no modo autônomo
  config_center: yaml # usa um arquivo YAML para configuração em vez de armazená-lo no etcd
plugin_attr:
  prometheus:
    export_uri: /prometheus/metrics # habilita o Plugin prometheus e exporta as métricas para este URI
    enable_export_server: false # exporta as métricas na porta padrão do plano de dados

Agora podemos habilitar o Plugin em cada Rota, tornando-o uma Regra global:

routes:
  # encaminha solicitações para /hello/* para o go-app
  - uri: /hello/*
    upstream:
      type: roundrobin
      nodes:
        "go-app:8080": 1
    plugins:
      # remove o prefixo "/hello" antes de encaminhar a solicitação para o go-app
      proxy-rewrite:
        regex_uri:
          - "/hello/(.*)"
          - "/$1"
  # exporta métricas do Prometheus para o URI especificado
  - uri: /prometheus/metrics
    plugins:
      public-api:
# habilita o Plugin Prometheus globalmente em todas as Rotas
global_rules:
  - id: 1
    plugins:
      prometheus:
        prefer_name: true
#END

Isso exportará as métricas para o endpoint /prometheus/metrics no Apache APISIX.

Você pode aprender mais sobre as métricas disponíveis na documentação.

Instrumentando e Exportando Métricas do Serviço Go

O Prometheus possui uma biblioteca de cliente Go oficial para instrumentar aplicações Go.

Por padrão, o Prometheus expõe as métricas padrão do Go. Você também pode criar suas próprias métricas específicas da aplicação.

Em nosso serviço, exporemos as métricas padrão e criaremos nossa própria métrica de contador para rastrear o número de solicitações:

package main

import (
  "encoding/json"
  "fmt"
  "io/ioutil"
  "log"
  "net/http"
  "os"

  // Pacotes do Prometheus
  "github.com/prometheus/client_golang/prometheus"
  "github.com/prometheus/client_golang/prometheus/promauto"
  "github.com/prometheus/client_golang/prometheus/promhttp"
)

// Response armazena a Mensagem obtida do python-app
type Response struct {
  Message string `json:"message"`
}

// idioma e nome padrão
var (
  lang = "en"
  name = "John"
)

// cria uma nova métrica de contador personalizada do Prometheus
var pingCounter = promauto.NewCounter(
  prometheus.CounterOpts{
    Name: "go_app_request_count",
    Help: "Número de solicitações tratadas pelo go-app",
  },
)

// HelloHandler trata as solicitações para o go-app
func HelloHandler(w http.ResponseWriter, r *http.Request) {
  lang = r.URL.String()
  name = r.URL.Query()["name"][0]
  
  fmt.Println("Solicitação para", lang, "com nome", name)
  pingCounter.Inc()
  
  pUrl := os.Getenv("PYTHON_APP_URL")
  if len(pUrl) == 0 {
    pUrl = "localhost"
  }

  // chama o python-app para obter a tradução
  resp, err := http.Get("http://" + pUrl + ":8000" + lang)
  if err != nil {
    log.Fatalln(err)
  }

  body, err := ioutil.ReadAll(resp.Body)
  if err != nil {
    log.Fatalln(err)
  }

  resp.Body.Close()

  var m Response
  json.Unmarshal(body, &m)

  // envia a resposta com "Olá nome!" no idioma especificado
  fmt.Fprintf(w, "%s %s!", m.Message, name)
}

func main() {
  // expõe as métricas do Prometheus
  http.Handle("/metrics", promhttp.Handler())
  http.HandleFunc("/", HelloHandler)
  
  http.ListenAndServe(":8080", nil)
}

Isso exporá as métricas para o endpoint /metrics. Você pode aprender mais sobre a biblioteca de cliente Go em seu repositório GitHub.

Instrumentando e Exportando Métricas do Serviço Python

O Prometheus também possui uma biblioteca de cliente Python oficial. Existem também bibliotecas de terceiros que são adaptadas para casos de uso específicos.

Nosso serviço usa FastAPI, e usaremos a biblioteca prometheus_fastapi_instrumentator para instrumentá-lo:

from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware

from prometheus_fastapi_instrumentator import Instrumentator

app = FastAPI()

hello = {"en": "Hello", "fr": "Bonjour", "es": "Hola", "ml": "ഹലോ"}

# expõe as métricas padrão do Python para o endpoint /metrics
Instrumentator().instrument(app).expose(app)

@app.get("/{lang}")
async def get_hello(lang):
    return {"message": hello[lang]}

Você pode aprender mais sobre como criar métricas personalizadas na documentação.

Configurando o Prometheus

Agora podemos coletar essas métricas no Prometheus.

Você pode configurar o Prometheus para coletar métricas de cada um dos serviços. Por padrão, o Prometheus verifica as métricas no caminho /metrics:

global:
  scrape_interval: 15s
  evaluation_interval: 15s

scrape_configs:
  - job_name: "prometheus"
    static_configs:
      - targets: ["localhost:9090"]
  
  - job_name: "go-app"
    static_configs:
      - targets: ["go-app:8080"]

  - job_name: "python-app"
    static_configs:
      - targets: ["python-app:8000"]

  - job_name: "apisix"
    static_configs:
      - targets: ["apisix:9080"]
    metrics_path: "/prometheus/metrics"

É isso! Agora, se você abrir o painel do Prometheus (padrão na porta 9090) e clicar em "Status" na barra de navegação e em "Targets", você poderá ver o status das métricas sendo coletadas de seus serviços.

prometheus-target-status.png

Consultando e Visualizando Métricas no Prometheus

Agora, você pode usar o painel do Prometheus para executar consultas e expressões complexas.

prometheus-query.png

Você pode aprender mais sobre como consultar o Prometheus na documentação oficial.

Usando o Grafana para Consultar o Prometheus

O Grafana é uma plataforma de visualização de dados de código aberto que funciona com o Prometheus para fornecer uma ferramenta abrangente para coletar, consultar e visualizar métricas.

O Prometheus é bom em coletar métricas e consultar, mas carece de ferramentas para criar visualizações significativas. O Grafana supera essa limitação transformando as métricas coletadas em visualizações.

O Grafana também é compatível com muitas outras fontes de dados além do Prometheus.

Depois de implantar o Grafana, você pode abrir a interface web (padrão na porta 3000).

Primeiro, você precisa adicionar o Prometheus como uma fonte de dados. Para fazer isso, vá para /datasources ou "Configuração" e "Fontes de dados". Clique em "Adicionar fonte de dados" e selecione Prometheus. Especifique onde o Prometheus está implantado, salve e teste a conexão.

grafana-add-prometheus.png

Usando Painéis Pré-construídos do Grafana

O Grafana hospeda um repositório público de painéis que contém painéis pré-construídos do Grafana. Você pode usá-los em sua instância do Grafana para visualizar rapidamente as métricas relevantes.

Usaremos o painel Go Processes que processará e visualizará o status do processo publicado pela biblioteca de cliente Go do Prometheus.

Para importar este modelo, primeiro copie seu ID (6671) do repositório de painéis. Em sua interface do Grafana, vá para "Painéis" e selecione "Importar". Cole o ID que você copiou e clique em "Carregar".

grafana-dashboard.png

Você também pode explorar outros painéis pré-construídos ou criar os seus próprios. Consulte a documentação para saber mais sobre isso.

O Que Vem Depois?

Isso é tudo para este tutorial!

Este artigo foi apenas uma introdução sobre como você pode configurar o monitoramento em seus serviços, e eu encorajo você a aprender mais sobre o Prometheus e o Grafana a partir dos recursos mencionados abaixo:

O código completo e o arquivo Docker Compose para este tutorial estão disponíveis em pottekkat/monitoring-101.

Tags: