kakakakakku blog

Weekly Tech Blog: Keep on Learning!

Mackerel の「拡張グラフパーマリンク」を使ってファイルシステム使用率をグラフにしようと試行錯誤した話

さぁ「Mackerel Advent Calendar 2016」2日目の記事を書くぞ!まだ枠空いてますよ〜

qiita.com

最近作った最高のダッシュボードの話

10月末に mkr dashboards コマンドを使って,ダッシュボードの定義を YAML 形式でバージョン管理しながら運用している話をまとめた.実際にチーム内で積極的に活用していて,障害時/テレビ砲待機時/定常モニタリング時など,気になったらすぐに Mackerel のダッシュボードを見る習慣が根付いている.もしダッシュボードの運用に悩んでいる人がいたら参考になるはず!!!

kakakakakku.hatenablog.com

メトリック一覧取得 API を叩いてみた

上の記事を書いたときに @songmu さんに「メトリック一覧取得 API と組み合わせると良いかも」とコメントを頂いた.「メトリック一覧取得 API」とは,今年の5月にリリースされた新機能で,簡単に言うと「サービスとホストに紐付くメトリック名の一覧を取得するだけの API」で,マッシュアップしてこそ効果を発揮する系の API だとは思う.具体的には以下の2個のエンドポイントで叩くことができる.

  • サービス(メトリック名の一覧を取得する)
    • /api/v0/services/<serviceName>/metric-names
  • ホスト(メトリック名の一覧を取得する)
    • /api/v0/hosts/<hostId>/metric-names

mackerel.io

ホストメトリック名の一覧を取得してみたところ,filesystem.xvde.sizefilesystem.xvde.used を発見した.上の記事にも書いた通り,実は「ロールごとにファイルシステムのメトリックを見れない」ことにずっと悩んでいたんだけど,もしかしたら filesystem.xvde.sizefilesystem.xvde.used で解決するのでは?と考えた.ちなみに xvde に関してはまぁルートデバイスのアタッチ次第なので,そこは読み替えてもらう前提として.

# 実際にはカスタムメトリック名も取得できる(量が多く割愛している)
$ curl -H 'X-Api-Key: xxx' -s https://mackerel.io/api/v0/hosts/xxx/metric-names | jq .
{
  "names": [
    "cpu.guest.percentage",
    "cpu.idle.percentage",
    "cpu.iowait.percentage",
    "cpu.irq.percentage",
    "cpu.nice.percentage",
    "cpu.softirq.percentage",
    "cpu.steal.percentage",
    "cpu.system.percentage",
    "cpu.user.percentage",
    "disk.xvde.reads.delta",
    "disk.xvde.writes.delta",
    "filesystem.xvde.size",
    "filesystem.xvde.used",
    "interface.eth0.rxBytes.delta",
    "interface.eth0.txBytes.delta",
    "loadavg5",
    "memory.active",
    "memory.buffers",
    "memory.cached",
    "memory.free",
    "memory.inactive",
    "memory.swap_cached",
    "memory.swap_free",
    "memory.swap_total",
    "memory.total",
    "memory.used"
  ]
}

ダッシュボードにグラフを貼ってみた

以下の iframe を用意してダッシュボードにグラフを貼ってみたところ,予想通り,ロール毎に filesystem.xvde.sizefilesystem.xvde.used を描画することができた.

<iframe src="https://mackerel.io/embed/orgs/xxx/services/my-service/web?graph=filesystem.xvde.size&period=1d&simplified=false&stacked=false" height="200" width="400" frameborder="0"></iframe>
<iframe src="https://mackerel.io/embed/orgs/xxx/services/my-service/web?graph=filesystem.xvde.used&period=1d&simplified=false&stacked=false" height="200" width="400" frameborder="0"></iframe>

f:id:kakku22:20161129235321p:plain

実際に必要なのは「使用率 (%)」だ!

実際にモニタリングするなら「ファイルシステム使用率 (%)」を描画したいなと思って,メトリックの計算を試してみようと思った.

Zabbix 2.0 でファイルシステム系のメトリックを取得する場合は,ローレベルディスカバリ (LDD) を使うことも多くて少し仕組みが違うけど,例えば Zabbix で Memcached のキャッシュヒット率を取得する場合は「計算フィールド」を使うと思う.この「計算フィールド」と同じことを Mackerel でやりたいなと思った.

拡張グラフパーマリンクを使う(実験的機能)

Mackerel でメトリックを計算するためには「拡張グラフパーマリンク」を使う.「拡張グラフパーマリンク」は表現の幅を大きく広げられる可能性があって,素晴らしい機能だと思ってる.例えば,メトリックを1週間前と比較してグラフに描画をすることができたりする.ただし,現在もまだ実験的機能で,もし使う場合は事前に実験的機能を有効にしておく必要がある.

やっと本題に入れる.今回「拡張グラフパーマリンク」にハマって試行錯誤した話をまとめる.

mackerel.io

group 関数を使うと複数のメトリックを同じグラフに描画できる

group 関数を使うと複数のメトリックを同じグラフに描画できるため,さっきまで別々のグラフだった filesystem.xvde.sizefilesystem.xvde.used を同じグラフに展開できた.

