Partie 17 : Dashboard Pi-hole — DNS et blocage dans Grafana

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

kubectl_pihole.jpeg

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.

Dashboard_pihole.jpeg

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