Grafana Series - GaC 1: Implementation Approaches for Grafana as Code
This article was last updated on: May 17, 2026 am
Series Articles
Overview
GaC (Grafana as Code) is clearly an extension of the IaC (Infrastructure as Code) concept.
In the article Terraform Series - What is IaC?, we already explained the related concepts in detail. We can directly apply them to GaC:
Grafana as Code (GaC) refers to managing and configuring Grafana through code rather than manual processes or console clicks.
There are two key terms here:
- Grafana
- Code
Grafana is the managed object. Here, it doesn’t just refer to Grafana OSS as a single product — it also includes commercial products and cloud services provided by Grafana Labs, including but not limited to:
- Grafana Alerting
- Grafana Cloud Stack, including Grafana Cloud’s:
- Authentication
- Permissions
- Policies
- Service Account
- Organizations
- …
- Grafana Enterprise
- Grafana OnCall: Incident Response and Management platform (IRM)
- Grafana SLO: SLA and availability management
- Grafana Synthetic Monitoring: synthetic checks, similar to BlackBoxProbe
Code is the management approach — managing Grafana resources the same way you manage code. And the most important part of managing code — version control — is unavoidable.
…
Of course, this series of articles primarily focuses on managing the Grafana product through code.
This article mainly follows the logic of the official article Grafana as code: A complete guide to tools, tips, and tricks, interspersed with the author’s evaluations and final choices.
Official GaC Approaches
The official recommendations include the following approaches. I’ll also add a few that I consider viable:
- Terraform-based Grafana Terraform provider
- Ansible-based Grafana Ansible collection
- Grizzly: An official Grafana open-source CLI tool for unified deployment and configuration of Grafana.
- Tanka: An official Grafana open-source Kubernetes cluster management tool based on Jsonnet
- Crossplane-based Grafana Crossplane provider
- Kubernetes CRD-based Kubernetes Grafana Operator
- API-based custom development:
- Jsonnet-based Dashboard as Code
- grafana/jsonnet-libs: Grafana Labs’ Jsonnet libraries (github.com)
- grafana/grafonnet: Jsonnet library for generating Grafana dashboards. (github.com)
- grafana/grafonnet-lib: Jsonnet library for generating Grafana dashboard files. (github.com) (🐾Deprecated, but many Dashboard resources still depend on it)
- Prometheus Monitoring Mixins | Monitoring Mixins
- kubernetes-monitoring/kubernetes-mixin: A set of Grafana dashboards and Prometheus alerts for Kubernetes. (github.com)
Quite a dazzling array of options, isn’t it? Hard to choose? 😄😄😄
I felt the same way at first. Don’t worry — let’s go through them one by one. The GaC landscape will become clear soon enough.
│ 📝Notes:
│
│ You may not have heard of Crossplane before. I happened to write an introductory article about it in 2021. If you’re interested, feel free to read it as supplementary material.
│
│ * Crossplane - A More Advanced Cloud Infrastructure Management Platform Than Terraform?
Jsonnet
Based on some of Grafana’s official talks, code repositories, and blog posts, Grafana heavily relies on Jsonnet as a configuration language. We’ll cover its history and usage in detail later.
Regardless of which GaC approach you choose, Jsonnet-based Dashboard as Code is a must-have.
- In Terraform, you can use the Jsonnet Provider in combination with Grafana
- In Ansible, you can add tasks for installing Jsonnet-related dependencies and generating dashboards with Jsonnet as prerequisite tasks
- In Grizzly and Tanka, Jsonnet is a first-class citizen. For example, Grizzly can directly use Jsonnet
- …
In summary, Jsonnet is currently the virtually only deep Dashboard as Code solution — it’s a must-have.
│ 📝Notes:
│ For shallow GaC usage, managing dashboards directly through Dashboard JSON files as code is also acceptable.
│ But once you get into deeper usage — when dashboards multiply and there’s a lot of repetitive configuration — Jsonnet is the only choice.
Grafana Terraform Provider
Grafana administrators can use the Grafana Terraform Provider to manage dashboards and alerts, add synthetic monitoring probes and checks, manage identity and access, and more.
An example Terraform configuration for creating a dashboard looks like this:
1 | |
Target Users
The Grafana Terraform Provider is better suited for users who are already using Terraform for non-Grafana use cases.
For users who want to manage the entire Grafana ecosystem resources on Grafana Cloud or Grafana OSS deployments, the Grafana Terraform Provider is the best choice because, compared to other Grafana as Code solutions, it supports the most Grafana resources.
My final choice was:
- Grafana Terraform Provider + Jsonnet
A major reason is exactly what was mentioned above: it supports the most Grafana resources.
I plan to use Grafana through AWS Managed Grafana. Compared to Grafana OSS, AWS Managed Grafana has some subtle differences:
- AWS Managed Grafana has DataSource Permission management, which Grafana OSS does not have.
However, the Grafana Terraform Provider does provide this capability — it’s listed under Grafana Enterprise, but it actually works.
The Grafana features I currently need include:
- Grafana Users
- Grafana Teams
- Grafana Organizations
- Grafana DataSource
- Grafana DataSource Permission
- Grafana Folder
- Grafana Folder Permission
- Grafana Dashboard
- Grafana Dashboard Permission
- Grafana Alerting
Only the Grafana Terraform Provider provides complete coverage of all these features.
Known Limitations
Managing dashboards isn’t the simplest process — users have to deal with lengthy JSON, which can be difficult to review and update. Grafonnet can help generate dashboard JSON for use with Terraform, but Grafonnet requires knowledge of Jsonnet, which may be undesirable for some users.
Regardless of the approach, Jsonnet is something all users entering the deep end of GaC must master — there’s no escaping it.
Grafana Ansible Collection
Configuration management resources are available through the Ansible Collection for Grafana. It can be used to manage various resources, including folders, cloud stacks, and dashboards. Users can programmatically manage Grafana resources not yet part of the Grafana Ansible Collection by writing Ansible playbooks that use the HTTP API.
An example Ansible configuration for creating a dashboard looks like this:
1 | |
Target Users
Like Terraform, the Grafana Ansible Collection is better suited for those already using Ansible for non-Grafana use cases. Additionally, the Collection currently only works with Grafana Cloud, so it makes the most sense for Grafana Cloud customers who want to declaratively manage resources with Ansible.
Known Limitations
As of now, the Grafana Ansible Collection only works with Grafana Cloud and only supports 8 resource types:
- API keys
- Cloud Stack
- plugins
- dashboards
- folders
- data sources
- alert contact points
- alert notification policies
This can be a drawback for users who want to manage the entire Grafana ecosystem as code with Ansible. As with Terraform, building dashboards is also not the simplest process.
In summary, the biggest drawback of the Grafana Ansible Collection is: it only works with Grafana Cloud and only supports 8 resource types.
Grizzly
Grizzly is a command-line tool that allows you to manage your observability resources as code. Grizzly supports Kubernetes-inspired YAML representations of Grafana resources, making it easier to get familiar with. Grizzly supports moving dashboards within a Grafana instance and can also retrieve information about already-configured Grafana resources. Grizzly currently supports:
- Grafana dashboards/dashboard folders
- Grafana data sources
- Prometheus recording rules/alerts in Grafana Cloud
- Grafana Cloud Synthetic Monitoring checks
Grizzly can also deploy dashboards built in Jsonnet using Grafonnet. (Learn more in the Grafonnet documentation).
A sample Kubernetes-style Grizzly configuration for creating a dashboard looks like this:
1 | |
Target Users
Grizzly is best suited for users who use Jsonnet to manage Grafana resources, or who prefer defining their Grafana resources in Kubernetes-style YAML.
Known Limitations
Grizzly currently does not support Grafana OnCall and Grafana Alerting resources.
It also does not support DataSource/Folder/Dashboard Permission resources.
In summary, Grizzly is best suited for users who use Jsonnet to manage Grafana resources, but its coverage of Grafana resources is also incomplete.
Grafana Crossplane Provider
The Grafana Crossplane Provider is built using Terrajet and provides support for all resources supported by the Grafana Terraform Provider. It enables users to define Grafana resources as Kubernetes manifests and also helps users who build GitOps pipelines around Kubernetes manifests using tools like ArgoCD.
To get started with the Grafana Crossplane Provider, install Crossplane in your Kubernetes cluster and install the provider with this command:
1 | |
During provider installation, CRDs for all resources supported by the Terraform provider are added to the cluster, so users can start defining their Grafana resources as Kubernetes custom resources. The Crossplane provider ensures that what’s defined in the CRDs is visible in the Grafana UI. If any changes are made directly in the UI, those changes will be discarded when the provider re-syncs. This helps ensure that any declarative definitions in the cluster will be the source of truth for Grafana resources.
To get started, refer to the examples folder in the Grafana Crossplane repository.
A sample Kubernetes CRD for creating a Dashboard looks like this:
1 | |
Target Users
The Grafana Crossplane Provider is suitable for existing Crossplane users who want to manage Grafana resources from within Kubernetes and use Kubernetes manifests for GitOps pipelines.
Known Limitations
The Crossplane provider depends on having the Crossplane CLI and Crossplane installed in the Kubernetes cluster. This dependency is unattractive for non-Crossplane users. It’s also in alpha stage, so it hasn’t reached a stable state yet.
In summary, it’s suitable for users already using Crossplane, but holds little appeal for non-Crossplane users. Additionally, it’s not yet stable.
Kubernetes Grafana Operator
The Grafana Operator is a Kubernetes Operator for configuring and managing Grafana and its resources using Kubernetes CRs. It’s a Kubernetes-native solution built by the Grafana community. It can also use dashboards built in Grafonnet as a source for dashboard configuration.
Refer to the documentation section in the grafana-operator repository to get started.
A sample Kubernetes configuration for creating a dashboard using the Grafana Operator looks like this:
1 | |
Target Users
The Grafana Operator works great for users who want to manage Grafana resources from within Kubernetes and use Kubernetes manifests for GitOps pipelines.
Known Limitations
This only works with Grafana OSS, so Grafana Cloud users won’t be able to use it. Also, the Grafana Operator doesn’t have a Helm Chart, which can be an issue for organizations with pipelines built around Helm.
In summary, I personally believe the Kubernetes Grafana Operator is well-suited for users who:
- Self-host Grafana OSS
- Deploy Grafana OSS within a Kubernetes cluster
It also has these advantages:
- Supports various detailed Grafana OSS configurations
- Grafana Dashboards can be sourced from Grafana.com IDs (other tools don’t seem to have this)
- Supports installing Grafana Plugins (other tools don’t seem to have this)
- Perfectly aligned with GitOps
Correspondingly, it also has some disadvantages:
- Community-developed, lacking official Grafana support
- Does not support Grafana Cloud/AWS Managed Grafana or other cloud services
Tanka
A clean, concise, and super-flexible YAML alternative for your Kubernetes cluster.
- 💥 Concise: The Jsonnet language expresses your application more clearly than YAML.
- 📚 Reusable: Build libraries, import them anytime, even share them on GitHub
- 📌 Clean: With Kubernetes libraries and abstractions, you’ll never see templates again!
- 🎯 Confidence: Stop guessing — use tk diff to see exactly what will happen
- 🔭 Helm: Vendor, modify, and export reproducible Helm Charts.
- 🚀 Production-ready: Tanka deploys Grafana Cloud and more production setups
A sample configuration for creating Prometheus + Grafana K8s resources using Tanka looks like this:
jsonnet
local k = import “github.com/grafana/jsonnet-libs/ksonnet-util/kausal.libsonnet”;
{
_config:: {
grafana: {
port: 3000,
name: “grafana”,
},
prometheus: {
port: 9090,
name: “prometheus”
}
},
local deployment = k.apps.v1.deployment,
local container = k.core.v1.container,
local port = k.core.v1.containerPort,
local service = k.core.v1.service,
prometheus: {
deployment: deployment.new(
name=$._config.prometheus.name, replicas=1,
containers=[
container.new($._config.prometheus.name, “prom/prometheus”)
+ container.withPorts([port.new(“api”, $._config.prometheus.port)]),
],
),
service: k.util.serviceFor(self.deployment),
},
grafana: {
deployment: deployment.new(
name=$._config.grafana.name, replicas=1,
containers=[
container.new($._config.grafana.name, “grafana/grafana”)
+ container.withPorts([port.new(“ui”, $._config.grafana.port)]),
],
),
service:
k.util.serviceFor(self.deployment)
+ service.mixin.spec.withType(“NodePort”),
},
}
Target Users
Strictly speaking, Tanka shouldn’t appear here. Tanka is essentially a Kubernetes infrastructure management tool. Its competing alternatives are:
- Kustomize
- Helm
- Kubernetes Operator
Or even:
- Terraform
- Ansible
If you’re an avid fan of the Jsonnet configuration language and want to manage Kubernetes infrastructure along with observability Grafana Dashboards, Prometheus rules, and Alert rules through Jsonnet, then Tanka is for you.
Known Limitations
Abandoning Kubernetes YAML and fully adopting Jsonnet for resource management requires you to additionally master the following:
- Jsonnet
- Tanka usage
- Jsonnet libraries for Kubernetes resources
- Grafana-related Jsonnet libraries
In summary, Tanka is not recommended unless you’re an avid fan and expert of the Jsonnet configuration language.
API-Based Custom Development
I did a thorough search for Grafana’s APIs. The official options include:
- Grafana API: The lowest-level API interface.
- grafana-api-golang-client: A low-level Go client based on the Grafana API. It’s also the underlying implementation of the Grafana Terraform Provider.
If using the Grafana API, an example of creating a Dashboard looks like this:
http
POST /api/dashboards/db HTTP/1.1
Accept: application/json
Content-Type: application/json
Authorization: Bearer eyJrIjoiT0tTcG1pUlY2RnVKZTFVaDFsNFZXdE9ZWmNrMkZYbk
{
“dashboard”: {
“id”: null,
“uid”: null,
“title”: “Production Overview”,
“tags”: [ “templated” ],
“timezone”: “browser”,
“schemaVersion”: 16,
“version”: 0,
“refresh”: “25s”
},
“folderId”: 0,
“folderUid”: “l3KqBxCMz”,
“message”: “Made changes to xyz”,
“overwrite”: false
}
If using grafana-api-golang-client, you can refer to this test case for an example of creating a Dashboard:
https://github.com/grafana/grafana-api-golang-client/blob/master/dashboard_test.go
Target Users
First, API-based custom development is suitable for situations where the development team is strong, there are more customization needs, none of the above GaC approaches meet the requirements, or integration with internal enterprise automation tools is needed.
Second, Grafana provides the Go-based grafana-api-golang-client. If your tech stack is Go, it’s recommended to use grafana-api-golang-client directly.
If your tech stack is not Go, it’s recommended to develop based on the Grafana API.
Known Limitations
None.
The only limitation is the technical capability and resource investment of you/your team/your organization.
Summary
Here’s a handy comparison table covering all the properties and tools mentioned above.
| Property/Tool | Grafana Terraform Provider | Grafana Ansible Collection | Grizzly | Tanka | Grafana Crossplane Provider | Grafana Operator | Grafana API |
|---|---|---|---|---|---|---|---|
| Supported Grafana Resources | All resources | Grafana Cloud Stack, plugins, API keys, dashboards, data sources, folders | Synthetic Monitoring checks, dashboards, data sources, folders, Prometheus rules | Unknown | All major resources | Folders, data sources, dashboards, notification channels, Grafana plugin, Grafana OSS deploy | All resources |
| Formatting Tools | HCL/JSON/Jsonnet | YAML | Jsonnet/YAML/JSON | Jsonnet | YAML/JSON | YAML | Up to you |
| Kubernetes-style Manifests | ✔️ | ✔️ | ✔️ | Up to you | |||
| Manage Defined Resources in K8s | ✔️ | ✔️ | ✔️ | Up to you | |||
| Simple Dashboard Build Process | ✔️ | Up to you | |||||
| Retrieve Grafana Resource Info | ✔️ | ✔️ | Unknown | Up to you | |||
| Built-in Resource Sync Process | ✔️ | Unknown | ✔️ | ✔️ | Up to you | ||
| Target Users | Existing Terraform users | Existing Ansible users | Users wanting Kubernetes-style manifest management for Grafana with built-in workflows and sync | Users deployed on K8s who are Jsonnet fans/experts | Existing Crossplane users, or those wanting to manage Grafana with K8s resources | Users fully on Grafana OSS deployed in K8s who want K8s resource management | Users whose needs aren’t met by existing solutions, with heavy customization needs and internal tool integration |
│ Most of the tools defined here can be used in combination with each other, enabling users to achieve a 1 + 1 > 2 effect.
My final choice is:
- Grafana Terraform Provider
- Jsonnet
My Grafana environments are primarily:
- AWS Managed Grafana
- Grafana OSS
- Grafana Cloud Free
The Grafana features I need include:
- Grafana Users
- Grafana Teams
- Grafana Organizations
- Grafana DataSource
- Grafana DataSource Permission
- Grafana Folder
- Grafana Folder Permission
- Grafana Dashboard
- Grafana Dashboard Permission
- Grafana Alerting
For more information or to get started with Grafana, check out each tool’s code repository or reach out to me. Stay tuned for my upcoming articles. 💪💪💪