Exposer les métriques Prometheus de vos pods Kubernetes vers Mimir
Vous voulez monitorer votre application et vous ne voulez pas gérer un Prometheus. Bonne nouvelle : sur Kubernetes France Nuage, Alloy, Mimir et Grafana sont déjà là. Vous ajoutez trois annotations sur votre pod, et vos métriques remontent automatiquement dans Mimir. Pas d'Helm chart à installer, pas de scraper à configurer, pas de tenant à créer.
Ce qu'il vous faut
- Un namespace sur votre cluster Kubernetes France Nuage
- Une instance Grafana France Nuage (voir le guide Stack Grafana)
- Une application qui expose — ou peut exposer — un endpoint
/metricsau format Prometheus
C'est tout. Aucun composant d'observabilité à déployer de votre côté.
Prometheus, Mimir : c'est quoi la différence ?
Prometheus est le standard pour collecter et stocker des métriques. Il est fantastique pour une instance unique, mais il devient compliqué à l'échelle : rétention longue, haute disponibilité, multi-tenant, ça demande du travail.
Mimir est la version scalable de Prometheus. Même langage de requête (PromQL), même format de métriques, mais pensé pour le long terme, la haute disponibilité et le multi-tenant. Vos dashboards et vos alertes continuent de fonctionner à l'identique — Mimir ressemble à Prometheus côté client. Pour plus de détails, lisez le guide Mimir.
Sur Kubernetes France Nuage, on exécute :
- Grafana Alloy comme collecteur : il découvre automatiquement les pods à scraper via les annotations
- Mimir comme backend de stockage : un tenant par namespace, isolation garantie
- Grafana : déjà branché sur Mimir avec votre tenant pré-configuré
Étape 1 : exposer un endpoint /metrics
Si votre application expose déjà /metrics, sautez à l'étape 2.
Sinon, voici un exemple minimal avec Node.js et prom-client :
npm install express prom-client
// server.js
const express = require('express');
const client = require('prom-client');
const register = new client.Registry();
register.setDefaultLabels({ app: 'mon-service' });
client.collectDefaultMetrics({ register });
const httpRequests = new client.Counter({
name: 'http_requests_total',
help: 'Total des requêtes HTTP reçues',
labelNames: ['method', 'status'],
});
register.registerMetric(httpRequests);
const app = express();
app.get('/', (req, res) => {
httpRequests.inc({ method: 'GET', status: '200' });
res.send('hello');
});
app.get('/metrics', (req, res) => {
register.metrics().then((metrics) => {
res.set('Content-Type', register.contentType);
res.end(metrics);
});
});
app.listen(9090, () => console.log('listening on :9090'));
Vous avez maintenant une app qui écoute sur le port 9090 et expose ses métriques sur /metrics. Vous pouvez tester localement :
curl http://localhost:9090/metrics
Vous devriez voir une série de métriques par défaut (process_cpu_seconds_total, nodejs_heap_size_used_bytes, etc.) suivies de votre http_requests_total.
Étape 2 : ajouter les annotations sur votre Pod
C'est le cœur du tutoriel. Alloy scrute le cluster en continu et scrape tous les pods qui portent ces annotations :
metadata:
annotations:
prometheus.io/scrape: "true"
prometheus.io/port: "9090" # port du /metrics
prometheus.io/path: "/metrics" # optionnel, /metrics par défaut
Attention : ces annotations doivent être sur le Pod, pas sur le Deployment ou le Service. Concrètement, elles vont dans spec.template.metadata.annotations d'un Deployment :
apiVersion: apps/v1
kind: Deployment
metadata:
name: mon-service
namespace: mon-app
spec:
replicas: 2
selector:
matchLabels:
app: mon-service
template:
metadata:
labels:
app: mon-service
annotations:
prometheus.io/scrape: "true"
prometheus.io/port: "9090"
prometheus.io/path: "/metrics"
spec:
containers:
- name: app
image: registry.gitlab.com/mon-groupe/mon-service:latest
ports:
- name: http
containerPort: 9090
Appliquez :
kubectl apply -f deployment.yaml -n mon-app
Si vous déployez via un pipeline CI/CD, jetez un œil au tutoriel Déployer sur Kubernetes depuis GitLab CI pour câbler helm upgrade à chaque push.
Alloy détecte le nouveau pod, commence à scraper /metrics toutes les 15 secondes, et pousse les points vers Mimir avec le header X-Scope-OrgID: mon-app. Le tenant Mimir est dérivé du nom de votre namespace — vous n'avez rien à configurer.
Étape 3 : interroger vos métriques dans Grafana
Ouvrez votre instance Grafana France Nuage. La datasource Mimir est déjà configurée et branchée sur votre tenant.
- Allez dans Explore
- Sélectionnez la datasource Mimir
- Tapez une requête PromQL, par exemple :
http_requests_total{app="mon-service"}
Ou pour voir le taux de requêtes sur 5 minutes :
sum(rate(http_requests_total{app="mon-service"}[5m])) by (status)
Vous pouvez aussi vérifier que le scrape fonctionne en cherchant la métrique up :
up{namespace="mon-app"}
Une valeur à 1 signifie que le scrape est réussi. Une valeur à 0 indique qu'Alloy n'arrive pas à joindre votre endpoint — passez à la section dépannage.
Dépannage
La métrique up renvoie 0
Alloy voit votre pod mais n'arrive pas à scraper l'endpoint. Vérifiez dans l'ordre :
- Le port est correct : l'annotation
prometheus.io/portdoit pointer vers le port d'écoute réel du container, pas le port du Service - Le path est correct : si votre endpoint n'est pas
/metrics, ajoutezprometheus.io/path: "/votre-path" - Le container écoute sur toutes les interfaces :
0.0.0.0:9090, pas127.0.0.1:9090, sinon Alloy ne peut pas l'atteindre depuis l'extérieur du pod
La métrique up n'apparaît pas du tout
Alloy ne voit même pas votre pod. C'est presque toujours un problème d'annotations :
- Les annotations sont sur le Pod (
spec.template.metadata.annotations), pas sur le Deployment lui-même - Les valeurs sont des strings :
"true","9090", pastrueou9090 - L'annotation
prometheus.io/scrapevaut bien"true"(pas"1"ni"yes")
Vérifiez avec :
kubectl get pod -n mon-app -l app=mon-service -o jsonpath='{.items[0].metadata.annotations}'
Mes métriques n'apparaissent pas dans Grafana
Si up fonctionne mais que vos métriques custom ne sortent pas :
- Vérifiez que vous êtes sur la bonne datasource (Mimir, pas une Prometheus locale)
- Enlevez les filtres trop restrictifs de votre requête PromQL
- Patientez 15-30 secondes : c'est l'intervalle de scrape
ERR cardinality limit exceeded
Mimir protège le tenant contre l'explosion de cardinalité. Si vous voyez cette erreur, une de vos métriques a trop de combinaisons de labels distinctes. Passez à la section suivante.
Bonnes pratiques
Maîtrisez la cardinalité des labels
C'est le piège numéro un avec Prometheus et Mimir. Chaque combinaison unique de labels crée une série temporelle distincte, et chaque série consomme de la mémoire.
À éviter absolument :
user_id,request_id,trace_idcomme labels : cardinalité infinie, votre tenant va exploserurlbrute :/user/42,/user/43... transformez-la en template/user/:idtimestampou toute valeur dérivée du temps
À préférer :
- Labels à cardinalité bornée :
method,status,endpoint(templaté),env - Un
appet unenvcohérents sur toutes vos métriques pour faciliter les requêtes
Nommez vos métriques selon les conventions Prometheus
- Suffixe
_totalpour les counters - Suffixe
_secondspour les durées (pas_ms) - Suffixe
_bytespour les tailles - Nom en
snake_case, pas de majuscules
Une app, un port, un endpoint
Exposer /metrics sur le même port que votre app principale est plus simple à configurer qu'un port dédié. Si vous avez une raison de les séparer (sécurité, pare-feu), pensez à ouvrir un second port dans votre container et à ajuster prometheus.io/port.
Aller plus loin
- Guide Mimir — architecture, multi-tenant, comparatif, bonnes pratiques
- Guide Stack Grafana — créer des dashboards, configurer Alertmanager, envoyer des logs vers Loki
- Déployer sur Kubernetes depuis GitLab CI — automatiser le déploiement de vos pods annotés
- Documentation PromQL — le langage de requête
Des questions ? support@france-nuage.fr