【検証】Serf v0.4.5までの新機能【してみた】

【検証】Serf v0.4.5までの新機能【してみた】 はてなブックマーク - 【検証】Serf v0.4.5までの新機能【してみた】


オーケストレーションツールの Serf ( http://serfdom.io/ ) は、リリース以来、順調にバージョンアップを続けています。昨年末には v0.2 だと思っていたら、2月末のリリースでは v0.4.5 になりました。

前回の検証から時間が経ち、改めてバージョンアップに伴う機能や拡張点を整理したのが本投稿。OSC での発表に間に合わなかった補足になります。Serf のアップデート情報を追う方や、これから Serf を始めようとしている方の参考になれば幸いです( ^ω^)

◆ ‘-iface’ オプションで、複数 NIC 環境での起動が容易に

これまで複数のネットワークインタフェースカードを備える環境では、agent 起動時に ‘-bind’ オプションを用いて指定する必要がありました。

$ serf join -bind=192.168.10.3

一方、都度 IP アドレスを明示する必要があるため、動的に IP アドレスが変わってしまう環境や、スクリプトでの指定が行いづらい問題がありました。

新しい ‘-iface’ オプションを使えば、IP アドレスを明示する必要は無く、どのインターフェースを使用するかのみ指定します。

$ serf join -iface=eth0

これを活用することで、仮想マシンの複製を行った後や、同じスクリプトを複数の Serf ノードに展開するとき、都度ファイルを書き直す必要がなくなりました。

◆ ‘-discover’ オプションのサポートで、serf join 時の参加ノード明示が不要に

serf の起動オプションで ‘-discover’ がサポートされました (v0.4.0)。従来、ノードを起動し、Serf クラスタに参加するには ‘-join’ オプションで「どのホスト」に参加するか明示する必要がありました。そのため、-join 先のホストが停止しているとノードに追加できない(所謂 SPOF の発生)問題がありました。

それを解決するのが ‘-discover’ オプションです。mDNS ( Multicast DNS ) が利用可能なネットワークであれば、Serf がマルチキャスト通信を行い、同一ネットワーク内のノードを自動把握することが出来ます。次のように、serf agent 起動時に ‘-join’ 先を明示せず、’-discover=クラスタ名’のオプションを付けます。

$ serf agent -iface=eth1 -discover=webapp

複数台で同時に実行すると、自動的にメンバに追加されていることが分かります。

$ serf members
node2.pocketstudio.net  192.168.39.12:7946  alive
node1.pocketstudio.net  192.168.39.11:7946  alive

オプションでクラスタ名(上記の例では webapp ) を指定します。同一セグメント内で Serf が混在しても、クラスタ名が一致しないと、自動的にクラスタに加えられることがありません。そのため、役割に応じて自答的に参加するクラスタを選択させることも出来ます。

◆ role が tag に変更

既存の role 機能はダイナミック・タグに置き換えられました。これまでは role=xxx の固定形式でしたが、タグでは「key=value」の形式であれば、様々な値を付与できます。

$ serf agent -iface=eth1 -discover=webapp -tag role=app1 &

タグは1つだけでなく、複数のタグを設定することが出来ます。また、タグ変更時に agent を再起動する必要はありません。動的に変更する事ができます。この状態でメンバ一覧を見てみましょう。

$ serf members
node1.pocketstudio.net  192.168.39.11:7946  alive  role=app1

起動時に ‘-tag’ オプションを指定するだけでなく、稼働中でもタグを追加出来ます。例えば「deploy=1st」というタグを付けたい場合には、’tags -set’ オプションを付けます。

$ serf tags -set deploy=1st
Successfully updated agent tags

メンバ一覧を確認すると、反映している事が分かります。

$ serf members
node1.pocketstudio.net  192.168.39.11:7946  alive  role=app1,deploy=1st

削除する場合は ‘-delete キー名’ オプションを使います。

$ serf tags -delete deploy

なお、タグの追加・削除時、新たに「member-update」というイベントハンドラが発行されるようになりました(タグ追加時、削除時いずれも)。イベントハンドラが発行されるということは、タグ操作のタイミングでコマンドが実行されるようになる事を意味します。色々使い勝手が拡がりそうですね。

◆serf members の拡張(正規表現でフィルタリング)

serf の管理ノード数が増えてくると、members 一覧で表示するノードも増え、情報を探し出すのが面倒になります。楽に特定できるよう、タグの検索(正規表現)が出来るようになりました。

たとえば、このように3つのノードが存在しているとします。

$ serf members
node1.pocketstudio.net  192.168.39.11:7946  alive  role=app1,deploy=1st
node2.pocketstudio.net  192.168.39.12:7946  alive  role=app1
node3.pocketstudio.net  192.168.39.13:7946  alive

この中で、タグ「role」が「app」で始まる任意の値を探したい時は、次のように指定します。

$ serf members -tag role=app*

あるいは、丁寧に記述すると、次のようになります。

$ serf members -tag role=\(app\).*
node2.pocketstudio.net  192.168.39.12:7946  alive  role=app1
node1.pocketstudio.net  192.168.39.11:7946  alive  role=app1,deploy=1st

カッコの前に「\」が入っているのは、コマンドライン実行時、エスケープさせている為です。これがないと、次のようにエラーが出ます。

-bash: syntax error near unexpected token `('

また、以前のバージョンでは -tag の変わりに -role を使う事が出来ましたが、最新バージョンでは次のように警告が表示されます。

Deprecation warning: 'Role' has been replaced with 'Tags'

また、稼働状態を ‘-status’ でフィルタさせることも出来ます。たとえば alive だけのメンバを表示させたい時は

$ serf members -status=alive

と指定すると、稼働中のものが表示されます。「-status=left」とすると、Serf クラスタから離れたノード情報が表示されます。

さて、正規表現でフィルタ出来ると何が嬉しいか、といいますと、JSON 形式の出力に対応している点です。例えば left 状態のノードを JSON 出力させると、次のように表示されます。

$ serf members -status=left -format=json
{
  "members": [
    {
      "name": "node3.pocketstudio.net",
      "addr": "192.168.39.13:7946",
      "port": 7946,
      "tags": {},
      "status": "left",
      "protocol": {
        "max": 3,
        "min": 1,
        "version": 3
      }
    }
  ]
}

JSON 形式のデータを用いれば、他のプログラムとの連携なり、データのやりとりをスムーズに行える事が期待できます。

◆複数 IP アドレス保持環境に ‘advertise’

1つの NIC 上に、IP エイリアスなどで複数の IP アドレスを設定することがあります。あるいは、NAT されている環境でも同じです。例えば、192.168.39.1 と 192.168.39.3 と2つの IP アドレスがあるとき、どの IP アドレスで Serf を使用するか明示させることができます。

$ serf agent -discover=webapp -advertise=192.168.39.1

以上が、主な変更点の整理になります。他にも細かな改良なりバグ修正が行われていますので、詳しくは ChangeLog をご覧ください。

◆参考

ChangeLog
https://github.com/hashicorp/serf/blob/master/CHANGELOG.md