Observabilité OpenStack : Prometheus, Alertmanager et optimisation de Node Exporter
Exemples de configuration de la chaîne de supervision que nous déployons sur les plateformes OpenStack et Ceph : openstack-exporter scrapé par Prometheus, tableaux de bord provisionnés dans Grafana, alertes routées par Alertmanager, et un Node Exporter réglé pour que les interfaces virtuelles et les ponts de conteneurs cessent de polluer les tableaux de bord. La dernière section montre comment publier des métriques personnalisées depuis des scripts avec le collector textfile.
1. Scraper OpenStack et les hôtes avec Prometheus
Deux familles de métriques comptent : ce que rapportent les API OpenStack (état des services, quotas, nombre d'instances, latence API) via openstack-exporter, et ce que rapporte chaque hôte via node_exporter. Étiquetez les hôtes par rôle au moment du scrape pour que tableaux de bord et alertes distinguent un contrôleur d'un nœud de calcul ou d'un hôte OSD Ceph.
# Install Node Exporter on every OpenStack host (Debian/Ubuntu package, runs as user "prometheus")
apt-get install prometheus-node-exporter -y
# prometheus.yml (excerpt)
scrape_configs:
# openstack-exporter (default port 9180) talks to the OpenStack APIs with a clouds.yaml
- job_name: 'openstack-api'
static_configs:
- targets: ['controller-01:9180']
# Hosts, labelled by role
- job_name: 'node'
static_configs:
- targets: ['control-01:9100', 'control-02:9100', 'control-03:9100']
labels: { role: 'controller' }
- targets: ['az1-node-01:9100', 'az1-node-02:9100']
labels: { role: 'compute', az: 'AZ1' }
- targets: ['ceph-osd-01:9100', 'ceph-osd-02:9100']
labels: { role: 'ceph' }
# Ceph MGR prometheus module
- job_name: 'ceph'
static_configs:
- targets: ['ceph-mon-01:9283']
2. Provisionner les tableaux de bord Grafana en code
Les tableaux de bord ont leur place dans le contrôle de version, pas dans une instance Grafana construite à la souris. Un provider de type fichier charge les tableaux de bord JSON depuis un répertoire au démarrage ; ce répertoire est déployé par Ansible avec le reste de la plateforme. Panneaux typiques : latence API par service, échecs de création d'instances, CPU et mémoire des hyperviseurs, santé Ceph et états des PG, débit réseau par rôle.
# /etc/grafana/provisioning/dashboards/openstack.yml
apiVersion: 1
providers:
- name: 'OpenStack'
folder: 'Cloud'
type: file
disableDeletion: true
updateIntervalSeconds: 60
options:
path: /etc/grafana/provisioning/dashboards/json
3. Règles d'alerte et routage Alertmanager
Une alerte n'est utile que si quelqu'un en est responsable. Chaque règle porte un label de sévérité et de service ; Alertmanager route sur ces labels vers l'équipe qui peut agir, avec un regroupement pour éviter une notification par hôte pendant un incident.
# /etc/prometheus/rules/openstack.yml
groups:
- name: openstack-critical
rules:
- alert: OpenStackExporterDown
expr: up{job="openstack-api"} == 0
for: 5m
labels:
severity: critical
service: openstack
annotations:
summary: Prometheus cannot scrape openstack-exporter
- alert: NovaComputeServiceDown
expr: openstack_nova_agent_state{adminState="enabled"} == 0
for: 10m
labels:
severity: critical
service: nova
annotations:
summary: "nova-compute down on {{ $labels.hostname }}"
- alert: NovaAgentMetricsMissing
expr: absent(openstack_nova_agent_state)
for: 10m
labels:
severity: critical
service: nova
annotations:
summary: openstack-exporter no longer exposes Nova agent metrics
- alert: CephHealthWarning
expr: ceph_health_status{job="ceph"} != 0
for: 10m
labels:
severity: warning
service: ceph
- alert: HostRootFilesystemAlmostFull
expr: (node_filesystem_avail_bytes{mountpoint="/"} / node_filesystem_size_bytes{mountpoint="/"}) < 0.10
for: 15m
labels:
severity: warning
service: host
# /etc/alertmanager/alertmanager.yml (excerpt)
route:
receiver: 'ops-team'
group_by: ['alertname', 'service']
group_wait: 30s
group_interval: 5m
repeat_interval: 4h
routes:
- matchers: [ service="ceph" ]
receiver: 'storage-team'
continue: true
- matchers: [ severity="critical" ]
receiver: 'oncall'
receivers:
- name: 'ops-team'
slack_configs:
- api_url: 'https://hooks.slack.com/services/...'
channel: '#cloud-ops'
- name: 'oncall'
webhook_configs:
- url: 'https://incident-tool.example.org/webhook/prometheus'
- name: 'storage-team'
email_configs:
- to: 'storage@example.org'
4. Node Exporter : maîtriser la cardinalité des interfaces réseau
Les hôtes OpenStack exposent de nombreuses interfaces, mais tap*, qbr*, qvb*, qvo*, br-int et br-tun appartiennent au chemin de données Neutron. Les exclure réduit la cardinalité, mais masque aussi le trafic des workloads et des signaux utiles au diagnostic. Conservez une collecte prudente, puis filtrez les tableaux de bord courants avec des requêtes PromQL ou des variables Grafana validées pour chaque rôle de nœud.
# /etc/default/prometheus-node-exporter
ARGS='--web.listen-address=":9100" \
--collector.netdev.device-exclude="^(lo|ovs-system)$" \
--collector.netclass.ignored-devices="^(lo|ovs-system)$"'
systemctl restart prometheus-node-exporter
# Keep tap*, qbr*, qvb*, qvo*, qr-*, qg-*, ha-*, br-int, br-tun and br-ex:
# they carry instance, router, tunnel, HA or provider traffic in Neutron.
# Verify what is still exported
curl -s localhost:9100/metrics | grep '^node_network_receive_bytes_total' | cut -d'"' -f2 | sort -u
Recommandation opérationnelle
Commencez par exclure uniquement lo et le placeholder ovs-system. Examinez les séries restantes par rôle de nœud, puis placez les filtres d'affichage dans les tableaux de bord. Déployez toute exclusion côté collector sur un hôte par rôle avant l'ensemble du parc.
5. Métriques personnalisées avec le collector textfile
Node Exporter ne peut pas nativement tout collecter : les résultats de cronjobs, de scripts de sauvegarde, de vérification d'expiration de certificats ou de scripts de contrôle personnalisés ne sont pas exposés par défaut. Le collector textfile permet à n'importe quel script d'écrire des métriques dans un fichier .prom, que Node Exporter lit et transmet dans la chaîne Prometheus / Grafana comme n'importe quelle autre métrique.
# /etc/default/prometheus-node-exporter
ARGS='--web.listen-address=":9100" \
--collector.textfile.directory="/var/lib/node_exporter/custom_metrics" \
--collector.netdev.device-exclude="^(lo|ovs-system)$"'
# The Debian/Ubuntu package runs as the "prometheus" user
mkdir -p /var/lib/node_exporter/custom_metrics
chown prometheus:prometheus /var/lib/node_exporter/custom_metrics
systemctl restart prometheus-node-exporter
# /usr/local/bin/backup-with-metric.sh
#!/bin/bash
DIR=/var/lib/node_exporter/custom_metrics
/usr/local/bin/backup.sh \
&& echo "backup_last_success_timestamp $(date +%s)" > "$DIR/backup.prom.$$" \
&& mv "$DIR/backup.prom.$$" "$DIR/backup.prom"
# /etc/cron.d/backup-status (one job per line, no line continuation)
0 3 * * * root /usr/local/bin/backup-with-metric.sh
# Matching alert: no successful backup for 36 hours
# - alert: BackupStale
# expr: (time() - backup_last_success_timestamp > 36 * 3600) or absent(backup_last_success_timestamp)
# for: 1h
# labels: { severity: warning, service: backup }
Quand l'utiliser
- Suivre le succès, l'échec et la durée des cronjobs et scripts de sauvegarde
- Exposer les dates d'expiration de certificats ou des vérifications de licence et de quota
- Publier les résultats de scripts de contrôle ou de maintenance personnalisés
- Alimenter les tableaux de bord et alertes Prometheus / Grafana avec le résultat de tâches ponctuelles ou batch
Important : écrivez dans un fichier temporaire puis renommez-le (mv) de façon atomique dans le répertoire textfile, sinon Node Exporter peut lire un fichier partiellement écrit.
6. Points de vigilance
- ■openstack-exporter a besoin d'un utilisateur Keystone dédié avec des rôles en lecture seule et son propre clouds.yaml ; ne scrapez jamais avec les identifiants admin utilisés pour l'exploitation.
- ■Alertez d'abord sur les symptômes (latence API, échecs de création, PG dégradés) et ensuite sur les causes (CPU, disque) ; un CPU saturé avec des API saines est un ticket de capacité, pas une astreinte.
- ■Revoyez la regex d'exclusion après chaque changement Neutron ou Kolla : un bridge renommé réapparaît silencieusement dans les tableaux de bord, ou pire, un bond de production se retrouve filtré.
- ■Versionnez règles d'alerte et tableaux de bord avec le code de la plateforme et testez la syntaxe des règles en CI (promtool check rules) avant de déployer.
- ■Planifiez un atelier de réglage après deux à quatre semaines de trafic de production réel : les seuils choisis le premier jour sont toujours faux quelque part.