Gérer Grafana avec Terraform
Créez dossiers, sources de données, tableaux de bord, alertes, équipes et comptes de service depuis du HCL.
Le provisionnement par fichiers couvre les sources de données, les tableaux de bord et l’alerting, mais pas les utilisateurs, les équipes, les comptes de service ni les permissions. Terraform couvre tout cela, fonctionne avec n’importe quel Grafana en cours d’exécution (auto-hébergé ou Grafana Cloud) via son API, et conserve un fichier d’état pour détecter et corriger la dérive. Ce guide configure le provider et gère les ressources courantes.
Prérequis et provider
Il vous faut Terraform ou OpenTofu, un Grafana accessible, et un jeton de compte de service avec un rôle capable de gérer ce que vous déclarez (voir le guide sur l’authentification pour le créer). Gardez le jeton hors du code :
terraform {
required_providers {
grafana = {
source = "grafana/grafana"
version = ">= 2.9.0" # épinglez la version que vous avez testée
}
}
}
variable "grafana_url" {
type = string
default = "http://localhost:3000"
}
variable "grafana_token" {
type = string
sensitive = true
}
provider "grafana" {
url = var.grafana_url
auth = var.grafana_token
}
Passez le jeton via l’environnement pour qu’il n’atterrisse jamais dans un fichier :
export TF_VAR_grafana_token='glsa_...'
terraform init
Pour Grafana Cloud, vous pouvez créer le stack et son compte de service dans la même configuration. La documentation de Grafana présente un modèle à deux providers : un provider cloud qui s’authentifie avec un jeton de politique d’accès Cloud pour créer le stack (grafana_cloud_stack) et un compte de service (grafana_cloud_stack_service_account avec son jeton), puis un second provider, aliasé sur le stack, qui utilise ce jeton.
Dossiers et sources de données
resource "grafana_folder" "apps" {
title = "Applications"
}
resource "grafana_data_source" "prometheus" {
type = "prometheus"
name = "Prometheus"
uid = "prometheus"
url = "http://prometheus:9090"
is_default = true
json_data_encoded = jsonencode({
timeInterval = "15s"
})
}
resource "grafana_data_source" "postgres" {
type = "postgres"
name = "Postgres"
uid = "postgres-main"
url = "postgres.internal:5432"
username = "grafana"
json_data_encoded = jsonencode({
database = "app"
sslmode = "require"
})
secure_json_data_encoded = jsonencode({
password = var.postgres_password
})
}
Définir uid explicitement garde les tableaux de bord et les règles d’alerte portables d’un environnement à l’autre. Les secrets passés via secure_json_data_encoded sont stockés chiffrés par Grafana, mais ils sont aussi écrits dans l’état Terraform ; stockez donc l’état dans un backend chiffré et à accès contrôlé.
Tableaux de bord
resource "grafana_dashboard" "webapp" {
folder = grafana_folder.apps.uid
config_json = file("${path.module}/dashboards/webapp.json")
overwrite = true
}
Utilisez fileset pour charger tout un répertoire :
resource "grafana_dashboard" "all" {
for_each = fileset("${path.module}/dashboards", "*.json")
folder = grafana_folder.apps.uid
config_json = file("${path.module}/dashboards/${each.value}")
}
Le JSON du tableau de bord est le même fichier que celui utilisé pour le provisionnement par fichiers ; vous pouvez donc passer d’une approche à l’autre. Pour rattacher un tableau de bord à un dossier, les anciennes versions du provider référençaient l’id du dossier et les plus récentes préfèrent son uid ; consultez la documentation du provider pour la version que vous épinglez.
Alerting
Terraform dispose de ressources pour chaque partie de l’alerting :
resource "grafana_contact_point" "slack" {
name = "team-slack"
slack {
url = var.slack_webhook_url
recipient = "#alerts"
}
}
resource "grafana_notification_policy" "default" {
group_by = ["alertname", "namespace"]
contact_point = grafana_contact_point.slack.name
group_wait = "30s"
group_interval = "5m"
repeat_interval = "4h"
}
Les groupes de règles utilisent grafana_rule_group avec des blocs rule dont les entrées data reflètent le YAML de provisionnement (requête, réduction, seuil). Les mute timings et les modèles ont grafana_mute_timing et grafana_message_template. Recherchez les noms d’attributs exacts dans la documentation du provider, car les ressources d’alerting ont été révisées au fil des versions du provider.
grafana_notification_policy gère tout l’arbre des politiques, comme dans le provisionnement par fichiers ; assurez-vous donc qu’un seul outil en soit propriétaire.
Équipes, comptes de service et permissions
Ce sont les ressources que les fichiers ne peuvent pas exprimer :
resource "grafana_team" "platform" {
name = "platform"
email = "platform@example.com"
}
resource "grafana_service_account" "ci" {
name = "ci-dashboards"
role = "Editor"
}
resource "grafana_service_account_token" "ci" {
name = "ci-token"
service_account_id = grafana_service_account.ci.id
}
resource "grafana_folder_permission" "apps" {
folder_uid = grafana_folder.apps.uid
permissions {
team_id = grafana_team.platform.id
permission = "Edit"
}
}
Traitez le jeton généré comme une sortie secrète, et envoyez-le dans votre gestionnaire de secrets plutôt que de l’afficher.
Workflow
terraform fmt -check
terraform validate
terraform plan -out tfplan
terraform apply tfplan
En CI, exécutez plan sur les pull requests et apply à la fusion. Le plan montre exactement quels tableaux de bord, sources de données et alertes vont changer.
Adopter ce qui existe déjà
Si quelqu’un a construit des choses dans l’interface, importez-les dans l’état plutôt que de les recréer :
terraform import grafana_folder.apps <folder-uid>
terraform import grafana_dashboard.webapp <dashboard-uid>
terraform import grafana_data_source.prometheus <data-source-uid>
Les versions plus récentes de Terraform peuvent aussi utiliser des blocs import. Les formats d’ID d’import peuvent différer entre les versions du provider ; confirmez-les dans la documentation des ressources.
Terraform aux côtés du provisionnement par fichiers
Ne gérez pas la même ressource avec les deux. Choisissez une frontière et tenez-vous-y. Une répartition courante : provisionnement par fichiers pour les sources de données et les tableaux de bord (chargés au démarrage, sans jeton d’API) et Terraform pour les équipes, les comptes de service et les permissions. Une autre : Terraform pour tout, avec des fichiers de provisionnement limités aux paramètres du serveur.
Guides populaires
-
Opérer Grafana comme du code : vue d'ensemble Ce qui peut vivre dans des fichiers, ce qui nécessite une API, et comment les pièces s'assemblent. -
Configurer le serveur Grafana avec grafana.ini et les variables d'environnement Sachez où se trouvent les fichiers de configuration, comment les surcharges sont ordonnées et comment garder les paramètres dans Git. -
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. -
Provisionner les règles d'alerte, les points de contact et les politiques de notification Définissez toute la chaîne d'alerting en YAML pour qu'elle soit relue et versionnée comme du code. -
Déployer Grafana sur Kubernetes avec Helm et des valeurs de provisionnement Exécutez Grafana depuis un chart Helm où sources de données, tableaux de bord et paramètres proviennent tous de fichiers de valeurs. -
Recharger, vérifier et dépanner le provisionnement en ligne de commande Découvrez ce que Grafana a chargé, rechargez sans redémarrer et corrigez les erreurs de provisionnement habituelles.