TP: Monitoring

Principe

  • Instrumenter des applications
    • Ajout de logs pour suivre l’exécution
    • Ajout de métriques
    • Contextualisation des logs

Dans ce TP, on travaillera sur les applications API et Worker du TP Déploiement Kubernetes. Il faudra pouvoir redéployer vos propres versions de ces applications, donc pousser vos propres images sur vos dépôts harbor.

Sondes dans les applications api et worker

Modifier le déploiement de l’application worker afin d’y ajouter une sonde de liveness.

Note: le code de worker embarque déjà une route pour la sonde en question, il y donc uniquement à changer le déploiement.

Modifier l’application api afin d’ajouter des routes pour deux sondes:

  • une sonde de liveness qui indiquera que le serveur fonctionne
  • une sonde de readiness qui vérifiera en plus que le service worker est vivant

Redéployer api en y ajoutant les deux sondes et tester leur bon fonctionnement, par exemple en descendant à 0 le nombre de workers.

Logs dans les applications api et worker

Modifier api et worker afin d’ajouter des logs:

  • sur les réceptions de requêtes
  • sur la réussite ou l’échec des requêtes
  • sur les actions des différents services

Ajouter également des logs de debug permettant de suivre les principaux appels de méthodes entre les composants au sein de chacune des applications.

Redéployer et vérifier que les logs sont bien visibles avec kubectl logs.

Mesures au sein des applications

On souhaite à présent ajouter des mesures aux différents déploiements.

Déploiement de prometheus

Déployer un serveur prometheus. On pourra utiliser par exemple l’image bitnami/prometheus:2 (doc). Ci-dessous un fichier de configuration à placer dans une ConfigMap qui sera montée à l’emplacement /opt/bitnami/prometheus/conf/prometheus.yml:

# my global config
global:
  scrape_interval: 15s # Set the scrape interval to every 15 seconds. Default is every 1 minute.
  evaluation_interval: 15s # Evaluate rules every 15 seconds. The default is every 1 minute.
  # scrape_timeout is set to the global default (10s).

# Alertmanager configuration
alerting:
  alertmanagers:
    - static_configs:
        - targets:
          # - alertmanager:9093

# Load rules once and periodically evaluate them according to the global 'evaluation_interval'.
rule_files:
# - "first_rules.yml"
# - "second_rules.yml"

# A scrape configuration containing exactly one endpoint to scrape:
# Here it's Prometheus itself.
scrape_configs:
  # The job name is added as a label `job=<job_name>` to any timeseries scraped from this config.
  - job_name: "prometheus"

    # metrics_path defaults to '/metrics'
    # scheme defaults to 'http'.

    static_configs:
      - targets: ["localhost:9090"]

Pour le moment ce fichier contient une configuration de récupération de métriques (dans scrape_configs): prometheus lui-même.

Rediriger le port 9090 en local via kubectl port-forward, puis accéder à la route /graph de prometheus. Dans la zone de recherche, taper scrap et sélectionner scrape_samples_scraped parmi les suggestions. Basculer dans le tab Graph pour afficher une courbe sur une période de temps (par défaut 1h).

Instrumentation de PostgreSQL

PostgreSQL ne rend pas directement accessible ses métriques à Prometheus. On va passer par un conteneur annexe dédié à cette tâche. On utilisera pour ça le PostgreSQL Server Exporter.

Modifier le déploiement de postgresql de façon à ajouter un side container base sur le PostgreSQL Server Exporter. Comme les deux conteneurs (postgresql et l’exporteur) sont dans le même pod, l’adresse pour accéder à postgresql devrait être localhost.

Modifier la configuration de prometheus pour récupérer les métriques ainsi exportées et vérifier que la récupération fonctionne (par exemple en regardant l’onglet status -> targets ou en affichant la métrique pg_stat).

Métriques dans les applications Spring

Monitoring par défaut

Ajouter les dépendances suivantes au projets Spring:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
    <groupId>io.micrometer</groupId>
    <artifactId>micrometer-registry-prometheus</artifactId>
    <version>1.8.2</version>
</dependency>

Ajouter également les entrées suivantes dans application.properties:

# Monitoring, see https://dzone.com/articles/monitoring-and-profiling-spring-boot-application
# Enable prometheus exporter
management.metrics.export.prometheus.enabled=true
# Enable prometheus end point
management.endpoints.web.exposure.include=prometheus
# enable percentile-based histogram for http requests
management.metrics.distribution.percentiles-histogram.http.server.requests=true
# http SLA histogram buckets
management.metrics.distribution.sla.http.server.requests=100ms,150ms,250ms,500ms,1s
# enable JVM metrics
management.metrics.enable.jvm=true

Repackager l’application, la lancer en local vérifier qu’elle répond bien sur la route /actuator et que le point d’accès pour prometheus fourni bien des métriques. Noter le chemin de récupération des métriques prometheus, puis arrêter le serveur.

Redéployer les applications dans kubernetes.

Ajouter une configuration de scraping pour ces applications dans la configuration de prometheus. Au même niveau que le job_name, ajouter une entrée metrics_path avec comme valeur le chemin noté précédement.

Une fois la configuration mise en place, vérifier que les métriques sont disponibles (e.g. jvm_memory_used_bytes).

Monitoring spécifique

En s’inspirant de la section Custom Metrics du tutoriel Monitoring and Profiling Your Spring Boot Application, ajouter un gauge pour mesurer le nombre d’appels à la route de chiffrement d’api et un compteur pour compter le nombre total de clés. Redéployer, puis vérifier la présence des mesures dans Prometheus.

Utiliser ensuite l’annotation @io.micrometer.core.annotation.Timed sur une des méthodes du contrôleur EncryptController et effectuer une requête, puis vérifier la présence de la mesure. Quelles mesures supplémentaires on été créées? Remarque: Timed prend plusieurs arguments optionels dont le nom de la mesure. Spécifier des tags supplémentaires via extraTags (le tableau de Strings contient une clé puis sa valeur, puis une autre clé, puis la valeur de la deuxième clé, etc). Déployer et vérifier la présence des tags dans la mesure.

Remarque: Les mesures produites par @Timed permettent également de récupérer le nombre d’appels aux méthodes annotées.

Logs contextualisés et suivi de requête

En suivant les explications sur les MDC, ajouter un contexte aux logs de l’api associant à chaque requête un identifiant unique. Modifier l’appel à worker afin d’y ajouter un header contenant également cet identifiant.

Du côté de worker, récupérer le contenu du header puis l’injecter comme contexte dans les logs de worker.

Redéployer et vérifier que vous pouvez tracer à travers les logs les appels liés à une requête dans API jusque dans worker.