Partie 17 : Dashboard Pi-hole — DNS et blocage dans Grafana
Mars 2026
Le besoin
Pi-hole tourne depuis un moment sur le cluster K3s, il bloque les pubs et gère le DHCP de tout le réseau. Mais on n'a aucune visibilité : combien de requêtes DNS par jour ? Quels domaines sont bloqués ? Quels clients font le plus de requêtes ?
On va brancher pihole-exporter comme sidecar, et créer un dashboard Grafana avec les métriques clés.
Architecture retenue
Pi-hole tourne avec hostNetwork: true sur rpi4-worker (IP fixe 192.168.1.50, nécessaire pour le DHCP). L'approche sidecar est naturelle : le container pihole-exporter tourne dans le même pod, se connecte à Pi-hole via localhost:5080 et expose les métriques sur le port 9617.
┌─────────────────────────────────────────────────┐
│ pihole pod │
│ ┌──────────────┐ ┌───────────────────────┐ │
│ │ Pi-hole │ │ pihole-exporter │ │
│ │ port: 5080 │◀────│ localhost:5080 │ │
│ │ (web + API) │ │ → metrics :9617 │ │
│ └──────────────┘ └───────────────────────┘ │
│ hostNetwork: true (IP = 192.168.1.50) │
└─────────────────────────────────────────────────┘
↑
ServiceMonitor
Prometheus scrape :9617

Implémentation
1. Sidecar dans le Deployment
# helm-charts/pihole/templates/deployment.yaml
- name: pihole-exporter
image: ekofr/pihole-exporter:latest
env:
- name: PIHOLE_PROTOCOL
value: "http"
- name: PIHOLE_HOSTNAME
value: "127.0.0.1"
- name: PIHOLE_PORT
value: "5080"
- name: PIHOLE_PASSWORD # mot de passe admin Pi-hole
valueFrom:
secretKeyRef:
name: pihole-credentials
key: webpassword
ports:
- name: metrics
containerPort: 9617
2. Service dédié aux métriques
# helm-charts/pihole/templates/service.yaml
apiVersion: v1
kind: Service
metadata:
name: pihole-metrics
labels:
app.kubernetes.io/name: pihole
spec:
type: ClusterIP
selector:
app.kubernetes.io/name: pihole
ports:
- name: metrics
port: 9617
targetPort: metrics
3. ServiceMonitor dans le chart monitoring
# helm-charts/monitoring/templates/servicemonitor-pihole.yaml
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: pihole
namespace: monitoring
labels:
release: monitoring
spec:
namespaceSelector:
matchNames:
- pihole
selector:
matchLabels:
app.kubernetes.io/name: pihole
endpoints:
- port: metrics
interval: 30s
path: /metrics
4. Dashboard Grafana
Provisionné via ConfigMap avec le label grafana_dashboard: "1", comme les autres dashboards du projet. Contient :
- Vue d'ensemble : requêtes DNS today, publicités bloquées, % blocage, clients actifs, domaines en blocklist, statut Pi-hole
- Trafic dans le temps : courbe requêtes / bloquées sur la fenêtre sélectionnée
- Top domaines : tableau des 10 domaines les plus demandés et des 10 plus bloqués
Pièges rencontrés
Pi-hole v6 et l'API
Pi-hole v6 a complètement revu son API. L'authentification se fait maintenant via :
POST /api/auth
Content-Type: application/json
{"password": "le_mot_de_passe"}
La réponse contient un sid (session token) utilisé pour les requêtes suivantes. pihole-exporter gère ça en interne, il suffit de lui passer PIHOLE_PASSWORD, et d'avoir les bonnes documentations :).
La virgule dans le mot de passe
Le mot de passe Pi-hole d'origine contenait une virgule (,). ekofr/pihole-exporter utilise les virgules comme séparateur pour supporter plusieurs instances Pi-hole. Résultat : il voyait 2 mots de passe pour 1 host → crash au démarrage.
failed to load configuration: wrong number of PIHolePassword:
must be empty, single value or one per host
Solution : changer le mot de passe Pi-hole pour un sans caractère spécial. Comme le mot de passe est géré via l'env var FTLCONF_webserver_api_password, la commande pihole setpassword ne fonctionne pas — il faut mettre à jour le SealedSecret pihole-credentials et laisser ArgoCD redéployer.
Les app passwords Pi-hole v6
Pi-hole v6 propose des "Application passwords" (Settings → API → App passwords). En théorie c'est la bonne approche pour l'accès API. En pratique, l'authentification /api/auth échouait avec ces tokens même correctement générés et stockés. J'ai finalement opté pour le mot de passe admin directement, sans caractères spéciaux.
Résultat
pihole_ads_blocked_today 223
pihole_ads_percentage_today 0.19%
pihole_dns_queries_today 117 240
pihole_domains_being_blocked 77 526
pihole_clients_ever_seen 19
88% des requêtes sont servies depuis le cache local de Pi-hole — ce qui montre l'efficacité du DNS caching sur un réseau domestique.

Fichiers modifiés
| Fichier | Modification |
|---|---|
helm-charts/pihole/templates/deployment.yaml |
Ajout sidecar pihole-exporter |
helm-charts/pihole/templates/service.yaml |
Ajout service pihole-metrics :9617 |
helm-charts/pihole/values.yaml |
Section exporter (image + ressources) |
helm-charts/pihole/templates/sealed-secret.yaml |
Nouveau mot de passe sans virgule |
helm-charts/monitoring/templates/servicemonitor-pihole.yaml |
ServiceMonitor cross-namespace |
helm-charts/monitoring/templates/dashboard-pihole.yaml |
Dashboard Grafana Pi-hole DNS |