Grafana Grafana

Provisionner les tableaux de bord depuis des fichiers JSON

Chargez les tableaux de bord depuis le disque, associez les dossiers aux répertoires et créez-les sans perdre vos modifications.

12 min Intermédiaire

Les tableaux de bord sont des documents JSON, ce qui les rend faciles à stocker dans Git. Un fournisseur de tableaux de bord (dashboard provider) indique à Grafana un dossier à surveiller ; Grafana charge alors chaque fichier JSON qu’il y trouve, puis continue de vérifier les changements. Ce guide couvre le fichier du fournisseur, l’association des dossiers, le JSON du tableau de bord lui-même, et un workflow pour créer des tableaux de bord sans se retrouver avec des modifications présentes uniquement dans l’interface.

Le fichier du fournisseur

provisioning/dashboards/providers.yaml :

apiVersion: 1

providers:
  - name: default
    orgId: 1
    type: file
    disableDeletion: false
    updateIntervalSeconds: 30
    allowUiUpdates: false
    options:
      path: /var/lib/grafana/dashboards
      foldersFromFilesStructure: true

Ce que fait chaque champ :

  • name est obligatoire et doit être unique parmi les fournisseurs.
  • options.path est le répertoire que Grafana analyse à la recherche de fichiers JSON. Il doit exister à l’intérieur du conteneur.
  • updateIntervalSeconds est la fréquence à laquelle Grafana réanalyse le chemin. Tous les tableaux de bord sont chargés au démarrage, et les changements sont pris en compte ensuite sans redémarrage.
  • allowUiUpdates : à false, un tableau de bord provisionné ne peut pas être enregistré depuis l’interface, ce qui garde Git faisant autorité. À true, les enregistrements depuis l’interface sont conservés dans la base de données jusqu’à ce que le fichier source change, moment où le fichier les écrase.
  • disableDeletion : à true, supprimer un fichier ne supprime pas son tableau de bord dans Grafana. Laissez à false si Git doit être la vérité.
  • folder ou folderUid placent tous les tableaux de bord dans un seul dossier nommé. Sans eux, les tableaux de bord vont à la racine.
  • foldersFromFilesStructure: true associe les sous-répertoires de path à des dossiers Grafana. Laissez folder et folderUid vides lorsque vous l’utilisez. Les dossiers imbriqués ne sont pas pris en charge : un seul niveau de sous-répertoire est possible.

Organiser le dépôt par dossier

Avec foldersFromFilesStructure: true, cette arborescence :

dashboards/
├── infrastructure/
│   ├── node-exporter.json
│   └── kubernetes.json
└── applications/
    └── webapp.json

crée deux dossiers Grafana, infrastructure et applications, contenant les tableaux de bord. Utilisez plutôt des fournisseurs distincts si vous avez besoin de paramètres différents par groupe, par exemple un fournisseur avec allowUiUpdates: true pour une zone « brouillon ».

L’essentiel du JSON d’un tableau de bord

Un fichier provisionné doit contenir le modèle du tableau de bord lui-même, avec uid et title au premier niveau. Ne l’enveloppez pas dans l’enveloppe {"dashboard": {...}, "overwrite": true} utilisée par l’API HTTP, cause fréquente de l’erreur « Dashboard title cannot be empty ».

{
  "uid": "webapp-overview",
  "title": "Webapp Overview",
  "tags": ["webapp", "provisioned"],
  "schemaVersion": 39,
  "version": 1,
  "refresh": "30s",
  "time": { "from": "now-6h", "to": "now" },
  "templating": {
    "list": [
      {
        "name": "namespace",
        "type": "query",
        "datasource": { "type": "prometheus", "uid": "prometheus" },
        "query": "label_values(kube_pod_info, namespace)"
      }
    ]
  },
  "panels": [
    {
      "id": 1,
      "type": "timeseries",
      "title": "Request rate",
      "gridPos": { "h": 8, "w": 12, "x": 0, "y": 0 },
      "datasource": { "type": "prometheus", "uid": "prometheus" },
      "targets": [
        {
          "refId": "A",
          "expr": "sum(rate(http_requests_total{namespace=\"$namespace\"}[5m]))",
          "datasource": { "type": "prometheus", "uid": "prometheus" }
        }
      ]
    }
  ]
}

