node_exporter
est un exporteur de métriques au format prometheus, focalisé sur la
partie matériel/OS.
Mais il est possible de rajouter des métriques perso. Pour cela, Il faut
utiliser un textfile collector
:
- ajouter au lancement de
node_exporter
l’option
--collector.textfile.directory=
pour positionner le répertoire qui
va abriter les fichiers de métrique - créer par un script un fichier
.prom
contenant des métriques
prometheus - assurer la mise à jour de ce fichier
Exemple avec la validité d’un certificat
Le serveur dns0.math.cnrs.fr
utilise un certificat pour le chiffrement
SSL des communications avec les autres serveurs dns de notre
infrastructure.
Le script cert-validity
donne pour un certificat le nombre de jours
avant son expiration, et avec l’option -m
génère une métrique au
format prometheus.
cert-validity /var/lib/acme/dns0.math.cnrs.fr/full.pem
34
cert-validity --metrics /var/lib/acme/dns0.math.cnrs.fr/full.pem
# HELP ssl_certificate_expiry_days Days until SSL certificate expires
# TYPE ssl_certificate_expiry_days gauge
ssl_certificate_expiry_days{cert_name="dns0.math.cnrs.fr"} 34
Dans la métrique, on rajoute le nom du certificat, et donc ici du
serveur.
# cert-validity cert-path
# gives validity in days
# -m/--metrics : outputs metric
#
# error 1 number of arguments different of 1
# error 2 if file missing or not found
# error 3 if openssl cannot
# Variables
METRICS_MODE=false
CERT_PATH=""
# Parser les arguments
while [[ $# -gt 0 ]]; do
case $1 in
-m|--metrics)
METRICS_MODE=true
shift
;;
-*)
echo "Error: Unknown option $1" >&2
exit 1
;;
*)
if [ -z "$1" ]; then
echo "Error: Expected exactly 1 argument (certificate path)" >&2
exit 1
fi
CERT_PATH="$1"
shift
;;
esac
done
# Vérifier si le fichier existe
if [ ! -f "$CERT_PATH" ]; then
echo "Error: Certificate file not found: $CERT_PATH" >&2
exit 2
fi
# Extraire la date d'expiration avec openssl
EXPIRY_DATE=$(openssl x509 -in "$CERT_PATH" -noout -enddate 2>/dev/null | cut -d= -f2)
# Vérifier si openssl a réussi
if [ $? -ne 0 ] || [ -z "$EXPIRY_DATE" ]; then
echo "Error: Cannot parse certificate with openssl" >&2
exit 3
fi
# Convertir en timestamp Unix
EXPIRY_TIMESTAMP=$(date -d "$EXPIRY_DATE" +%s 2>/dev/null)
# Vérifier si la conversion de date a réussi
if [ $? -ne 0 ]; then
echo "Error: Cannot parse expiry date" >&2
exit 3
fi
CURRENT_TIMESTAMP=$(date +%s)
# Calculer les jours restants
DAYS_REMAINING=$(( (EXPIRY_TIMESTAMP - CURRENT_TIMESTAMP) / 86400 ))
# Output according to mode
if [ "$METRICS_MODE" = true ]; then
# Extract certificate name (Common Name)
CERT_NAME=$(openssl x509 -in "$CERT_PATH" -noout -subject 2>/dev/null | sed -e 's/.*CN *= *\(.*\)/\1/')
# If no CN found, use filename
if [ -z "$CERT_NAME" ]; then
CERT_NAME=$(basename "$CERT_PATH" .crt)
fi
# Generate Prometheus metric
echo "# HELP ssl_certificate_expiry_days Days until SSL certificate expires"
echo "# TYPE ssl_certificate_expiry_days gauge"
echo "ssl_certificate_expiry_days{cert_name=\"$CERT_NAME\"} $DAYS_REMAINING"
else
echo "$DAYS_REMAINING"
fi
Lancement de node_exporter
Je décide de stocker mes métriques perso dans
/var/lib/prometheus-node-exporter
, je rajoute donc au lancement :
--collector.textfile.directory=/var/lib/prometheus-node-exporter
Pour cela, je modifie le service systemd.
Génération journalière de la métrique
Je crée un wrapper au dessus du script précédent :
#!/nix/store/5jw69mbaj5dg4l2bj58acg3gxywfszpj-bash-5.2p26/bin/bash
/nix/store/np29p1wj8q3xgq8ajf53yw6gsa5v4qz0-cert-validity/bin/cert-validity -m "/var/lib/acme/dns0.math.cnrs.fr/cert.pem" \
> /var/lib/prometheus-node-exporter/cert.prom
Le service systemd
suivant permet de lancer le wrapper :
[Unit]
Description=Daily cert-validity metrics generation
[Service]
Environment="LOCALE_ARCHIVE=/nix/store/9dij3pl4dkdxmxhasjw1pa9hzqv4rjlp-glibc-locales-2.39-52/lib/locale/locale-archive"
Environment="PATH=/nix/store/ysqx2xfzygv2rxl7nxnw48276z5ckppn-coreutils-9.5/bin:/nix/store/36rvynxwln7iz0qq3k1v3r1mna8bma8s-findutils-4.9.0/bin:/nix/store/d9xr7s3z0r8rf0ba22q6ilqv68agymdb-gnugrep-3.11/bin:/nix/store/7xwbkzfrs6flyvjyvd23m8r2mlnycinq-gnused-4.9/bin:/nix/store/d9ff8aqv537mlhpinncx6dwc7a5ky6gk-systemd-255.6/bin:/nix/store/ysqx2xfzygv2rxl7nxnw48276z5ckppn-coreutils-9.5/sbin:/nix/store/36rvynxwln7iz0qq3k1v3r1mna8bma8s-findutils-4.9.0/sbin:/nix/store/d9xr7s3z0r8rf0ba22q6ilqv68agymdb-gnugrep-3.11/sbin:/nix/store/7xwbkzfrs6flyvjyvd23m8r2mlnycinq-gnused-4.9/sbin:/nix/store/d9ff8aqv537mlhpinncx6dwc7a5ky6gk-systemd-255.6/sbin"
Environment="TZDIR=/nix/store/jyh52p2cxrjn8r4ywdv2am5pjkj1xcqa-tzdata-2024a/share/zoneinfo"
ExecStart=/nix/store/j3j50icl3jkmzxai5vm4m367wcd5x4fg-cert-metrics
Group=named
NoNewPrivileges=true
PrivateTmp=true
ProtectHome=true
ProtectSystem=strict
ReadOnlyPaths=/var/lib/acme
ReadOnlyPaths=/var/lib/acme/dns0.math.cnrs.fr
ReadOnlyPaths=/var/lib/acme/dns0.math.cnrs.fr/cert.pem
ReadWritePaths=/var/lib/prometheus-node-exporter
Type=oneshot
User=node-exporter
Remarquez particulièrement la gestion des droits d’accès au fichier du
certificat :
- l’accès au fichier de certificat est réalisé par
ReadOnlyPaths
- l’accès au répertoire pour le stockage de la métrique utilise
ReadWritePaths
User
etGroup
sont positionnés
Et enfin le timer systemd
associé permet de régénérer la métrique tous
les jours :
[Unit]
Description=Run cert-validity metric daily
[Timer]
OnCalendar=daily
Persistent=true
RandomizedDelaySec=1h
[Install]
WantedBy=timers.target
Test du bon fonctionnement
On force la génération de la métrique en démarrant manuellement le
service :
systemctl start cert-metrics
On peut ensuite vérifier que le fichier a bien été rempli :
cat /var/lib/prometheus-node-exporter/cert.prom
# HELP ssl_certificate_expiry_days Days until SSL certificate expires
# TYPE ssl_certificate_expiry_days gauge
ssl_certificate_expiry_days{cert_name="dns0.math.cnrs.fr"} 34
Et enfin interroger le prometheus local :
curl -s http://localhost:9100/metrics | grep ssl
# HELP ssl_certificate_expiry_days Days until SSL certificate expires
# TYPE ssl_certificate_expiry_days gauge
ssl_certificate_expiry_days{cert_name="dns0.math.cnrs.fr"} 34