Surveillance des microservices avec Prometheus et Grafana

Navendu Pottekkat

Navendu Pottekkat

June 8, 2023

Ecosystem

La surveillance continue est essentielle pour rendre les systèmes de microservices robustes. Sans une surveillance appropriée, les microservices peuvent rapidement être submergés, entraînant des erreurs et une perte de performance.

Grâce à la surveillance continue, les développeurs peuvent détecter les problèmes de leurs services dès qu'ils surviennent et prendre des mesures pour prévenir des dommages importants. Elle fournit également des informations sur la performance de vos services, vous permettant de prendre des décisions éclairées.

Cet article présentera comment configurer la surveillance sur votre application de microservices en utilisant deux outils populaires dans ce domaine, Prometheus et Grafana.

Le code source et le fichier Docker Compose pour ce tutoriel sont disponibles sur pottekkat/monitoring-101.

Bases de Prometheus

Prometheus est un outil open-source de surveillance et d'alerte. Il "tire" les métriques (mesures) des microservices en envoyant des requêtes HTTP et stocke les résultats dans une base de données de séries temporelles.

Vous pouvez instrumenter vos services en utilisant les bibliothèques client fournies par Prometheus. Cela vous permettra de créer et de collecter des métriques personnalisées à partir de vos services.

Prometheus dispose également d'exportateurs qui vous permettent de tirer des métriques qui ne sont pas au format Prometheus. Un exportateur agit comme un intermédiaire et transforme les données exportées en un format lisible par Prometheus.

1-prometheus-architecture.png

Prometheus fournit un langage de requête puissant, PromQL, pour travailler avec ces données collectées. Vous pouvez utiliser PromQL pour créer des requêtes complexes afin de filtrer, agréger et transformer les données au format souhaité.

En plus de tirer des métriques, Prometheus peut également déclencher des alertes lorsque des seuils définis sont dépassés. Le mécanisme d'alerte est hautement configurable et peut envoyer des notifications vers des destinations comme Slack ou par e-mail.

Prometheus dispose d'une interface graphique qui vous permet de visualiser facilement les métriques collectées. Il s'intègre également avec d'autres outils de visualisation avancés comme Grafana.

prometheus-dashboard.png

Types de métriques

Prometheus propose quatre types de métriques de base :

  1. Compteur : représente un compteur unique qui augmente de manière monotone. Sa valeur peut augmenter ou être réinitialisée à zéro lors d'un redémarrage. Vous pouvez l'utiliser pour représenter des métriques comme le nombre de requêtes traitées.
  2. Jauge : représente une valeur numérique qui peut augmenter ou diminuer. Vous pouvez l'utiliser pour représenter des valeurs comme l'utilisation de la mémoire ou le nombre de requêtes par seconde.
  3. Histogramme : échantillonne les données dans des compartiments configurables. Utilisez-le pour représenter des valeurs comme la durée des requêtes ou la taille des réponses.
  4. Résumé : similaire à l'histogramme, il calcule également des valeurs configurables sur une fenêtre temporelle glissante.

Vous pouvez en apprendre davantage sur ces types de métriques et leur utilisation dans la documentation officielle.

Application Exemple

Notre application exemple sera composée d'une passerelle API, d'une application Go et d'une application Python.

2-sample-app-flowchart.png

L'application retournera "Hello <nom> !" dans la langue que vous choisissez avec le <nom> que vous fournissez. Apache APISIX sera la passerelle API qui dirige le trafic vers vos services.

Le diagramme ci-dessous montre comment le système fonctionne.

3-sample-app-sequence.png

  1. L'utilisateur envoie une requête GET à APISIX, le point d'entrée de l'application.
  2. APISIX transfère la requête au service Go.
  3. Le service Go envoie une requête GET au service Python pour obtenir "Hello" dans la langue spécifiée.
  4. Le service Python répond avec la traduction requise de "Hello".
  5. Le service Go crée la réponse requise en utilisant le nom fourni dans la requête et l'envoie à APISIX.
  6. APISIX transfère la réponse à l'utilisateur.

