Gestiona Grafana con Terraform
Crea carpetas, data sources, dashboards, alertas, equipos y service accounts desde HCL.
El provisioning por archivos cubre data sources, dashboards y alertas, pero no usuarios, equipos, service accounts ni permisos. Terraform los cubre todos, funciona contra cualquier Grafana en ejecución (autoalojado o Grafana Cloud) a través de su API, y mantiene un archivo de estado para poder detectar y corregir desviaciones. Esta guía configura el provider y gestiona los recursos comunes.
Requisitos previos y provider
Necesitas Terraform u OpenTofu, un Grafana accesible y un token de service account con un rol que pueda gestionar lo que declares (consulta la guía de autenticación para crear uno). Mantén el token fuera del código:
terraform {
required_providers {
grafana = {
source = "grafana/grafana"
version = ">= 2.9.0" # fija la versión que hayas probado
}
}
}
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
}
Pasa el token mediante el entorno para que nunca acabe en un archivo:
export TF_VAR_grafana_token='glsa_...'
terraform init
Para Grafana Cloud, puedes crear el stack y su service account en la misma configuración. La documentación de Grafana muestra un patrón de dos providers: un provider cloud que se autentica con un token de política de acceso de Cloud para crear el stack (grafana_cloud_stack) y una service account (grafana_cloud_stack_service_account con su token), y un segundo provider con alias hacia el stack que usa ese token.
Carpetas y data sources
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
})
}
Definir uid explícitamente mantiene los dashboards y las reglas de alertas portables entre entornos. Los secretos pasados mediante secure_json_data_encoded los almacena cifrados Grafana, pero también se escriben en el estado de Terraform, así que guarda el estado en un backend cifrado y con acceso controlado.
Dashboards
resource "grafana_dashboard" "webapp" {
folder = grafana_folder.apps.uid
config_json = file("${path.module}/dashboards/webapp.json")
overwrite = true
}
Usa fileset para cargar un directorio entero:
resource "grafana_dashboard" "all" {
for_each = fileset("${path.module}/dashboards", "*.json")
folder = grafana_folder.apps.uid
config_json = file("${path.module}/dashboards/${each.value}")
}
El JSON del dashboard es el mismo archivo que usarías para el provisioning por archivos, así que puedes moverte entre ambos enfoques. Cuando asocias un dashboard a una carpeta, las versiones antiguas del provider hacían referencia al id de la carpeta y las más nuevas prefieren su uid; consulta la documentación del provider de la versión que fijes.
Alertas
Terraform tiene recursos para cada parte del 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"
}
Los grupos de reglas usan grafana_rule_group con bloques rule cuyas entradas data reflejan el YAML de provisioning (consulta, reducción, umbral). Los mute timings y las plantillas tienen grafana_mute_timing y grafana_message_template. Busca los nombres exactos de atributos en la documentación del provider, ya que los recursos de alerting se han revisado entre versiones del provider.
grafana_notification_policy gestiona todo el árbol de políticas, como en el provisioning por archivos, así que asegúrate de que solo una herramienta sea su dueña.
Equipos, service accounts y permisos
Estos son los recursos que los archivos no pueden expresar:
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"
}
}
Trata el token generado como una salida secreta y envíalo a tu gestor de secretos en lugar de imprimirlo.
Flujo de trabajo
terraform fmt -check
terraform validate
terraform plan -out tfplan
terraform apply tfplan
En CI, ejecuta plan en los pull requests y apply al hacer merge. El plan muestra exactamente qué dashboards, data sources y alertas cambiarán.
Adopta lo que ya existe
Si alguien construyó cosas en la interfaz, impórtalas al estado en lugar de recrearlas:
terraform import grafana_folder.apps <folder-uid>
terraform import grafana_dashboard.webapp <dashboard-uid>
terraform import grafana_data_source.prometheus <data-source-uid>
Las versiones más nuevas de Terraform también pueden usar bloques import. Los formatos de ID de importación pueden diferir entre versiones del provider, así que confírmalos en la documentación del recurso.
Terraform junto al provisioning por archivos
No gestiones el mismo recurso con ambos. Elige un límite y respétalo. Un reparto común es provisioning por archivos para data sources y dashboards (cargados al arrancar, sin necesidad de token de API) y Terraform para equipos, service accounts y permisos. Otro es Terraform para todo, con archivos de provisioning limitados a los ajustes del servidor.
Guías populares
-
Opera Grafana como código: la visión de conjunto Qué puede vivir en archivos, qué necesita una API y cómo encajan las piezas. -
Configura el servidor de Grafana con grafana.ini y variables de entorno Sabe dónde viven los archivos de configuración, cómo se ordenan las sobrescrituras y cómo mantener los ajustes en Git. -
Provisiona dashboards desde archivos JSON Carga dashboards desde disco, asigna carpetas a partir de directorios y crea dashboards sin perder cambios. -
Provisiona reglas de alertas, contact points y políticas de notificación Define todo el pipeline de alertas en YAML para que se revise y versione como código. -
Despliega Grafana en Kubernetes con Helm y valores de provisioning Ejecuta Grafana desde un chart de Helm donde los data sources, dashboards y ajustes provienen de archivos de valores. -
Recarga, verifica y soluciona problemas de provisioning desde la línea de comandos Averigua qué cargó Grafana, recarga sin reiniciar y arregla los errores de provisioning más habituales.