<iframe src="https://mackerel.io/embed/orgs/xxx/advanced-graph?query=group(role('my-service:web', 'filesystem.xvde.used'), role('my-service:web', 'filesystem.xvde.size'))&title=filesystem&period=1h&simplified=false&stacked=false" height="200" width="400" frameborder="0"></iframe>

クエリ部分を整形すると SQL 的に読めると思う.

group(
  role('my-service:web', 'filesystem.xvde.used'),
  role('my-service:web', 'filesystem.xvde.size')
)

f:id:kakku22:20161130001133p:plain

divide 関数と scale 関数を使えば「使用率 (%)」も簡単に表現できそう

次に divide 関数で除算をして,scale 関数で乗算をすれば,使用率 (%) の計算も楽勝じゃん!と思ったけど,結論として無理だった.最初は単純に以下のように書いた.

<iframe src="https://mackerel.io/embed/orgs/xxx/advanced-graph?query=scale(divide(role('my-service:web', 'filesystem.xvde.used'), role('my-service:web', 'filesystem.xvde.size')), 100.0)&title=filesystem&period=1h&simplified=false&stacked=false" height="200" width="400" frameborder="0"></iframe>

クエリ部分を整形すると SQL 的に読めると思う(実際には動かない例だけど).

scale(
  divide(
    role('my-service:web', 'filesystem.xvde.used'),
    role('my-service:web', 'filesystem.xvde.size')
  ),
  100.0
)

ようするに ( filesystem.xvde.size / filesystem.xvde.used * 100 ) を実現するクエリを書いた.ドキュメントに詳しく書かれて無くてハマってしまったけど,試行錯誤して気付いたこととして,divide 関数はホストメトリックのような単一の値だけをサポートしていて,role 関数を使った複数ホストの値はサポートしていないようだった.よって僕が書いたクエリだと,多対多の divide になってしまうため,エラーになる.

ワークアラウンドを考えた

諦めるのはまだ早いぞ!と思って,全ホストごとに集計して group 関数を使うワークアラウンドを考えてみた.実際にうまくできた.ただし,ホストを固定しているため,ロールの意味が全くないし,オートスケールなどをしている場合には使えないし,制約ばかりになってしまった.URL 長すぎワロタwww

ちなみに &unit=%25 を付けることで,グラフ上の単位が % になる.細かな工夫も重要!

<iframe src="https://mackerel.io/embed/orgs/xxx/advanced-graph?query=group(alias(scale(divide(host('host1', 'filesystem.xvde.used'), host('host1', 'filesystem.xvde.size')), 100.0), 'host1'), alias(scale(divide(host('host2', 'filesystem.xvde.used'), host('host2', 'filesystem.xvde.size')), 100.0), 'host2'), alias(scale(divide(host('host3', 'filesystem.xvde.used'), host('host3', 'filesystem.xvde.size')), 100.0), 'host3'), alias(scale(divide(host('host4', 'filesystem.xvde.used'), host('host4', 'filesystem.xvde.size')), 100.0), 'host4'), alias(scale(divide(host('host5', 'filesystem.xvde.used'), host('host5', 'filesystem.xvde.size')), 100.0), 'host5'))&unit=%25&title=filesystem&period=1h&simplified=false&stacked=false" height="200" width="400" frameborder="0"></iframe>

クエリ部分を整形すると SQL 的に読めると思う.ただまぁ…ツライ!

group(
  alias(
    scale(
      divide(
        host('host1', 'filesystem.xvde.used'),
        host('host1', 'filesystem.xvde.size')
      ),
      100.0
    ),
    'host1'
  ),
  alias(
    scale(
      divide(
        host('host2', 'filesystem.xvde.used'),
        host('host2', 'filesystem.xvde.size')
      ),
      100.0
    ),
    'host2'
  ),
  alias(
    scale(
      divide(
        host('host3', 'filesystem.xvde.used'),
        host('host3', 'filesystem.xvde.size')
      ),
      100.0
    ),
    'host3'
  ),
  alias(
    scale(
      divide(
        host('host4', 'filesystem.xvde.used'),
        host('host4', 'filesystem.xvde.size')
      ),
      100.0
    ),
    'host4'
  ),
  alias(
    scale(
      divide(
        host('host5', 'filesystem.xvde.used'),
        host('host5', 'filesystem.xvde.size')
      ),
      100.0
    ),
    'host5'
  )
)

一応期待していたグラフにはなったけど…むむむ!

f:id:kakku22:20161130235002p:plain

まとめると

今回は Mackerel の「拡張グラフパーマリンク」を試してみた.クエリで使える関数は他にもたくさんあって,もっと応用できそうだなと感じた.「拡張グラフパーマリンク」に凄く未来がある!

ただし,今回試行錯誤した「ロールごとにファイルシステム使用率 (%) をグラフに描画する件」は結論うまくできなかった.もしかしたら僕の勘違いかもしれないから,普通にこうすると実現できるよ!というアドバイスがあったら是非お願いします 🙇

引き続き Mackerel を使っていくぞ!

「Mackerel Advent Calendar 2016」3日目

明日も引き続き僕が書くよ…!

まだ枠空いてるし,仲間募集中〜!