#hashitalks Japan 2025 で「Grafana as Code - Terraformによるダッシュボードとアラートの構成管理」というお話をしました

#hashitalks Japan 2025 で「Grafana as Code - Terraformによるダッシュボードとアラートの構成管理」というお話をしました

2025.11.17

HashiTalks:Japan 2025にて「Grafana as Code - Terraformによるダッシュボードとアラートの構成管理」というタイトルで登壇しました。ご視聴いただいた皆様、ならびにこの機会をくださったHashiCorpの皆様、ありがとうございました!

本記事はその発表内容をブログ用に再編したものです。

Grafanaとは

メトリクス、ログ、トレースなどのデータを可視化するためのオープンソースの監視・分析プラットフォームです。

主な特徴

  • 多様なデータソースに対応: Prometheus、Elasticsearch、CloudWatch、MySQLなど
  • 柔軟なダッシュボード: グラフ、テーブル、ヒートマップなど、様々な形式でデータを可視化
  • アラート機能: Slack、PagerDuty、メールなど様々なチャネルに通知
  • クエリエディタ: データソースごとに最適化されたクエリエディタを提供

以下はGrafanaで作成したダッシュボードの例です。このような綺麗で見やすいダッシュボードを比較的簡単に作成できるツールです。

grafana-dashboard-english.png

プロジェクトの背景

まず、Grafanaリソース(ダッシュボード、アラート)の構成管理を行ったプロジェクトについて説明します。

Kubernetes (EKS)上でアプリケーションを稼働させているプロジェクトです。Kubernetesスタックにおいて監視・可視化のデファクトスタンダードといえるPrometheus + Grafanaの構成を採用しました。具体的には、AWSのマネージドサービスであるAmazon Managed Service for Prometheus (AMP)とAmazon Managed Grafana (AMG)を使用しています。このAMGで使用されているGrafanaのバージョンは9.4です。

aws-architecture.png

当初はGrafanaのUIから手動でダッシュボードを作成していましたが、アラート機能の追加を機として、以下の理由から構成管理ツールの導入を決定しました。

  • 変更履歴を残したい
  • 別環境への横展開(Dev→Stg→Prod)を容易にしたい

※ 本記事の実装は2024年1月〜4月時点のGrafana 9.4およびAMGの仕様に基づいています。Grafanaのバージョンアップに伴い、一部の仕様が変更されている可能性があります。最新情報は公式ドキュメントをご確認ください。

なぜTerraformを選んだのか

構成管理ツールとしてTerraformを選択した主な理由は以下の通りです:

  1. 既にTerraformの経験が十分にあった

    • EKSをはじめとするAWSサービスのIaCでTerraformを使用していた
    • Kubernetesリソースのデプロイにも一部Terraformを活用していた
  2. GrafanaやPromQLにはほぼ初挑戦の状態だった

    • PromQL (Prometheus Query Language): Prometheusでメトリクスをクエリするための言語
    • 構成管理ツールまで未経験のものを採用すると、苦戦が予想された
  3. 他の有力な候補が見当たらなかった

    • Grizzly: 当時アラート系リソースが(おそらく)未対応だった(現在は対応済)
    • Grafonnet: experimentalな状態(2025年11月現在も依然experimental)

ダッシュボード編

ここからは、ダッシュボード編とアラート編に分けて具体的に説明します。

Tips1: ダッシュボードはUIで作り込んでからTerraformに取り込む

ダッシュボード管理において最も効率的だと感じたアプローチは「UI(=ダッシュボードWebページ上)で作り込んでからTerraformに取り込む」という流れです。

UIの方が効率的な理由

  • PromQLの動作確認が即座にできる
    • クエリのテストをリアルタイムで実行可能
  • 視覚的フィードバックが得られる
    • グラフの見た目をリアルタイムで確認しながら調整できる

具体的なフロー

  1. GrafanaのUIでダッシュボードを作成・調整
  2. 動作を確認
  3. UIでJSONモデルを表示、コピー
  4. ローカルにJSONファイルとして保存
  5. grafana_dashboardリソースのconfig_json属性にJSONファイルを指定
resource "grafana_dashboard" "main" {
  folder      = var.folder_uid
  config_json = file("${path.module}/json/main-dashboard.json")
  overwrite   = true
}

overwrite = trueを設定することで、既にダッシュボードが存在していた場合でも上書きできるため、スムーズに移行できます。

Terraformで直接作り込むのは辛い

理論上はTerraform上で直接JSONを記述してダッシュボードを作成可能ですが、おすすめしません。

Terraformで作り込む場合、前述の grafana_dashboard.config_json 以下に巨大なJSONを定義する必要があります。

例えば以下がTerraformでやる場合の例です。

json-turai.png

この画像で表示されている部分だけでは

  • ダッシュボードのタイトル
  • ダッシュボードのタグ
  • 1パネル目の定義の途中

くらいまでしか定義できていません。1ダッシュボード内には 10数個のパネルを配置する場合もあるので、まだまだこの程度の記述では収まりません。

実際に作成したダッシュボードのJSONは1700行ほどにも達しており、これをUI無しで作成するのは現実的ではありませんでした。

Tips2: JSON内に固有ID値が入らないようにする

ダッシュボード定義のJSON内には、環境固有のIDが含まれることがあり、これが複数環境間(Dev/Stg/Prod)での横展開を困難にします。

