Nomad metrics

OpenTelemetry: metrics pour Nomad en utilisant Prometheus, et Grafana

La dernière fois on avait déployé un cluster Nomad basique. Nous allons voir commencer à ajouter la collection des metrics depuis les services principaux (nomad et traefik).

Pour cela on va déployer Prometheus, et Grafana pour explorer la donnée.

On crée le fichier prometheus.hcl.

 0job "prometheus" {
 1  datacenters = ["services"]
 2  group "prometheus" {
 3    count = 1
 4    network {
 5      port "prometheus_ui" {
 6        to = 9090
 7      }
 8    }
 9    service {
10        name = "prometheus"
11        port = "prometheus_ui"
12        provider = "nomad"
13        tags = [
14            "traefik.enable=true",
15            "traefik.http.routers.prometheus.service=prometheus",
16            "traefik.http.routers.prometheus.rule=Host(`prometheus.service.local`)",
17            "traefik.http.routers.prometheus.tls=true",
18        ]
19    }
20
21    task "prometheus" {
22      driver = "docker"
23
24      config {
25        image = "docker.io/prom/prometheus:v2.53.4"
26        ports = ["prometheus_ui"]
27        args = [
28          "--config.file=/etc/prometheus/config/prometheus.yml",
29          "--storage.tsdb.path=/prometheus",
30          "--web.listen-address=0.0.0.0:9090",
31          "--web.console.libraries=/usr/share/prometheus/console_libraries",
32          "--web.console.templates=/usr/share/prometheus/consoles"
33        ]
34        volumes = [
35          "local/prom/config:/etc/prometheus/config",
36        ]
37      }
38      template {
39        data = <<EOH
40---
41global:
42  scrape_interval:     1s
43  evaluation_interval: 1s
44scrape_configs:
45  - job_name: 'traefik'
46    scrape_interval: 5s
47    static_configs:
48      - targets: ["traefik.metrics.service.local"]
49EOH
50
51        change_mode   = "signal"
52        change_signal = "SIGHUP"
53        destination   = "local/prom/config/prometheus.yml"
54      }
55      resources {
56        cpu    = 100
57        memory = 256
58      }
59    }
60  }
61}

Alors voyons ça plus en détail. Comme on déploie notre service Prometheus de manière libre sur Nomad, il nous est impossible de savoir quelle Ip aura le service de manière sûre. Pour palier à cela, nous enregistrons un entrypoint sur Traefik pour rediriger vers Prometheus, le tout de manière dynamique, en redirigeant vers le port donnée à la volée par Nomad.

13        tags = [
14            "traefik.enable=true",
15            "traefik.http.routers.internal-prometheus.service=prometheus",
16            "traefik.http.routers.internal-prometheus.rule=Host(`prometheus.service.local`)",
17            "traefik.http.routers.internal-prometheus.tls=true",
18        ]
Ainsi si Prometheus est accessible sur prometheus.service.local. Et le tout en https.

Et dans le fichier de configuration on ajoute le chemin de collection pour traefik.

On va ajouter des arguments supplémentaires au service Traefik pour exposer des metrics au format prometheus, et définir une route manuellement pour y accéder.

0          "--metrics.prometheus=true",
1          "--metrics.prometheus.addRoutersLabels=true",
2          "--metrics.prometheus.addServicesLabels=true",
3          "--metrics.prometheus.addEntryPointsLabels=true",
4          "--metrics.prometheus.manualRouting=true",

On va ajouter sur toutes à les metrics de Traefik le router, service et entrypoint.

0        "traefik.http.routers.metrics.service=prometheus@internal",
1        "traefik.http.routers.metrics.rule=Host(`traefik.metrics.service.internal`)",
2        "traefik.http.routers.metrics.tls=true",

Et on exposé les données sur le dns traefik.metrics.service.internal, en pointant vers le service prometheus@internal.

Dans l’étape antérieur nous avons configuré Nomad, pour exposer des metrics. Elle sont accessibles en mTLS sur l’url https//server1.vm:4646/v1/metrics?format=prometheus

0curl --cert /opt/nomad/certs/global-client-nomad.pem --key /opt/nomad/certs/global-client-nomad-key.pem --cacert /opt/nomad/certs/nomad-agent-ca.pem 'https//server1.vm:4646/v1/metrics?format=prometheus'

On doit à nouveau générer des certificats clients pour Prometheus et les téléverser sur les machine client2 et client3, ainsi que le ca /opt/nomad/certs/nomad-agent-ca.pem.

0$docker run --rm -it -v /opt/nomad/certs:/home -w /home  docker.io/hashicorp/nomad:1.9.5 tls cert create -client additional-dnsname server1.vm -additional-dnsname server.nomad.dns.com -days 90

Et modifier la configuration de Prometheus, pour ajouter un autre job de collection:

45  - job_name: 'traefik'
46    scrape_interval: 5s
47    static_configs:
48      - targets: ["traefik.metrics.service.local"]
49  - job_name: 'nomad-server'
50    scrape_interval: 10s
51    scrape_timeout: 5s
52    metrics_path: '/v1/metrics'
53    params:
54      format: ['prometheus']
55    scheme: https
56    tls_config:
57      ca_file: /opt/nomad/certs/nomad-agent-ca.pem
58      cert_file: /opt/nomad/certs/prometheus.pem
59      key_file: /opt/nomad/certs/prometheus-key.pem
60      insecure_skip_verify: true
61    static_configs:
62      - targets: ['server1.vm:4646']
 0job "grafana" {
 1  datacenters = ["services"]
 2  type        = "service"
 3  group "grafana" {
 4    count = 1
 5
 6    network {
 7      port "grafana" {
 8        to = 3000
 9      }
10    }
11    service {
12      name = "grafana"
13      port = "grafana"
14      provider = "nomad"
15      tags = [
16        "traefil.enable=true",
17        "traefik.http.routers.grafana.tls=true"
18      ]
19    }
20
21    task "grafana" {
22      driver = "docker"
23      env {
24        GF_LOG_LEVEL          = "ERROR"
25        GF_LOG_MODE           = "console"
26        GF_PATHS_DATA         = "/var/lib/grafana"
27        GF_PATHS_PROVISIONING = "/local/grafana/provisioning"
28      }
29      user = "root"
30      config {
31        image = "grafana/grafana:10.4.2"
32        ports = ["grafana"]
33        volumes = ["/opt/data/grafana:/var/lib/grafana"]
34      }
35      resources {
36        cpu    = 200
37        memory = 200
38      }
39    }
40  }
41}

Désormais Grafana est accessible sur https://grafana.service.dns.com. Si vous souhaitez lui passez une configuration spécifique vous pouvez utiliser la stanza template.

Il suffira alors de créer un datasource pour le service Prometheus en pointant sur prometheus.service.local.

Comme vous voyez avoir des metrics sur votre cluster de base est simple et rapide. On peut facilement instrumentaliser Nomad et Traefik.

Pour aller plus loin, on peut aller chercher des metrics sur l’engine docker, par exemple en utilisant CAdvisor. Ajouter l’authentification à Prometheus.