Observer avec Cockpit
Pourquoi
Le soir du 14 septembre, un orage traverse la métropole. En deux heures, les habitants envoient autant de signalements qu'en une semaine ordinaire. Le groupe d'instances s'agrandit, la base répond plus lentement, puis quelques utilisateurs reçoivent des erreurs 502. Le lendemain matin, l'équipe veut comprendre : à quelle heure la latence a-t-elle décroché ? était-ce la base, le Redis, les instances ? combien de requêtes ont échoué ? Elle n'a, pour répondre, que des journalctl lancés à la main sur des instances dont la moitié ont déjà été supprimées par la réduction automatique du groupe.
C'est le problème que résout l'observabilité : pouvoir répondre, après coup ou en direct, à des questions sur le comportement d'un système sans y avoir accès directement, à partir des données qu'il émet. Trois types de données y contribuent : les métriques (des nombres mesurés dans le temps : requêtes par seconde, latence, mémoire), les journaux (des événements datés, en texte) et les traces (le parcours d'une requête à travers les composants). Le cours Observabilité : les principes les présentera en détail ; cette leçon montre comment les obtenir chez Scaleway.
Sans observabilité, trois choses arrivent. On apprend les pannes par les utilisateurs. On diagnostique à l'aveugle, en redémarrant ce qui « a l'air » malade. Et, avec des instances éphémères, on perd les preuves : les journaux d'une machine supprimée par l'autoscaling disparaissent avec elle.
Cockpit est le service d'observabilité managé de Scaleway. Cette leçon en fait le tour, puis branche Signalements dessus, de façon que la prochaine soirée d'orage se lise sur un tableau de bord et déclenche une alerte avant les plaintes.
Les concepts
Ce qu'est Cockpit
Cockpit stocke des métriques, des journaux et des traces, et fournit une instance de Grafana pour les visualiser. Il repose sur des logiciels libres de Grafana Labs : Mimir pour les métriques (compatible avec Prometheus), Loki pour les journaux, Tempo pour les traces. Chaque projet Scaleway a un seul Cockpit, activé automatiquement dès que vous utilisez un produit intégré.
Ses équivalents ailleurs : Amazon CloudWatch (et, pour l'écosystème Prometheus, Amazon Managed Service for Prometheus et Amazon Managed Grafana), Azure Monitor, Google Cloud Observability. La différence de fond, chez Scaleway, est que tout repose sur des formats et des protocoles ouverts (écriture distante Prometheus, API Loki, OTLP) : un agent configuré pour Cockpit pousse aussi bien vers un Prometheus ou un Loki que vous hébergeriez, ce qui compte pour la réversibilité.
Cockpit organise les données en sources de données (data sources) régionales, de deux sortes :
- les sources Scaleway, alimentées automatiquement par les produits intégrés, et en lecture seule ;
- les sources personnalisées, que vous créez dans une région, pour y pousser vos propres métriques, journaux ou traces.
Les données d'un produit Scaleway sont stockées dans la région de ce produit ; les données personnalisées, dans la région de leur source, sans réplication vers d'autres régions. La documentation indique qu'elles sont dupliquées sur les zones de la région. Le Grafana du projet interroge toutes les régions où vous avez des sources.
Ce que les produits envoient d'eux-mêmes
C'est la bonne nouvelle : une bonne partie de l'observabilité de l'infrastructure est déjà là, sans agent, et gratuite dans la durée de conservation par défaut. Au 5 octobre 2026, la page d'intégration de Cockpit indique notamment, pour les produits de Signalements :
| Produit | Métriques | Journaux |
|---|---|---|
| Instances (CPU et GPU) | oui | non |
| Block Storage | oui | non |
| Object Storage | oui | oui |
| Managed Database for PostgreSQL | oui | oui |
| Managed Database for Redis | oui | oui |
| Load Balancer | oui | oui |
| Public Gateway | oui | oui |
| VPC | oui | non |
| Edge Services | oui | oui |
| Serverless Containers, Functions et Jobs | oui | oui |
| Secret Manager | oui | non |
| Queues, Topics and Events, NATS | oui | non |
| Transactional Email | oui | non |
| Container Registry, Domains and DNS, IAM, Audit Trail | non | non |
Deux lignes méritent l'attention. Les instances fournissent des métriques vues de l'hyperviseur (processeur, réseau, disque), mais aucun journal : ce que votre application écrit reste sur la machine tant qu'un agent ne l'envoie pas. Et la plupart de ces intégrations viennent avec des tableaux de bord préconfigurés, que Scaleway maintient.
Jetons et accès à Grafana
Pour pousser ou lire des données personnalisées, on s'authentifie avec un jeton Cockpit, régional, dont on choisit les portées. La CLI 2.62 en propose dix : lecture seule ou écriture seule pour les métriques, les journaux et les traces, accès complet aux règles de métriques ou de journaux, et accès complet au gestionnaire d'alertes. Un agent de collecte n'a besoin que des portées write_only_metrics et write_only_logs : il ne doit pas pouvoir lire ce qu'il envoie, ni modifier les alertes.
L'accès humain à Grafana passe, depuis le 3 novembre 2025, par l'IAM de Scaleway : on se connecte à Grafana avec son compte Scaleway, second facteur compris. La connexion par identifiants Grafana propres a été retirée le 20 janvier 2026. Les droits sur Cockpit se donnent donc comme les autres, par des politiques IAM (le jeu ObservabilityFullAccess pour l'administration, par exemple), ce que la leçon 1 a organisé.
Conservation et coût
La durée de conservation (retention) se règle par source de données. Au 5 octobre 2026 :
| Métriques personnalisées | Journaux et traces personnalisés | Métriques Scaleway | Journaux Scaleway | |
|---|---|---|---|---|
| Minimum | 1 jour | 1 jour | 31 jours | 1 jour |
| Par défaut | 31 jours | 7 jours | 31 jours | 7 jours |
| Maximum | 5 ans | 5 ans | 5 ans | 5 ans |
La tarification, telle que la documente Scaleway :
- Données Scaleway : collecte gratuite ; conservation gratuite jusqu'aux durées par défaut (31 jours pour les métriques, 7 pour les journaux).
- Données personnalisées : ingestion payante, 0,15 € par million d'échantillons de métriques (avec des paliers dégressifs au-delà de 10 milliards par mois), 0,35 € par Go de journaux ou de traces ; conservation gratuite jusqu'aux durées par défaut.
- Au-delà des durées par défaut : 0,0002 € pour 10 millions d'échantillons par jour pour les métriques, 0,002 € par Go et par jour pour les journaux et les traces.
Un échantillon est un point d'une série temporelle : une valeur, à un instant, pour une combinaison d'étiquettes. C'est l'unité qui se paie, et c'est elle qu'il faut savoir compter (voir En pratique).
Les limites qui comptent
La page des limites de Cockpit fixe, entre autres, pour les métriques : 25 000 échantillons par seconde en ingestion, 1 million de séries actives par source de données, 65 étiquettes par série ; pour les journaux : 4 Mo par seconde en ingestion, 256 Ko par ligne, 15 étiquettes par flux, et des requêtes sur 30 jours et une heure au plus. Les règles d'alerte et d'enregistrement sont évaluées au mieux toutes les 15 secondes, avec 20 règles par groupe et 70 groupes par projet.
Les alertes
Le gestionnaire d'alertes (alert manager) est régional et doit être activé. Il reçoit les alertes déclenchées et notifie des contacts (courriel, et d'autres canaux configurables dans Grafana). Deux sources d'alertes :
- les alertes préconfigurées, fournies par Scaleway pour certains produits, que l'on active une à une ; leurs seuils et leurs durées sont fixés par Scaleway et ne se modifient pas ;
- les règles personnalisées, écrites en PromQL (métriques) ou LogQL (journaux), envoyées par l'API de règles de Mimir ou de Loki, ou créées dans Grafana. Dans Grafana, il faut choisir des alertes gérées par la source de données : la documentation précise que les alertes gérées par Grafana lui-même ne sont pas prises en charge.
En pratique
Les commandes ont été vérifiées avec l'aide de la CLI scw 2.62 et les structures du SDK Go. Le code Python a été exécuté localement avec le client de test de Flask ; la sortie montrée plus bas en provient. Le reste de la leçon ne montre pas de sortie.
1. Ouvrir Grafana et lire ce qui existe déjà
$ scw cockpit grafana get -o json | jq -r .grafana_url
L'adresse affichée ouvre le Grafana du projet, avec connexion par votre compte Scaleway. Dans le dossier des tableaux de bord Scaleway, ouvrez ceux des instances, de la base et du répartiteur, et sélectionnez la région fr-par en haut de page : les tableaux préconfigurés filtrent par région. Vous avez déjà, sans rien installer, le processeur des instances, les connexions et la latence de la base, et les codes de réponse du répartiteur. C'est de là que part tout diagnostic d'infrastructure.
2. Créer les sources personnalisées
$ MET=$(scw cockpit data-source create name=sig-metriques type=metrics \
retention-days=31 region=fr-par -o json)
$ LOG=$(scw cockpit data-source create name=sig-journaux type=logs \
retention-days=14 region=fr-par -o json)
$ MET_URL=$(jq -r .url <<< "$MET"); LOG_URL=$(jq -r .url <<< "$LOG")
$ echo "$MET_URL $LOG_URL"
type:metrics,logsoutraces.retention-days: 31 jours de métriques sont gratuits ; 14 jours de journaux dépassent la durée gratuite de 7 jours, un choix délibéré : un incident d'un vendredi soir s'analyse souvent le lundi suivant, et une semaine ne suffit pas pour comparer avec la semaine d'avant.- Le champ
urldonne l'adresse de base de la source. Les adresses d'envoi s'en déduisent :/api/v1/pushpour l'écriture distante Prometheus,/loki/api/v1/pushpour Loki.
3. Un jeton qui ne sait qu'écrire
$ scw cockpit token create name=sig-alloy \
token-scopes.0=write_only_metrics token-scopes.1=write_only_logs \
region=fr-par -o json > .tmp/jeton-alloy.json
$ chmod 600 .tmp/jeton-alloy.json
Le champ secret_key de la réponse est le jeton ; il ne sera plus affiché. Rangez-le dans Secret Manager (leçon Secret Manager), d'où les instances le liront au démarrage, puis supprimez le fichier local. Ne l'écrivez pas dans les données utilisateur de cloud-init, lisibles pendant toute la vie de l'instance.
4. Instrumenter Signalements
Les métriques d'infrastructure disent qu'une instance est chargée ; elles ne disent pas que la route POST /signalements renvoie des erreurs 500 depuis dix minutes. Pour cela, l'application doit compter elle-même ce qu'elle fait. La bibliothèque officielle de Prometheus pour Python, prometheus_client, s'en charge.
Une difficulté propre à gunicorn : Signalements tourne avec plusieurs processus (workers). Chacun a sa mémoire, donc ses propres compteurs ; une requête sur /metrics ne verrait que ceux du processus qui la reçoit. La bibliothèque prévoit un mode multiprocessus : chaque processus écrit ses valeurs dans des fichiers d'un répertoire désigné par la variable PROMETHEUS_MULTIPROC_DIR, et /metrics les agrège. Le module suivant, metriques.py, applique ce mode :
"""Métriques Prometheus de Signalements, compatibles avec plusieurs workers gunicorn."""
import time
from flask import Flask, Response, g, request
from prometheus_client import (CONTENT_TYPE_LATEST, CollectorRegistry, Counter,
Histogram, generate_latest, multiprocess)
REQUETES = Counter(
"signalements_requetes_total",
"Requêtes HTTP traitées",
["methode", "route", "code"],
)
DUREE = Histogram(
"signalements_requete_duree_secondes",
"Durée de traitement des requêtes HTTP",
["route"],
buckets=(0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5),
)
def instrumenter(app: Flask) -> None:
@app.before_request
def _debut():
g.debut = time.perf_counter()
@app.after_request
def _fin(reponse):
# La règle d'URL (« /signalements/<int:ident> ») et non le chemin réel :
# un identifiant par série ferait exploser le nombre de séries.
route = request.url_rule.rule if request.url_rule else "inconnue"
DUREE.labels(route).observe(time.perf_counter() - g.get("debut", time.perf_counter()))
REQUETES.labels(request.method, route, str(reponse.status_code)).inc()
return reponse
@app.get("/metrics")
def _metrics():
registre = CollectorRegistry()
multiprocess.MultiProcessCollector(registre)
return Response(generate_latest(registre), mimetype=CONTENT_TYPE_LATEST)Dans app.py, un appel instrumenter(app) après la création de l'application suffit. Un essai local avec le client de test de Flask, après des requêtes sur /sante, deux sur /signalements/12 et /signalements/13, et une sur une adresse inconnue, produit notamment ces lignes (prometheus_client 0.26.0, Flask 3.1.3) :
signalements_requete_duree_secondes_count{route="/sante"} 1.0
signalements_requete_duree_secondes_count{route="/signalements/<int:ident>"} 2.0
signalements_requete_duree_secondes_count{route="inconnue"} 1.0
signalements_requetes_total{code="200",methode="GET",route="/sante"} 1.0
signalements_requetes_total{code="200",methode="GET",route="/signalements/<int:ident>"} 2.0
signalements_requetes_total{code="404",methode="GET",route="inconnue"} 1.0Les deux consultations de signalements différents tombent dans la même série : c'est l'effet du commentaire du code, et c'est ce qui garde la facture sous contrôle (voir Sous le capot).
Le mode multiprocessus demande deux réglages en plus, d'après la documentation de la bibliothèque :
- le répertoire
PROMETHEUS_MULTIPROC_DIRdoit être vide au démarrage. Dans le conteneur, un montage en mémoire recréé à chaque lancement s'en charge :--mount type=tmpfs,destination=/run/prometheuset-e PROMETHEUS_MULTIPROC_DIR=/run/prometheusdans la commandedocker runde l'unité systemd ; - gunicorn doit signaler la fin d'un processus, pour que ses jauges disparaissent. Un fichier
gunicorn.conf.py, chargé avec l'option-c, contient :
from prometheus_client import multiprocess
def child_exit(server, worker):
multiprocess.mark_process_dead(worker.pid)Warning
/metrics est servi sur le même port que l'API. Derrière le répartiteur de charge, il serait donc public, et révélerait vos routes et vos volumes à qui le demande. Bloquez ce chemin au niveau du répartiteur (une ACL sur le chemin, voir la leçon Le répartiteur de charge en profondeur), ou servez les métriques sur un port distinct que seul l'agent local interroge.
5. Collecter avec Grafana Alloy
Grafana Alloy est l'agent de collecte de Grafana Labs, qui succède à Grafana Agent ; la documentation de Scaleway l'utilise pour Cockpit. Installé sur chaque instance du groupe (par l'image ou par cloud-init, leçon 2), il fait trois choses : exposer les métriques système, interroger /metrics de l'application, lire le journal systemd. Sa configuration, /etc/alloy/config.alloy :
// Métriques système de l'instance (CPU, mémoire, disques, réseau)
prometheus.exporter.unix "noeud" {
set_collectors = ["cpu", "loadavg", "meminfo", "filesystem", "netdev"]
}
prometheus.scrape "noeud" {
targets = prometheus.exporter.unix.noeud.targets
scrape_interval = "60s"
forward_to = [prometheus.remote_write.cockpit.receiver]
}
// Métriques applicatives de Signalements, sur l'adresse privée de l'instance
prometheus.scrape "signalements" {
targets = [{"__address__" = sys.env("ADRESSE_PRIVEE") + ":8000"}]
metrics_path = "/metrics"
scrape_interval = "30s"
forward_to = [prometheus.remote_write.cockpit.receiver]
}
prometheus.remote_write "cockpit" {
endpoint {
url = sys.env("COCKPIT_METRIQUES_URL") + "/api/v1/push"
headers = { "X-TOKEN" = sys.env("COCKPIT_JETON") }
}
}
// Journaux du service signalements, lus dans journald
loki.relabel "journal" {
forward_to = []
rule {
source_labels = ["__journal__systemd_unit"]
target_label = "unit"
}
}
loki.source.journal "signalements" {
matches = "_SYSTEMD_UNIT=signalements.service"
relabel_rules = loki.relabel.journal.rules
labels = {service = "signalements"}
forward_to = [loki.write.cockpit.receiver]
}
loki.write "cockpit" {
endpoint {
url = sys.env("COCKPIT_JOURNAUX_URL") + "/loki/api/v1/push"
bearer_token = sys.env("COCKPIT_JETON")
}
}Chaque bloc suit la documentation des composants d'Alloy :
prometheus.exporter.unixembarque l'équivalent denode_exporter;set_collectorslimite ce qu'il collecte, ce qui limite ce que vous payez. La documentation de Scaleway avertit que les configurations par défaut des agents envoient souvent plus de métriques que nécessaire.prometheus.scrapeinterroge des cibles à intervalle régulier et transmet àprometheus.remote_write, qui pousse vers Cockpit avec l'en-têteX-TOKEN, comme dans l'exemple de Scaleway.loki.source.journallit le journal systemd, filtré parmatchessur l'unité du service ;loki.writepousse vers Loki, authentifié par jeton porteur, la forme que la documentation de Scaleway indique pour l'API Loki.- Les valeurs sensibles ou propres à l'instance arrivent par des variables d'environnement (
sys.env), fournies au servicealloypar un fichier d'environnement que l'instance remplit au démarrage depuis Secret Manager.
Après démarrage (systemctl enable --now alloy), les métriques signalements_requetes_total apparaissent dans la source sig-metriques, les journaux dans sig-journaux. Dans l'Explore de Grafana, la requête LogQL {service="signalements"} |= "ERROR" montre les erreurs de toutes les instances, y compris de celles qui n'existent plus.
6. Compter avant de payer
Avant de déployer sur tout le groupe, estimez. Pour une instance : environ 300 séries pour node avec ces collecteurs (l'ordre de grandeur se vérifie en comptant les lignes de la sortie de l'exportateur), et pour Signalements une dizaine de routes, trois méthodes et quelques codes, plus les douze séries par route de l'histogramme (dix seaux, neuf seuils plus +Inf, puis _sum et _count ; l'essai local montre qu'en mode multiprocessus la bibliothèque n'exporte pas de série _created). Disons 500 séries par instance.
- Échantillons par mois : 500 séries × 2 points par minute (intervalle de 30 secondes pour l'application, 60 pour le système : prenons 2 en moyenne haute) × 60 × 24 × 30, soit environ 43 millions d'échantillons par instance.
- Coût d'ingestion : 43 × 0,15 € = environ 6,50 € par instance et par mois, au tarif du 5 octobre 2026.
Avec quatre instances en moyenne, une trentaine d'euros par mois. Le calcul montre où sont les leviers : l'intervalle de collecte (passer de 30 à 60 secondes divise par deux), le nombre de collecteurs, et surtout le nombre de séries.
7. Les alertes
Activez le gestionnaire d'alertes et déclarez un contact :
$ scw cockpit alert-manager enable region=fr-par
$ scw cockpit contact-point create email.to=astreinte@lyneko.example \
send-resolved-notifications=true region=fr-par
$ scw cockpit test-alert trigger region=fr-par
La dernière commande envoie une alerte de test : vérifiez qu'elle arrive. Activez ensuite, dans la console (Cockpit, onglet Alerts), les alertes préconfigurées des produits de Signalements, en particulier celles de la base et du répartiteur.
Enfin, une règle à vous, sur un symptôme vu par l'utilisateur : la part des réponses en erreur 5xx. Le fichier regles-signalements.yaml :
name: signalements
interval: 1m
rules:
- alert: SignalementsErreurs5xx
expr: |
sum(rate(signalements_requetes_total{code=~"5.."}[5m]))
/ sum(rate(signalements_requetes_total[5m])) > 0.05
for: 10m
labels:
severity: critical
annotations:
summary: "Plus de 5 % de réponses en erreur 5xx depuis 10 minutes"Il s'envoie à l'API de règles de Mimir, avec une clé d'API Scaleway (et non un jeton Cockpit) dont la politique contient ObservabilityFullAccess, comme le décrit la documentation de Scaleway :
$ curl -sS -X POST -H "X-Auth-Token: $SCW_SECRET_KEY" \
-H "Content-Type: application/yaml" \
--data-binary @regles-signalements.yaml \
"$MET_URL/prometheus/config/v1/rules/production"
production est l'espace de noms des règles, au choix. for: 10m évite d'alerter sur une poignée d'erreurs passagères : l'alerte ne part que si la condition tient dix minutes. Le cours Concevoir une alerte utile reviendra sur ces choix.
Sous le capot
Le modèle de données. Une série temporelle est identifiée par un nom de métrique et un ensemble d'étiquettes : signalements_requetes_total{methode="GET",route="/sante",code="200"} est une série, la même avec code="500" en est une autre. Mimir stocke chaque série séparément. Le nombre de séries d'une métrique est donc le produit des nombres de valeurs de ses étiquettes : 10 routes × 3 méthodes × 6 codes = 180 séries. Si l'on avait mis le chemin réel (/signalements/12, /signalements/13...) au lieu de la règle d'URL, chaque signalement consulté créerait de nouvelles séries : des dizaines de milliers en une journée, jusqu'à la limite d'un million par source, et une facture qui suit. C'est l'explosion de cardinalité, l'erreur la plus coûteuse de l'instrumentation, et la raison du commentaire dans le code.
Compteurs et taux. Un compteur ne fait que croître (et repart de zéro quand le processus redémarre). Sa valeur brute ne dit rien ; c'est sa vitesse qui compte, que la fonction PromQL rate() calcule sur une fenêtre en tenant compte des remises à zéro. D'où l'expression de l'alerte : le taux des 5xx divisé par le taux total. Un histogramme, lui, range chaque durée observée dans des seaux cumulatifs (le="0.25" compte les requêtes de 250 ms ou moins) ; la fonction histogram_quantile() en tire une estimation des percentiles (la latence sous laquelle tombent 95 % des requêtes, par exemple).
Pousser plutôt qu'interroger. Prometheus, dans sa forme classique, va lui-même interroger les cibles (pull). Cockpit, service mutualisé, ne peut pas aller chercher vos métriques dans vos réseaux privés : il reçoit ce qu'on lui pousse, par le protocole d'écriture distante de Prometheus. Alloy fait les deux : il interroge localement (comme un Prometheus) et pousse à distance. C'est ce qui permet de garder /metrics invisible depuis Internet.
Pièges courants
Le chemin réel en étiquette. Voir ci-dessus : utilisez la règle d'URL, jamais le chemin, l'identifiant d'un utilisateur, une adresse IP ou un message d'erreur en valeur d'étiquette.
Un worker, une vérité. Sans mode multiprocessus, /metrics répond avec les compteurs du seul processus qui a reçu la requête : les graphiques oscillent sans raison et les totaux sont faux. Symptôme typique : un compteur qui « redescend ».
Le répertoire multiprocessus jamais vidé. Hors conteneur, si PROMETHEUS_MULTIPROC_DIR survit à un redémarrage, les fichiers des anciens processus sont relus et les compteurs reprennent des valeurs fantômes. Un tmpfs ou un répertoire d'exécution systemd (RuntimeDirectory=) règle la question.
Jeton et source dans deux régions différentes. La documentation insiste : le jeton et la source de données doivent être dans la même région. Sinon, l'envoi est refusé.
Des alertes que personne ne reçoit. Gestionnaire d'alertes non activé, contact non déclaré, ou alertes préconfigurées activées dans une autre région que celle des ressources. scw cockpit test-alert trigger dès la mise en place.
Les alertes gérées par Grafana. Créées dans l'interface de Grafana avec le gestionnaire d'alertes de Grafana, elles ne sont pas prises en charge par Cockpit : choisissez les alertes gérées par la source de données.
Tout collecter « au cas où ». L'agent par défaut, tous collecteurs actifs, avec un intervalle de 15 secondes, sur vingt instances : la facture d'ingestion dépasse celle des instances. Collectez ce qui sert à une question ou à une alerte.
Sécurité
- Les journaux contiennent des données personnelles. Une adresse, une description, une adresse IP de client : dès qu'ils partent dans Cockpit, ils y sont conservés selon la durée choisie, et le RGPD s'applique (minimisation, durée limitée). Ne journalisez ni mot de passe, ni jeton, ni contenu de formulaire complet ; préférez des identifiants.
- Des jetons à portée minimale. Écriture seule pour les agents, lecture seule pour un outil de tableau de bord externe, règles et gestionnaire d'alertes pour l'automate de déploiement des alertes. Un jeton d'agent volé ne permet alors que d'injecter des données, pas de lire les vôtres.
/metricsn'est pas public. Il renseigne un attaquant sur les routes, les volumes et parfois les versions. Bloquez-le au répartiteur.- L'accès à Grafana suit l'IAM. Depuis la bascule vers l'authentification IAM, révoquer un membre de l'organisation révoque aussi son accès aux tableaux de bord, et le second facteur s'applique. Vérifiez qu'aucun ancien compte Grafana ne subsiste dans vos procédures.
- Les données exportées sortent de votre contrôle. Les exports de données (en bêta au 5 octobre 2026, vers Datadog ou un point d'accès OTLP) envoient métriques et journaux vers un tiers : c'est un transfert à documenter, au sens du cours Cloud souverain.
En production
- Les traces. Cockpit accepte les traces au format OpenTelemetry, par HTTP uniquement. Instrumenter Signalements avec OpenTelemetry montrerait le temps passé dans la base, dans Redis et dans l'appel à l'Object Storage pour chaque requête lente. Le cours OpenTelemetry et les traces distribuées le fera ; Cockpit accepte aussi métriques et journaux par OTLP, ce qui permet de n'avoir qu'un seul agent.
- Les règles d'enregistrement précalculent les requêtes lourdes (le taux d'erreur par route, par exemple) et allègent tableaux de bord et alertes.
- La conservation longue se paie : pour garder un an de métriques à des fins de capacité, réduisez d'abord la résolution (règles d'enregistrement agrégées) plutôt que de tout conserver.
- Les tableaux de bord sont du code. Exportés en JSON depuis Grafana et versionnés, ils se relisent et se recréent ; un tableau de bord modifié à la main en pleine crise et jamais sauvegardé est perdu au prochain incident.
- Chez Lyneko, les applications tournent sur Kapsule, que la page d'intégration de Cockpit donne comme intégré pour les métriques et les journaux ; la documentation de Scaleway décrit aussi l'envoi des métriques et journaux des charges de travail d'un cluster.
Exercices
1. Lire la page d'intégration (niveau 200). Pour chacun des besoins suivants, dites si Cockpit le couvre sans agent : (a) la latence de la base sig-db ; (b) les messages d'erreur Python de l'application ; (c) le nombre de requêtes HTTP reçues par le répartiteur ; (d) l'occupation mémoire réelle des processus gunicorn ; (e) les appels à l'API IAM.
Solution
(a) Oui : métriques de Managed Database for PostgreSQL. (b) Non : les instances ne fournissent pas de journaux ; il faut un agent (Alloy et loki.source.journal). (c) Oui : métriques du Load Balancer. (d) Non : les métriques d'instance sont vues de l'hyperviseur ; la mémoire des processus demande l'exportateur système ou l'instrumentation de l'application. (e) Non : IAM n'est pas intégré à Cockpit ; les appels sont dans Audit Trail (leçon 15).
2. Une cardinalité dangereuse (niveau 200). Un développeur ajoute une étiquette commune (les 95 communes de la métropole) et une étiquette utilisateur (12 000 agents municipaux) au compteur signalements_requetes_total, qui a déjà 10 routes, 3 méthodes et 6 codes possibles. Calculez le nombre de séries potentielles. Que se passe-t-il, et que proposez-vous ?
Solution
180 × 95 × 12 000 = 205 200 000 séries potentielles. Toutes ne seront pas observées, mais même une fraction dépasse la limite d'un million de séries par source de données : Cockpit refusera des échantillons, et l'ingestion explosera avant. Retirer l'étiquette utilisateur (une donnée d'identification, qui n'a rien à faire dans une métrique, et qui relève du RGPD) ; garder éventuellement commune sur une métrique dédiée, sans methode ni route (95 séries), si le besoin est réel. Le détail par utilisateur relève des journaux, avec une conservation limitée.
3. Le budget d'une collecte (niveau 200). Estimez le coût mensuel d'ingestion de la configuration de la leçon si le groupe d'instances passe à dix instances en permanence, puis proposez deux réglages qui le divisent au moins par deux sans perdre l'alerte sur les erreurs 5xx.
Solution
Environ 10 × 6,50 € = 65 € par mois au tarif du 5 octobre 2026. Réglages : passer l'intervalle de collecte de l'application à 60 secondes (la fenêtre de 5 minutes de l'alerte garde cinq points) ; réduire les collecteurs de l'exportateur système à ceux qui servent (le processeur et la mémoire sont aussi fournis gratuitement par l'intégration des instances) ; supprimer des seaux de l'histogramme. Les deux premiers suffisent à diviser par deux environ ; l'alerte, qui ne repose que sur le compteur, n'est pas touchée.
Récapitulatif
- Cockpit est le service d'observabilité managé de Scaleway : Mimir pour les métriques, Loki pour les journaux, Tempo pour les traces, Grafana pour voir, un Cockpit par projet.
- Les produits intégrés envoient leurs métriques (et souvent leurs journaux) gratuitement ; les instances ne fournissent pas de journaux : il faut un agent.
- Les sources personnalisées reçoivent vos données ; les jetons sont régionaux et limités par portée ; l'accès humain à Grafana passe par l'IAM depuis novembre 2025.
- La conservation par défaut (31 jours pour les métriques, 7 pour les journaux) est gratuite ; l'ingestion personnalisée se paie à l'échantillon et au gigaoctet.
- Avec plusieurs workers gunicorn,
prometheus_clientexige le mode multiprocessus ; les étiquettes portent des valeurs bornées, jamais un chemin ou un identifiant. - Grafana Alloy interroge localement et pousse vers Cockpit par écriture distante et par l'API Loki.
- Les alertes demandent un gestionnaire activé, des contacts, et des règles sur des symptômes vus par l'utilisateur.
Pour aller plus loin
- La page des limites de Cockpit, à relire avant de dimensionner une collecte.
- Les bonnes pratiques de nommage et d'étiquetage de Prometheus.
- La documentation du mode multiprocessus de
prometheus_client, pour ses limites (pas de collecteurs personnalisés, modes des jauges). - La leçon suivante, Sécuriser et auditer un compte, qui s'appuie sur Audit Trail, la source d'information que Cockpit n'a pas.
Sources
- Scaleway, Cockpit : concepts (sources de données, jetons, conservation, alertes)
- Scaleway, Cockpit : tarification
- Scaleway, Cockpit : capacités et limites
- Scaleway, Cockpit : intégration des produits
- Scaleway, Cockpit : authentification à Grafana par IAM
- Scaleway, envoyer des métriques avec Grafana Alloy, et par OTLP
- Scaleway, créer des alertes par programme (API Mimir et Loki)
- Prometheus, client Python : mode multiprocessus
- Prometheus, bonnes pratiques de nommage et d'étiquetage
- Grafana Alloy, composants loki.write et loki.source.journal
- Grafana Mimir, API HTTP : règles
- scaleway/scaleway-cli, commandes cockpit (v2.62.0)