Configuration de Prometheus pour Collecter les Métriques

Nous allons instrumenter et exporter des métriques de tous les services de notre application et les collecter dans Prometheus. Nous commencerons par notre passerelle API, Apache APISIX.

Exportation des Métriques depuis APISIX

Apache APISIX est une passerelle API open-source et cloud-native.

Vous n'avez pas besoin de connaître APISIX pour suivre ce tutoriel, et vous pouvez utiliser le fichier Docker Compose fourni pour tout configurer. Pour en savoir plus sur APISIX, visitez api7.ai/apisix.

APISIX propose un Plugin Prometheus qui exporte facilement les métriques au format Prometheus. Vous pouvez configurer le Plugin dans votre fichier de configuration APISIX :

apisix:
  enable_admin: false # exécuter APISIX en mode autonome
  config_center: yaml # utiliser un fichier YAML pour la configuration au lieu de la stocker dans etcd
plugin_attr:
  prometheus:
    export_uri: /prometheus/metrics # activer le Plugin Prometheus et exporter les métriques vers cette URI
    enable_export_server: false # exporter les métriques sur le port par défaut du plan de données

Nous pouvons maintenant activer le Plugin sur chaque Route en le définissant comme une Règle globale :

routes:
  # rediriger les requêtes vers /hello/* vers go-app
  - uri: /hello/*
    upstream:
      type: roundrobin
      nodes:
        "go-app:8080": 1
    plugins:
      # supprimer le préfixe "/hello" avant de transférer la requête à go-app
      proxy-rewrite:
        regex_uri:
          - "/hello/(.*)"
          - "/$1"
  # exporter les métriques Prometheus vers l'URI spécifiée
  - uri: /prometheus/metrics
    plugins:
      public-api:
# activer le Plugin Prometheus globalement sur toutes les Routes
global_rules:
  - id: 1
    plugins:
      prometheus:
        prefer_name: true
#END

Cela exportera les métriques vers le point de terminaison /prometheus/metrics dans Apache APISIX.

Vous pouvez en apprendre davantage sur les métriques disponibles dans la documentation.

Instrumentation et Exportation des Métriques depuis le Service Go

Prometheus dispose d'une bibliothèque client officielle pour Go pour instrumenter les applications Go.

Par défaut, Prometheus exposera les métriques par défaut de Go. Vous pouvez également créer vos propres métriques spécifiques à l'application.

Dans notre service, nous exposerons les métriques par défaut et créerons notre propre compteur pour suivre le nombre de requêtes :

package main

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

  // Packages Prometheus
  "github.com/prometheus/client_golang/prometheus"
  "github.com/prometheus/client_golang/prometheus/promauto"
  "github.com/prometheus/client_golang/prometheus/promhttp"
)

// Response stocke le Message obtenu depuis python-app
type Response struct {
  Message string `json:"message"`
}

// langue et nom par défaut
var (
  lang = "en"
  name = "John"
)

// créer une nouvelle métrique compteur Prometheus personnalisée
var pingCounter = promauto.NewCounter(
  prometheus.CounterOpts{
    Name: "go_app_request_count",
    Help: "Nombre de requêtes traitées par go-app",
  },
)

// HelloHandler gère les requêtes vers go-app
func HelloHandler(w http.ResponseWriter, r *http.Request) {
  lang = r.URL.String()
  name = r.URL.Query()["name"][0]
  
  fmt.Println("Requête pour", lang, "avec le nom", name)
  pingCounter.Inc()
  
  pUrl := os.Getenv("PYTHON_APP_URL")
  if len(pUrl) == 0 {
    pUrl = "localhost"
  }

  // appeler python-app pour obtenir la traduction
  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)

  // renvoyer la réponse avec "Hello nom !" dans la langue spécifiée
  fmt.Fprintf(w, "%s %s!", m.Message, name)
}

func main() {
  // exposer les métriques Prometheus
  http.Handle("/metrics", promhttp.Handler())
  http.HandleFunc("/", HelloHandler)
  
  http.ListenAndServe(":8080", nil)
}

Cela exposera les métriques au point de terminaison /metrics. Vous pouvez en apprendre davantage sur la bibliothèque client Go depuis son dépôt GitHub.

Instrumentation et Exportation des Métriques depuis le Service Python

Prometheus dispose également d'une bibliothèque client officielle pour Python. Il existe également des bibliothèques tierces adaptées à des cas d'utilisation spécifiques.

Notre service utilise FastAPI, et nous utiliserons la bibliothèque prometheus_fastapi_instrumentator pour l'instrumenter :

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": "ഹലോ"}

# exposer les métriques Python par défaut au point de terminaison /metrics
Instrumentator().instrument(app).expose(app)

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

Vous pouvez en apprendre davantage sur la création de métriques personnalisées dans la documentation.

Configuration de Prometheus

Nous pouvons maintenant collecter ces métriques dans Prometheus.

Vous pouvez configurer Prometheus pour collecter les métriques de chacun des services. Par défaut, Prometheus vérifie les métriques dans le chemin /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"

C'est tout ! Maintenant, si vous ouvrez le tableau de bord Prometheus (par défaut sur le port 9090) et cliquez sur "Status" dans la barre de navigation et "Targets", vous pourrez voir l'état des métriques collectées depuis vos services.

prometheus-target-status.png

Interrogation et Visualisation des Métriques dans Prometheus

Maintenant, vous pouvez utiliser le tableau de bord Prometheus pour exécuter des requêtes et des expressions complexes.

prometheus-query.png

Vous pouvez en apprendre davantage sur l'interrogation de Prometheus dans la documentation officielle.

Utilisation de Grafana pour Interroger Prometheus

Grafana est une plateforme open-source de visualisation de données qui fonctionne avec Prometheus pour fournir un outil complet de collecte, d'interrogation et de visualisation des métriques.

Prometheus est bon pour collecter les métriques et interroger, mais manque d'outils pour créer des visualisations significatives. Grafana surmonte cette limitation en transformant les métriques collectées en visualisations.

Grafana est également compatible avec de nombreuses autres sources de données que Prometheus.

Une fois que vous avez déployé Grafana, vous pouvez ouvrir l'interface web (par défaut sur le port 3000).

Tout d'abord, vous devez ajouter Prometheus comme source de données. Pour ce faire, allez dans /datasources ou "Configuration" et "Data sources". Cliquez sur "Add data source" et sélectionnez Prometheus. Spécifiez où Prometheus est déployé, sauvegardez et testez la connexion.

grafana-add-prometheus.png

Utilisation de Tableaux de Bord Pré-construits dans Grafana

Grafana héberge un référentiel public de tableaux de bord qui contient des tableaux de bord Grafana pré-construits. Vous pouvez les utiliser dans votre instance Grafana pour visualiser rapidement les métriques pertinentes.

Nous utiliserons le tableau de bord Go Processes qui traitera et visualisera l'état des processus publiés par la bibliothèque client Prometheus pour Go.

Pour importer ce modèle, copiez d'abord son ID (6671) depuis le référentiel de tableaux de bord. Dans votre interface Grafana, allez dans "Dashboards" et sélectionnez "Import". Collez l'ID que vous avez copié et cliquez sur "Load".

grafana-dashboard.png

Vous pouvez également explorer d'autres tableaux de bord pré-construits ou créer les vôtres. Consultez la documentation pour en savoir plus à ce sujet.

Et Après ?

C'est tout pour ce tutoriel !

Cet article n'était qu'une introduction à la manière dont vous pouvez configurer la surveillance sur vos services, et je vous encourage à en apprendre davantage sur Prometheus et Grafana à partir des ressources mentionnées ci-dessous :

Le code complet et le fichier Docker Compose pour ce tutoriel sont disponibles sur pottekkat/monitoring-101.

Tags: