1. Discovery #
Auto-détection des cibles via Kubernetes, Consul ou fichiers statiques.
Trouver les cibles automatiquement #
Disponible dans : ✓ OSS ✓ Enterprise ✓ Cloud
Dans un environnement moderne, les cibles apparaissent et disparaissent sans prévenir. Plutôt que de lister des adresses, on confie cette tâche aux composants discovery.*, qui publient une liste de cibles dans targets.
| Composant | Source |
|---|---|
discovery.kubernetes | Pods, services, nœuds… par l’API Kubernetes |
discovery.docker | Conteneurs du démon Docker |
discovery.file | Fichiers JSON ou YAML maintenus par un autre outil |
discovery.http | Une API qui renvoie les cibles |
discovery.dns | Enregistrements DNS |
discovery.process | Processus de la machine |
Qu'est-ce qu'une cible ? #
Une cible est un simple objet d'étiquettes. __address__ donne l'adresse. Les étiquettes commençant par __ sont internes : elles servent au relabeling, puis disparaissent avant le stockage. Vous pouvez les lire dans l'interface, sur la page du composant.
Exemple avec un fichier #
Une équipe décrit ses cibles dans un fichier, sans toucher à la configuration d'Alloy :
[
{
"targets": ["app-1:8080", "app-2:8080"],
"labels": { "equipe": "plateforme", "env": "prod" }
}
]discovery.file "applis" {
files = ["/etc/alloy/cibles/*.json"]
refresh_interval = "30s"
}
discovery.relabel "applis" {
targets = discovery.file.applis.targets
rule {
source_labels = ["env"]
regex = "dev"
action = "drop"
}
rule {
target_label = "cluster"
replacement = "paris"
}
}Résultat observé dans l'interface d'Alloy, pour chaque cible : __address__, env=lab, equipe=plateforme et cluster=paris. Les cibles de dev sont écartées.
action = "drop"écarte ce qui correspond,"keep"ne garde que cela. Une règle sansactionremplace : elle écritreplacementdanstarget_label.
Exemple sur Kubernetes #
On ne garde que les pods annotés, et on transforme les métadonnées internes en étiquettes durables :
discovery.kubernetes "pods" {
role = "pod"
}
discovery.relabel "annotes" {
targets = discovery.kubernetes.pods.targets
rule {
source_labels = ["__meta_kubernetes_pod_annotation_prometheus_io_scrape"]
regex = "true"
action = "keep"
}
rule {
source_labels = ["__meta_kubernetes_namespace"]
target_label = "namespace"
}
rule {
source_labels = ["__meta_kubernetes_pod_name"]
target_label = "pod"
}
}Piège : sans règle explicite, les étiquettes__meta_*disparaissent. Si vous vouleznamespaceetpoddans vos métriques, il faut les copier, comme ci-dessus.
2. Scraping #
Configuration du composant prometheus.scrape.
Le composant prometheus.scrape #
prometheus.scrape interroge régulièrement chaque cible et transmet les métriques à la suite du pipeline. Il fonctionne comme Prometheus, mais sans stocker quoi que ce soit.
prometheus.scrape "applis" {
targets = discovery.relabel.applis.output
scrape_interval = "30s"
scrape_timeout = "10s"
metrics_path = "/metrics"
forward_to = [prometheus.relabel.filtre.receiver]
}
discovery.relabel "applis" {
targets = []
}
prometheus.relabel "filtre" {
rule {
source_labels = ["__name__"]
regex = "go_gc_.*"
action = "drop"
}
forward_to = [prometheus.remote_write.mimir.receiver]
}
prometheus.remote_write "mimir" {
endpoint {
url = "http://mimir:9009/api/v1/push"
}
}| Argument | Rôle | Défaut |
|---|---|---|
scrape_interval | Fréquence de collecte | 60s |
scrape_timeout | Délai maximal | 10s |
metrics_path | Chemin des métriques | /metrics |
job_name | Valeur de l’étiquette job | Nom du composant |
honor_labels | Garder les étiquettes de la cible en cas de conflit | false |
Attention au défaut : 60 secondes, contre 15 dans de nombreuses configurations Prometheus. Si vos courbes paraissent moins précises après une migration, regardez d'abord ce réglage.
Deux niveaux de filtrage #
| Composant | Agit sur | Quand | Exemple |
|---|---|---|---|
discovery.relabel | Les cibles | Avant la collecte | Ignorer les pods de dev |
prometheus.relabel | Les métriques | Après la collecte | Retirer go_gc_.* |
Ne pas collecter une cible économise bien plus que de filtrer ses métriques ensuite : filtrez le plus tôt possible.
Collecter le système sans node_exporter #
Alloy embarque des exportateurs. prometheus.exporter.unix remplace le node_exporter, et publie ses cibles comme n'importe quel composant de découverte :
prometheus.exporter.unix "hote" {
enable_collectors = ["cpu", "meminfo", "diskstats", "filesystem", "netdev"]
}
prometheus.scrape "hote" {
targets = prometheus.exporter.unix.hote.targets
forward_to = [prometheus.remote_write.mimir.receiver]
}
prometheus.remote_write "mimir" {
endpoint {
url = "http://mimir:9009/api/v1/push"
}
}Vérifier la collecte #
Dans l'interface, la page du composant prometheus.scrape indique pour chaque cible son URL, son état (up ou down) et sa dernière erreur. La métrique prometheus_scrape_targets_gauge compte les cibles. Une cible down n'empêche pas le composant d'être healthy : surveillez aussi la série up.
3. Remote Write #
Envoi des données vers Grafana Cloud ou une instance locale.
Envoyer vers Mimir, Prometheus ou Grafana Cloud #
prometheus.remote_write envoie les métriques vers tout backend compatible. Il écrit d'abord dans un journal sur disque (WAL), puis expédie depuis ce journal : une panne du backend ne fait donc pas perdre les données immédiatement.
prometheus.remote_write "mimir" {
external_labels = { region = "eu-west" }
endpoint {
url = "https://mimir.example.com/api/v1/push"
basic_auth {
username = sys.env("MIMIR_USER")
password = sys.env("MIMIR_PASSWORD")
}
queue_config {
capacity = 10000
max_shards = 10
max_samples_per_send = 2000
}
write_relabel_config {
source_labels = ["__name__"]
regex = "up|node_.*"
action = "keep"
}
}
wal {
truncate_frequency = "2h"
max_keepalive_time = "8h"
}
}Les réglages utiles #
| Réglage | Rôle | Défaut |
|---|---|---|
external_labels | Étiquettes ajoutées à tout l’envoi | – |
queue_config.capacity | Échantillons en attente par shard | 10000 |
queue_config.max_shards | Envois simultanés au maximum | 50 |
queue_config.max_samples_per_send | Taille d’un envoi | 2000 |
wal.truncate_frequency | Fréquence de nettoyage du journal | 2h |
wal.max_keepalive_time | Conservation maximale, faute d’envoi | 8h |
En cas de panne : les données sont conservées environ 8 heures par défaut, et le disque grossit pendant ce temps. Prévoyez l'espace pour --storage.path.Filtrer par destination #
write_relabel_config filtre pour un seul backend. Nous l'avons mesuré en envoyant les mêmes données vers deux destinations : celle qui ne gardait que up et alloy_build_info a reçu 8 échantillons, l'autre 1765. C'est le moyen le plus simple de réduire une facture de stockage.
Superviser l'envoi #
# Échantillons qui n'arrivent pas à partir (à alerter)
rate(prometheus_remote_storage_samples_failed_total[5m]) > 0
# File d'attente vers le backend
prometheus_remote_storage_samples_pending
# Cibles collectées
prometheus_scrape_targets_gaugeBonne pratique : mettez les mots de passe dans l'environnement ou un fichier (voir Gestion des secrets), et rendez --storage.path persistant : sans cela, le WAL disparaît au redémarrage du conteneur.4. Interopérabilité OTLP #
Recevoir et transformer des métriques OpenTelemetry.
Le pont entre Prometheus et OTLP #
Alloy brille par sa capacité à unifier les écosystèmes. Avec les composants otelcol, Alloy peut agir comme un collecteur OpenTelemetry, recevant des métriques au format OTLP envoyées directement par vos applications instrumentées, les convertir à la volée, et les intégrer dans votre pipeline d'expédition Prometheus existant.