Bonnes pratiques pour des tableaux de bord qui se comportent bien en tant que code :

  • Définissez un uid stable. Grafana met à jour le tableau de bord portant cet UID à chaque chargement. Évitez de réutiliser un UID dans plusieurs fichiers, ou le même titre deux fois dans un même dossier.
  • Omettez l’id numérique. Il est attribué par la base de données et diffère d’une instance à l’autre.
  • Référencez les sources de données par UID, en correspondance avec l’uid que vous avez provisionné ({"type": "prometheus", "uid": "prometheus"}). Les tableaux de bord exportés pour le partage peuvent contenir des espaces réservés comme ${DS_PROMETHEUS}, que vous devez remplacer par le vrai UID, ou par une variable de modèle de source de données.
  • L’interpolation de variables d’environnement ne fonctionne pas dans le JSON des tableaux de bord. Utilisez les variables de modèle du tableau de bord pour les différences par environnement.
  • Grafana 13 stocke les tableaux de bord dans un schéma plus récent en interne et migre l’ancien JSON au chargement ; les fichiers existants continuent donc de fonctionner.

Créer dans l’interface, puis rapatrier le résultat dans Git

Écrire à la main le JSON des panneaux est lent ; la plupart des équipes ébauchent donc dans l’interface puis exportent. Un workflow qui garde les fichiers comme vérité :

  1. Lancez une instance de test (la configuration compose du guide précédent) où un fournisseur a allowUiUpdates: true.
  2. Construisez ou ajustez le tableau de bord dans l’interface.
  3. Exportez-le en JSON depuis le menu de partage ou d’export du tableau de bord. Choisissez l’option d’export pour un partage externe si vous voulez que les sources de données soient remplacées par des entrées, puis définissez les vrais UID.
  4. Supprimez l’id numérique, définissez un uid stable et commitez le fichier dans le dossier du dépôt.
  5. Ouvrez une pull request. Le Grafana de production le récupère après la fusion, et allowUiUpdates: false y empêche toute divergence.

Vous pouvez aussi récupérer un tableau de bord existant via l’API :

curl -s -u admin:$GRAFANA_ADMIN_PASSWORD \
  http://localhost:3000/api/dashboards/uid/webapp-overview \
  | jq '.dashboard | del(.id)' > dashboards/applications/webapp.json

Formatez le JSON de façon cohérente (par exemple jq -S .) pour que les diffs montrent de vrais changements.

Générer des tableaux de bord depuis du code

Si de nombreux tableaux de bord partagent la même forme, générez le JSON au lieu de le copier. Le Grafana Foundation SDK (Go, TypeScript, Python, PHP, Java) construit des tableaux de bord à partir de code typé, et sa sortie est le même JSON que vous déposez dans le dossier du fournisseur. Le guide du Foundation SDK de cette série le présente.

Valider en CI

Détectez les erreurs avant qu’elles n’atteignent Grafana :

# JSON valide ?
jq empty dashboards/**/*.json
# chaque fichier a-t-il un uid et un title ?
for f in dashboards/*/*.json; do
  jq -e '.uid and .title' "$f" >/dev/null || echo "missing uid/title: $f"
done
# uid en double ?
jq -r '.uid' dashboards/*/*.json | sort | uniq -d

Appliquer et vérifier

Les changements sont pris en compte dans le délai updateIntervalSeconds. Pour forcer une réanalyse :

curl -X POST -u admin:$GRAFANA_ADMIN_PASSWORD \
  http://localhost:3000/api/admin/provisioning/dashboards/reload

curl -s -u admin:$GRAFANA_ADMIN_PASSWORD \
  "http://localhost:3000/api/search?type=dash-db" | jq '.[] | {title, uid, folderTitle}'

Si un tableau de bord n’apparaît pas, consultez les lignes de log de démarrage et de réanalyse du logger de provisionnement. Les causes habituelles sont un chemin qui n’existe pas dans le conteneur, un JSON enveloppé dans l’enveloppe de l’API, ou deux fichiers partageant un même uid.

Guides populaires