Serf/Consulで管理を自動化! ~実践的な手法を紹介~

第1回Serf入門:動的に変化する環境を簡単に管理

Serfとは?

Serfは、HashiCorp社がオープンソースとして開発・公開しているクラスタ管理用のツールです。軽量なエージェントを起動するだけで手軽にクラスタを構成でき、複数台のサーバにまたがる作業の自動化に役立ちます。2013年後半から開発がスタートし、現在もGitHubやIRC上で開発が行われています。

登場背景と利用シーン

クラウドコンピューティングを使ったシステムの普及と、継続的な開発・運用スタイルの普及により、インフラ環境が増えたり減ったりするシーンが増えつつあります。クラウドを活用し、OSの領域までは短時間で準備できるようになりました。ミドルウェアやアプリケーションの設定も、ChefやAnsible等の構成管理ツールを使う手法が広まり、作業時間の短縮や正確性の向上が実現しています。

このようにインフラ部分が動的に変わることが当たり前になりつつある一方、運用視点で新しい課題が出てきます。例えば、増減したサーバーのホスト名・IPアドレスを監視設定に適用したり、複数台のサーバ上で一斉にコマンドを実行したりする必要性が出てきました。

PSSHであれば複数台のサーバに同時ログインするための仕組みがありました。しかし、そこには何らかのホスト情報一覧を管理するリストやログインの起点となるサーバが必要となります。また、障害発生をトリガとしてミドルウェアの設定変更を行いたい場合も、何らかの監視システムのエージェントを入れる必要があり、システムが複雑になりがちです。

これらの問題を解決するためにSerfが役立ちます。Serfであれば、管理用のサーバを準備しなくても、お互いが通信してクラスタを構成できます。Serfの機能を使えば、任意のコマンドをクラスタに所属するサーバで一斉に実行するだけでなく、サーバの追加や削除のタイミングでもコマンドを自動的に実行できます。

図1 一般的な運用とSerfの比較
図1 一般的な運用とSerfの比較

任意のコマンドを実行できることから、次のような利用方法があります。

  • ChefやAnsible等の構成管理ツールを一斉実行するタイミングの自動化
  • 特定のサーバのプロセスを、リモートから一斉に再起動
  • 障害発生を検出時、ロードバランサーの設定から自動削除、復旧時は自動回復
  • NagiosやSensu、Munin等の監視対象の追加・削除の自動化

Serfの3つの主な機能

Serfは複数台のサーバを管理するために、メンバー管理、障害検出、イベント共有機能を提供しています。これらの機能はコマンドプロンプト上での操作だけでなく、Message Pack RPCを通しても操作することができます。

メンバー管理

クラスタを構成する各サーバの死活や、メンバー(serfエージェントが稼働するサーバ)のホスト名、IPアドレス、タグを管理

障害検出

メンバーとの通信途絶時は障害情報を共有し、定期的に復帰を確認して疎通が回復できれば、クラスタへ自動復旧

イベント

メンバー管理や障害検出だけでなく、任意のタイミングで発生するイベントをクラスタ全体で瞬時に共有(100サーバでは約2秒で伝播)

このようなクラスタを構成できるのは、Serfが内部的にGossipプロトコルを拡張したSWIM方式を拡張したプロトコルを採用しているためです。次の図はクラスタで障害発生したイベントが伝わる様子です。複数台のサーバ上で、Serfエージェントが独自のクラスタを形成します。一定の間隔でエージェントが相互に通信し、お互いの監視を行っています。サーバCがサーバDの障害を検出すると、その情報は直ちに残りのサーバにも送られます。

図2 クラスタ構成とイベント
図2 クラスタ構成とイベント

Serfの他にもクラスタを形成するツールがありますが、構成や運用上の管理が複雑になりがちです。Serfであれは、1つのバイナリファイルをサーバに置くだけでセットアップが完了します。クラスタ構成のためにミドルウェアやライブラリをセットアップする必要もありません。ファイルをサーバに置く以外、今のシステムに変更を加えることなく、すぐに使える手軽さも大きな特徴です。

クラスタを形成する方法も簡単です。サーバ上でSerfエージェントを起動し、複数のサーバ上のエージェントが通信する設定を行うだけです。サーバの管理や操作を手軽にまとめることが目的であれば、Serfの導入のしやすさは注目です。

また、特集後半では同じくHashiCorpが提供するConsulを紹介します。Consulは、Serfが持っていないサービスレベルに対するメンバー管理・監視や、システム全体の可用性を高める仕組みが導入されています。その代わり、Serfよりも構成や管理が少し複雑になってしまいます。

Serfのセットアップ

