System job is suitable for running mackerel-agent with Nomad

System job is suitable for running mackerel-agent with Nomad

現在 Nomad クラスターを展開しこのブログを運用しています。

Nomad クラスターは現在 3 台のサーバーから構成されており、それぞれのサーバーは Mackerel でモニタリングしています。Mackerel へサーバーのメトリクスを送るためには mackerel-agent が必要ですが、mackerel-agent は Docker イメージが用意されているので、これを Nomad のジョブとして動かし Nomad クラスターの各サーバーを監視しています。

ジョブのタイプは Service タイプを使っており、各サーバに対し 1 つの mackerel-agent が動いている状態であって欲しいので以下の工夫をしていました。

  • Nomad クラスターのサーバーは 3 台なので group 節で count を 3 に設定する。
  • 1 つのサーバー上に複数の mackerel-agent が実行されてしまっては意味がないので、constraint 節で同じサーバー上に同じグループを配置しないように設定する。

この辺の工夫は以下の記事にまとめています。

しかし、System タイプのジョブを使用すれば全てが解決されることにドキュメントを眺めていて気づきました…。

System ジョブの特徴

System ジョブは Service ジョブと同じく、常駐して起動していて欲しいタスク向けのジョブです。しかし、Service ジョブと比較して主に以下の特徴があります。

  • System ジョブは全てのクライアントノード上で実行される。
  • System ジョブを実行するリソースの余裕がない場合、優先度の低いジョブを中断しリソースを確保する。

つまり、System ジョブは Service ジョブのようにどのノードでもいいので合計で期待する数動いていれば良い、という考え方でなく、各ノードで必ず動いていて欲しいジョブを定義するのに向いています。

この特性ってまさに監視サービスに向いていますね。何で今まで気づかなかったんだろうw

System ジョブとして mackerel-agent を起動する

以下のジョブ定義になります。

job "mackerel" {
  datacenters = ["sgp1"]
  type = "system"

  group "mackerel" {
    task "mackerel" {
      driver = "docker"

      config {
        image = "mackerel/mackerel-agent:0.60.0"
        volumes = [
          "/var/run/docker.sock:/var/run/docker.sock",
          "/var/lib/mackerel-agent/:/var/lib/mackerel-agent/"
        ]
      }

      env {
        "apikey" = "<Mackerel の API Key>"
        "enable_docker_plugin" = "0"
        "opts" = "-v -role=lorentzca:nomad-cluster"
        "auto_retirement" = "1"
      }
    }
  }
}

Nomad はジョブタイプの変更はできないので、いったんジョブをパージして再度起動してあげる必要があります。

$ nomad job stop -purge mackerel
$ nomad job run mackerel.nomad

System ジョブとして起動できました。 ✨

$ nomad job status
ID        Type     Priority  Status   Submit Date
ghost     service  70        running  2019-10-15T18:02:19Z
mackerel  system   50        running  2019-10-16T14:52:13Z
nginx     service  80        running  2019-06-20T14:23:16Z

ジョブの詳細をみてみます。constraint 節や count パラメータを使わなくても、System ジョブを使っているのでちゃんと各ノードに 1 つずつ起動しているのがわかりますね。めっちゃ便利やん!

$ nomad job status mackerel
ID            = mackerel
Name          = mackerel
Submit Date   = 2019-10-16T14:52:13Z
Type          = system
Priority      = 50
Datacenters   = sgp1
Status        = running
Periodic      = false
Parameterized = false

Summary
Task Group  Queued  Starting  Running  Failed  Complete  Lost
mackerel    0       0         3        0       0         0

Allocations
ID        Node ID   Task Group  Version  Desired  Status   Created   Modified
3e023d52  40f26a1d  mackerel    0        run      running  2m2s ago  2m1s ago
6a717e7a  90ef5f33  mackerel    0        run      running  2m2s ago  2m1s ago
ea795072  fa85b1a6  mackerel    0        run      running  2m2s ago  2m1s ago

感想

ちゃんとドキュメント嫁案件ではあったかと思いますが、ノードが増減した場合に count を変えるにはどうすればとか悩んでいたのでとても嬉しい。

mackerel-agent 以外ではロードバランサーからのトラフィックを受け付ける Nginx も各サーバーに必ず 1 つずつ動いていて欲しいジョブなので、こちらも System ジョブ化するとメリットがありますね。やろう。

何でもかんでも System ジョブにすると今度は却って柔軟性が失われデメリットになってしまうのでここぞというところで使っていきたい!!