今回具体的に問題になった要素は datasource UID(unique ID) でした。Grafanaの説明の際に「多様なデータソースに対応」とご紹介しましたが、このデータソースの定義はダッシュボード外で別途実施する必要があります。その上でダッシュボード内の各パネルでそのデータソースのUIDを指定します。ただ、UIDはデータソース登録時に動的に値が決まるので、環境毎に別の値が割り振られてしまいます。

対策: 名前ベースの参照に変更

UIDの代わりに、環境間で共通の名前(name属性)を使用することで解決できます。挙動は変わりません。

# ❌ 環境固有のUIDを直接参照
"datasource": {
  "type": "prometheus",
  "uid": "abc123xyz"
}

# ✅ 環境間で共通のnameを指定
"datasource": "AMP"

正規表現での自動変換

GrafanaUIからコピーしたJSONをTerraformに組み込む前に、以下の正規表現で一括変換を実施しました:

"datasource": \{\n( +)"type": "prometheus",\n( +)"uid": "[a-zA-Z]+"\n( +)\},
↓
"datasource": "AMP",

この変換により、次の環境(Stg、Prod)に展開する際にJSONを修正する必要がなくなります。

アラート編

続いてアラート編です。

前述のとおり、アラートに関しては既存のものがなく、今回構成管理の導入と同時に新規作成することになりました。

そのため、アラートについて一から学ぶ必要がありました。当初はダッシュボードと同様に、UIで作成してからTerraformコードと照らし合わせながら調整していくことを想定していましたが、アラートには重要な制約があることが分かりました。

Tips3: Terraformで作ったアラートリソースはUIで変更できない

Terraformで作成したアラート関連のリソースは、GrafanaのUI上で編集できなくなります。UI上では「provisioned」というラベルが付き、編集ボタンや削除ボタンが表示されなくなります。

※ 前述のとおりダッシュボード系のリソースは、Terraformで作成してもUI編集が可能です。

なぜ編集できないのか

これは手動変更による設定ドリフトを防ぐための仕様です。

  • 各アラート系Grafanaリソースは、UI以外から作成した場合、その作成方法(Terraform、API直接実行など)の情報を「provenance(プロビナンス:物の起源・由来を意味する英単語)」として保持しています
  • 同じprovenanceからでないと編集できないという仕組みになっています
  • つまり、Terraformで作ったらTerraformでしか編集・削除できません

なのですが、今回登壇するにあたってあらためてこのあたりの仕様を確認した所、私の理解が不足していた箇所が2点見つかりましたので共有します。

Terraform→UIはいけるらしいけど?

Grafanaの公式ドキュメントには、各リソースにてdisable_provenance = trueを設定すればTerraformで作成したリソースもUIで編集可能になると記載されています。

resource "grafana_contact_point" "my_contact_point" {
  name = "My Contact Point"

  disable_provenance = true
}

resource "grafana_message_template" "custom_notification_template_group" {
  name     = "custom_notification_template_group"
  template = "{{define \"template1\" }}Say{{ end }}{{define \"template2\" }}Hi!{{ end }}"

  disable_provenance = true
}

しかし、実際に試したところ、当環境ではこの設定が機能しませんでした。理由は不明です。ここからは私の推測ですが、AMG (Amazon Managed Grafana)環境では機能しないのかもしれません。というのも、AMGのドキュメントには豊富にTerraformでのアラートリソース実装例が記載されていました。にもかかわらず disable_provenanceについての言及がなく、「UIで編集不可」との旨だけ書かれていたためです。

no_ref_about_disable_provenance_on_amg_doc.png

他の環境(Grafana Cloudなど)では可能なのかもしれませんが、試せていないのであくまで推測です。ご了承ください。

UI→Terraformはいけた

逆方向、つまりUIで作成したリソースをTerraformにインポートは可能でした。terraform importコマンドやimportブロックが使用できます。

ただし、コードと実際のリソース間に差分があるとreplaceされるという挙動があり、一度replaceされるとTerraformで作成したリソース扱いになるため、以降はUIで変更不可になります。この挙動はdisable_provenanceの値を変更しても変わりませんでした。 (前述のとおりそもそもdisable_provenanceが機能していなのであれば、予想される動作と考えられます。)

Provider設定編

こちらについては HashiTalksでは時間の都合上割愛しました。せっかくなので本ブログ版には記載しておきます。

Tips4: API Keyの期限切れに対処する

Terraform Grafana providerには auth 属性の設定が必要です。こちらに設定する値は、AMGでは管理者権限でワークスペースにログインして、API Keyを発行することで取得できます。なのですが、このAPI Keyは最大でも30日で期限切れになります。期限切れ時の再発行対応が面倒です。

というわけで、工夫して再発行対応を不要にしました。詳細は以下エントリにまとめています。

https://dev.classmethod.jp/articles/amazon-managed-grafana-api-tokens-support/

service account への移行が推奨されている

API Keyは現在では非推奨であり、service account への移行が推奨されています。ですので上記エントリを参考にするよりも、以下を参考にされた方が良さそうです。(後日私も試してみたいと思います)

まとめ

Terraformを使ってGrafanaリソースを構成管理する際の4つの実践的なTipsを紹介しました。

  1. ダッシュボードはUIで作成してからTerraformにインポートする流れが効率的
  2. JSON内の固有ID値を排除することで環境間の移植性を確保
  3. Terraformで作成したアラートリソースはUIで変更不可という制約を理解しておく
  4. API Keyの期限切れ に対処する (service accountへ移行しよう)

これらのTipsが、Grafanaの構成管理にTerraformを導入する際の参考になれば幸いです。

この記事をシェアする

FacebookHatena blogX

関連記事