TT Lab
はじめる
学ぶ 学習パス コース

Grafana — ダッシュボードは問いだ

版は残っていたが、何が変わったかは誰も知らなかった

TT Labで続きを見る

一言でいうと

ダッシュボードをコードで管理するという言葉の核心は、ファイルに置くことではなく、変更を読めて、元に戻せるようにすることです。

なぜ必要なのか

障害の翌日、ダッシュボードが変わっています。誰が直したのかはわからず、何が変わったのかもわかりません。Grafanaはバージョンを残しますが、2つの版のJSONをダウンロードして比べると、数百行がまるごと違うと出てきます。保存のたびに変わるフィールドが混ざっているからです。そのため、「バージョンが残っている」という事実と、「何が変わったのかがわかる」という事実のあいだには、かなり遠い距離があります。

移すときも同じです。よくできたダッシュボードJSONを、別の環境にそのままアップロードすると、パネルがすべて空になります。画面にはエラーがなく、ただ空なのです。ダッシュボードがデータソースを名前ではなくuidで指しますが、自動生成されたuidは、環境ごとに違うからです。この事実を知らないと、1日を失います。

どう動くのか

Grafanaのダッシュボードは、保存されるたびに新しいバージョンが作られ、保存リクエストと一緒に送ったメッセージが、そのバージョンに付きます(ダッシュボードHTTP API)。メッセージを空にしておくと、一覧には時刻だけが残ります。そして、最初の保存のメッセージは、Grafana自身が上書きします。自分で確認しないと、「メッセージを書いたのに、なぜ残らないのか」と、長いあいだ迷うことになります。

2つの版を読めるようにするには、正規化が必要です。保存のたびに変わるのは、ダッシュボードの最上位にあるversion・idのようなフィールドです。これらを取り除いて、キーをソートして出力すれば、そのときからdiffは、人が読めるものになります。正規化関数が備えるべき性質は2つです。同じ入力にはいつも同じ出力を返すこと(決定的)と、揮発フィールドだけが違う2つの版を、同じものにすることです。

何を なぜ
最上位のversion・idを取り除きます 保存のたびに変わり、diffを覆い隠すからです
キーをソートします 順序が揺れると、同じ内容でも違って見えるからです
パネルのidは残します パネルを指す名前なので、意味があるからです

移す問題は、データソース変数で解決します。datasourceタイプのテンプレート変数を1つ作っておき、パネルにその変数を指させれば、環境が変わっても、直す場所は1か所です(変数のドキュメント)。存在しないuidでクエリが出ると、Grafanaは404を返しますが、この応答はブラウザーの開発者ツールでしか見えず、パネルには単に空のグラフとして表れます。

ここまで来ると、もう1つの性質が必要になります。ファイルと画面が同じかどうかを、自分で問える必要があります。リポジトリにダッシュボードを置いておくだけで、それが実際に画面と同じかどうかを誰も確認しなければ、2つは静かに分かれていきます。正規化関数がすでにあるので、この検査は短くなります。画面から受け取って正規化したものと、ファイルを正規化したものを、比べればよいのです。そして、その検査ツールも、両方向で試す必要があります。同じものを渡すと通過し、別のものを渡すと落ちるかを確認しないと、何を渡しても通過する検査ツールを信じて過ごすことになります。

見つけられるようにすることも、コードで管理することの一部です。ダッシュボードが数十個になると、どれを開くべきかが問題になり、そのときに頼るのが、フォルダーとタグです。どちらも、ダッシュボードJSONとプロビジョニング設定に書かれるので、ファイルが原本になったあとは、タグ1つを付ける作業さえ、ファイルを直して反映する必要があります。面倒に見えますが、その面倒さこそが、「誰がいつ何をなぜ」が残ることの対価です。

最後は、原本をどこに置くかです。プロビジョニングで提供されるダッシュボードは、画面からもAPIからも保存できず、保存を試みると、400とともに拒否されます(プロビジョニングのドキュメント)。不便に見えますが、これがこの方式の核心です。画面とファイルが分かれる道そのものを、なくしてしまいます。そのときから、ダッシュボードを変える唯一の道は、ファイルを直して読み込み直させることで、その道にはコードレビューが付きます。

現場での姿

あるチームは、ダッシュボードをリポジトリに置いていたのに、半年後には、画面とファイルが完全に違っていました。ファイルから提供せず、単にバックアップとして置いておいただけだったからです。誰にも、ファイルを直す理由がなく、画面で直すことを止めるものもありませんでした。プロビジョニングに変えて初めて、ファイルが原本になりました。

別のチームは、ステージングにダッシュボードを移したところ、「データが出ない」で2日を使いました。クエリも合っていて、Prometheusも正常でした。パネルのdatasource.uidが、本番環境で自動生成された値で、ステージングにはそのようなuidがなかったのです。データソース変数に切り出してからは、移す作業はファイルのコピーで終わりました。

この環境で判定できることとできないこと

このPodのGrafanaは本物として動いていますが、画像レンダラーがないので、画面の絵そのものは検査できません。その代わり、バージョンAPI・プロビジョニングの状態・保存拒否の応答・ダッシュボードJSONモデルは、すべて確認でき、このラボの判定は、その範囲の中で行います。リポジトリ側(レビュー・CI)は、このPodにgitがないので扱いません。その代わり、「リポジトリに何を載せれば一式になるのか」を、一覧として残すところまで進みます。

次のラボですること

ダッシュボードをアップロードして、保存メッセージを付けてもう一度保存したあと、バージョン一覧が実際に何を残すかを確認します。正規化スクリプトを作って、2つのバージョンの差を、人が読める形で取り出し、データソースを変数に切り出して、移せるようにします。次に、ダッシュボードをファイルから提供されるように変えて、保存が拒否される応答を、自分で受け取ってみます。最後に、タグ1つを付ける作業を、ファイルを直して行い、ファイルと画面が同じかどうかを自分で見る検査ツールまで作ります。