Serfを使うには、バイナリを各サーバ上に展開する必要があります。対応しているOSは、Linux、Mac OS X、Windowsなどです。ダウンロードページで作業環境に合わせてダウンロードをお願いします。以下はLinux環境(64bit)のセットアップ例です。

$ wget -O 0.6.4_linux_amd64.zip https://dl.bintray.com/mitchellh/serf/0.6.4_linux_amd64.zip
$ unzip 0.6.4_linux_amd64.zip
$ sudo cp ./serf /usr/local/bin/serf

正常であれば、次のようにバージョン情報を確認できます。Serfプロトコルのバージョンは、過去2世代まで互換性が保証されますので、実際の利用時には覚えておくことをお勧めします。

$ serf -v
Serf v0.6.4
Agent Protocol: 4 (Understands back to: 2)

Serfでクラスタを構成

エージェントの起動

2台のサーバでクラスタを構成するには、それぞれのサーバでSerfエージェントをコマンドラインで起動します。ここでは、次の図のような構成を想定します。

図3 2台でクラスタを構成
図3 2台でクラスタを構成

まず1台目のサーバでserf agentコマンドを使い、Serfを起動します。

$ serf agent &
==> Starting Serf agent...
==> Starting Serf agent RPC...
==> Serf agent running!
         Node name: 'sakura1.pocketstudio.net'
         Bind addr: '0.0.0.0:7946'
          RPC addr: '127.0.0.1:7373'
         Encrypted: false
          Snapshot: false
           Profile: lan

==> Log data will now stream in as it occurs:

    2015/03/10 22:21:16 [INFO] agent: Serf agent starting
    2015/03/10 22:21:16 [INFO] serf: EventMemberJoin: sakura1.pocketstudio.net 192.168.39.1
    2015/03/10 22:21:17 [INFO] agent: Received event: member-join

これで待機状態になりました。もう1台のサーバでは-joinオプションを使用して接続先のクラスタを明示して起動します。正常に起動すると「EventMemberJoin」というイベントが発生し、エージェントは相互にホスト名やIPアドレスなどの情報を共有開始します。

$ serf agent -join=192.168.39.11 &

3台目以降の場合も、同様のコマンドを使ってクラスタに参加できます。また、マルチキャスト通信(mDNS)が許可されているネットワーク内であればクラスタ参加先を明示しなくても自動的に参加するオプションがあります。エージェント起動時のオプションで-discover=<任意のクラスタ名称>を使う場合は、クラスタ名称の一致するSerfクラスタに自動的に参加します。

なお、Serfエージェントが通信するため、iptablesやファイアウォールで制限している場合、ポート7946(TCP/UDP)の許可が必要です。また、コマンドラインを通してRPCプロトコルを使って情報を取得する場合は、ポート7373(TCP)の許可も必要になります。

クラスタ情報の確認

クラスタを構成しているサーバの情報を表示するには、serf membersコマンドを実行します。実行結果には左から「ホスト名」⁠IPアドレス」⁠死活状況」⁠タグ(存在している場合⁠⁠」の情報が表示されます。

$ serf members
sakura1.pocketstudio.net  192.168.39.1:7946  alive
sakura2.pocketstudio.net  192.168.39.2:7946  alive

エージェントを停止しますと、⁠alive」の状態が「left」⁠Ctrl+Cなどで正常終了時)「failed」⁠異常停止時)の状態に切り替わります。

イベントとクエリ

次は、クラスタ間で情報が共有される状態を確認しましょう。ここではSerfのログを参照し、イベントが伝播する状況を確認します。エージェントを起動したままであれば、画面にデバッグ情報が出力され続けていると思います。別のコンソールから確認したい場合はserf monitorコマンドを実行します。

コマンドラインからserf event testと実行します。

$ serf event test
Event 'test' dispatched! Coalescing enabled: true

実行後はSerfクラスタ内でイベントが共有され、サーバすべてで次のようなログが表示されます。実際には、このイベント発生のタイミングで、任意のコマンドを実行するように設定できます。

    2015/03/10 22:42:24 [INFO] agent: Received event: user-event: test

イベントの他にクエリと呼ばれるリクエストを送ることができます。イベントは一方的に送るだけですが、クエリの場合は実行結果を実行したエージェントに戻せます。

まとめ

今回はSerfの基本的な概念や使い方を見て行きました。Serfの機能はバイナリ1つを置くだけですぐ使えますので、運用シーンにおける十徳ナイフのようなものと言えるのではないでしょうか。次回は、より実践的なイベントハンドラの取り扱い方を見ていきます。

参考情報

おすすめ記事

記事・ニュース一覧