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

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

コピーはその日から別々に古びていく

TT Labで続きを見る

一言でいうと

対象が1つ増えるたびにダッシュボードをコピーしていると、コピーはその日から別々に古くなっていきます。変数はそのコピーをドロップダウン1つに置き換え、パネルのリピートはそのドロップダウンを複数枚のパネルに展開します。

なぜ必要なのか

ダッシュボードが最初に壊れる方式は、ほとんどいつも同じです。よくできたダッシュボードが1つあり、別のサービスを見たい人がそれをコピーして、クエリの名前だけを書き換えます。1週間後に元のダッシュボードにパネルが1つ増え、1か月後に元のクエリの窓が[5m]から$__rate_intervalに変わります。コピーはどちらも知りません。

この状態が怖いのは、画面が正常に見えることです。コピーも数字を表示し、グラフも描かれます。ただ、元のダッシュボードとは別の問いに答えているだけで、インシデントのときに2つのダッシュボードを並べて開いた人は、2つの数字がなぜ違うのかを探すところから始めることになります。直すべき箇所が、ダッシュボードの数×パネルの数だけあるという事実も、普段は見えません。クエリを1回直す必要が出て初めて、8か所を手で直しながら気づきます。

そのため、このモジュールでは、コピーをまず実際に作ってみます。4セットをアップロードしておき、「このクエリを1回直すには、何か所直さなければならないか」を数字で書いてから始めます。その数字があって初めて、変数が何をなくしてくれるのかが実感できます。

どう動くのか

テンプレート変数は、ダッシュボードJSONのtemplating.list配列に入ります。値を手で並べるcustomタイプと、データソースに問い合わせるqueryタイプがあります。対象の一覧のように増える可能性のあるものは、必ずqueryでなければなりません。手で書いた一覧は、5つ目の対象ができた日に、静かに古くなります。

複数の値を選べるようにした瞬間に、1つのことが変わります。複数の値が選択された変数をクエリに差し込むには、その値を1つの文字列にする必要があり、その方法はデータソースが決めます。公式ドキュメントは、PrometheusとInfluxDBは正規表現を使うので(값1|값2|값3)の形に展開され(プレースホルダーは選択された各値です)、値ごとに正規表現のエスケープがかかると書いています。したがって、クエリのマッチャーも一緒に変える必要があります。label="$var"は値が1つのときだけ合い、複数の値を受け取るにはlabel=~"$var"と書かなければなりません。これを変えないと、値を1つ選ぶときはうまくいくのに、2つ選んだ瞬間に空のグラフになります。人はたいてい「データがないな」と読んで、そのまま通り過ぎます。

全選択(includeAll)には、もう1つ設定が付いています。allValueを空にしておくと、Grafanaがすべての値をつなげて1つの長い文字列を作り、値を書いておくと(例: .+)その文字列が代わりに入ります。対象が数百個ある環境では、後者のほうがずっと軽くなります。ただし、エスケープがかからないので、その値がデータソースで有効かどうかは、人が責任を持つ必要があります。

パネルのリピートは、ここから始まります。パネルにrepeatを設定して複数値の変数を指定すると、Grafanaは選択された値ごとにパネルを1枚ずつ作ります。横に展開するか縦に展開するか(repeatDirection)、1行に何枚まで置くか(maxPerRow)も一緒に決めます。リピートされたパネルの中では、変数がそのパネルの値1つに解決されるので、タイトルに変数を入れておけば、どの対象のグラフなのかがタイトルでわかります。

変数が別の変数に依存するようにもできます。2つ目の変数のクエリの中で1つ目の変数を使うと、Grafanaがその関係に気づき、前の値が変わったときに後ろの値を再読み込みします。ここで重要なことが2つあります。1つは順序です。templating.listの前のほうにある変数が先に解決されるので、依存する側が後ろにある必要があります。もう1つは更新のタイミングです。ダッシュボードを開くときだけ再読み込みするか、時間範囲が変わるときにも再読み込みするかを選びます。時間範囲によって候補が変わる変数を前者の設定にしておくと、昨日を見に行った人が今日の一覧を見ることになります。

便利な分だけ、代償を払います。リピートパネル1枚は、オプションの数だけのパネルになり、パネルごとにクエリが最低1つずつ飛びます。リピートパネルが2つで、オプションがそれぞれ4つと3つなら、画面には7枚が描かれ、固定パネルまで合わせると8枚になります。対象が40個ある環境なら、同じダッシュボードが80枚になります。そのため、リピートを使うダッシュボードには展開されるパネル数の上限を決めておき、それを超える場合は、一覧を絞り込む変数を先に付けるか、ダッシュボードを分けるほうがよいです。

最後に、この環境で何を確認でき、何を確認できないかを書いておきます。このラボの採点は、ダッシュボードのJSONモデルと実際のクエリ結果だけで行います。変数が宣言されているか、タイプが何か、値の一覧がデータソースから実際に埋まるか、パネルのクエリが変数を使っているか、そのクエリが値を出すか、という点です。逆に、画面にパネルが実際に何枚描かれたかは、判定できません。リピートはブラウザーがダッシュボードを描くときに起きることで、このPodには画像レンダラープラグインがありません。サーバーが返すダッシュボードのJSONには、リピートされる前のパネル1枚しか入っておらず、変数のoptions配列も空(null)で返ってきます。そのため、オプションの数は、変数の宣言ではなくデータソースに直接問い合わせて数える必要があります。リピートが実際にどう見えるかは、Webプレビューで目で確認するしかありません。

現場での姿

あるチームは、サービスが12個あり、ダッシュボードも12個ありました。障害が起きてクエリを1つ直す必要が出ましたが、直した人は6個だけ直して帰宅しました。翌週、別の人が残りの6個のうち1つを見て、「ここは大丈夫」と判断しました。同じコードが動いているサービスでした。

逆に、リピートを信用しすぎて起きたこともあります。Pod名を変数にして、全選択を既定値にしたダッシュボードがあり、オートスケーリングがPodを200個まで増やした日に、そのダッシュボードを開いた人のブラウザーが固まりました。変数の一覧を絞り込む2つ目の変数(ネームスペース)を前に付けて、既定値を1つに変えて初めて、再び使えるようになりました。リピートは無料ではなく、オプションの数だけ掛け算されるコストです。

次のラボですること

まず、対象ごとにコピーされたダッシュボード4セットを実際にアップロードして、直すべき箇所がいくつあるかを数えます。次に、クエリ変数を1つ作って、値の一覧がデータから埋まることを確認し、複数値の選択と全選択をオンにしたうえで、クエリのマッチャーを正規表現に変えます。パネルのリピートで、対象の数だけパネルができるようにし、その変数に依存する2つ目の変数を加えて、順序と更新のタイミングを決めます。最後に、展開されるパネルの数を数えて上限を書き、コピー版として残っている古いダッシュボードを変数1つにまとめたうえで、まとめたパネルが元の4つのパネルと同じ答えを出すことを証明します。