スキップしてメイン コンテンツに移動

Serfを試してみました。

非集中型のクラスタ管理ツールのSerfを触ってみました。クラスタ管理というと何かいろいろ大変そうなイメージですが、Serfを利用すると簡単にサーバの死活監視や情報の収集が可能になります。

Serfについて

Serfの本家サイト:https://www.serfdom.io/

Serf is a decentralized solution for cluster membership, failure detection,and orchestration. Lightweght and highly available.

本家のサイトのトップページに書かれているようにserfは軽量で高可用性の非集中型のクラスタ管理ツールです。
  • インストールは簡単。
    •  serfの静的バイナリを各サーバにコピーするだけOK。
  • マスターサーバのような全体を管理しているノードはない
    • 全てのノードで実行されているserfは平等。
  • ゴシッププロトコルを利用したノード間のメッセージングツール
    • ノード間でお互いに通信して情報を全体に伝播させる。
  • 各ノードで実行されているserf agent が情報のやりとりをする。
    • クラスタ内のノードの増減についてのイベント
    • クラスタ内のノードの生死についてのイベント
    • ユーザ独自のイベントを通知することも可能
  • イベントをトリガにして任意の処理(スクリプト)を実行できる。
    • これによっていろいろ応用が効くようになる。

    例えば、クラスタ内のノードの死活監視やノードが追加/停止したときに自動でロードバランサの設定(バランス先)を変更するなどの使い方が考えられます。
    また複数のアプリケーションを組み合わせて利用する場合に全体の統制をとるのに利用できます。元々そのような管理の仕組みのないアプリケーションの組み合わせでも全体を統制するような仕組みを構築できます。

      インストール

      公式サイトに(静的)バイナリで配布されているのでそれをダウンロードしてきて展開し適当なパスにコピーすればOKです。今回は/usr/local/binに置く事にしました。

      # wget https://releases.hashicorp.com/serf/0.6.4/serf_0.6.4_linux_amd64.zip
      # unzip  0.6.4_linux_amd64.zip
      # cp serf /usr/local/bin

      Serfではこの基本的にserfコマンドのみを利用し、serf <コマンド名> [ 引数 ...]という形式で複数の機能を実行します。

      実行方法

      今回はVagrant+Virtualboxの仮想環境で検証していますが、実マシンはもちろんコンテナ環境でも問題ないです。とりあえず、debian01,debian02という名前の2つの仮想サーバを立ち上げます。サーバのアドレスは次のようになっています。
      debian01 : 192.168.0.101
      debian02 : 192.168.0.102
      debian03 : 192.168.0.103 (後ほど出てきます)
      まだ以下のログでサーバ毎の時間がずれていますが気にしないでください(すみません)

      まずそれぞれの仮想サーバでserf agentを実行します。コマンドはそのまま実行するとforegroundでの実行になります。今回はログをそのまま表示するためにforegroundで実行していますが、実際に利用する場合はbackgroundでの実行になると思います。

      debian01上で

      root@debian01:# serf agent -node=debian01 -bind=192.168.0.101
      ==> Starting Serf agent...
      ==> Starting Serf agent RPC...
      ==> Serf agent running!
               Node name: 'debian01'
               Bind addr: '192.168.0.101:7946'
                RPC addr: '127.0.0.1:7373'
               Encrypted: false
                Snapshot: false
                 Profile: lan

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

          2015/12/02 10:15:41 [INFO] agent: Serf agent starting
          2015/12/02 10:15:41 [INFO] serf: EventMemberJoin: debian01 192.168.0.101
          2015/12/02 10:15:42 [INFO] agent: Received event: member-join

      同様なことをdebian02上でも実行します。

       

      ノードのクラスタへの参加

      agentを実行した段階ではまだお互いに"自分のクラスタ"に属しているだけの状態です。それぞれのサーバでメンバーを確認してみると自分自身しかいません。

      root@debian01:~# serf members
      debian01  192.168.0.101:7946  alive

      root@debian02:~# serf members
      debian02  192.168.0.102:7946  alive

      どちらかのノードをもう片方のクラスタに参加させることにより同じクラスタに属して通信が可能な状態になります。debian02をdebian01のクラスタに参加させてみます。このことはdebian01をdebian02のクラスタに参加させることと同じです。debian02には自分のクラスタにdebian01が参加したというイベントが通知されます。

      root@debian02:~# serf join 192.168.0.101
      Successfully joined cluster by contacting 1 nodes.
      root@debian02:~# serf members
      debian02  192.168.0.102:7946  alive 
      debian01  192.168.0.101:7946  alive

      debian01上で確認してみてもdebian02が参加していることがわかります。

      root@debian01:~# serf members
      debian01  192.168.0.101:7946  alive 
      debian02  192.168.0.102:7946  alive

      またそれぞれのノードにノードが追加されたことが通知されています。
      debian01側

      2015/12/02 10:43:49 [INFO] serf: EventMemberJoin: debian02 192.168.0.102
      2015/12/02 10:43:50 [INFO] agent: Received event: member-join

      debian02側

      2015/12/02 10:39:16 [INFO] serf: EventMemberJoin: debian01 192.168.0.101
      2015/12/02 10:39:16 [INFO] agent: joined: 1 nodes
      2015/12/02 10:39:17 [INFO] agent: Received event: member-join
      さらにクラスタにノードを追加する場合にはノードのいずれかのメンバのクラスタに追加すればOKです。例えば3番目のノードdebian03立ち上げてをdebian02のクラスタに参加させてみましょう。次のようにserf agentの起動時にノードを指定して同時にjoinすることも可能です。

      debian03上で

      root@debian03:~# serf agent --node=debian03 --bind=192.168.0.103 --join=192.168.0.102
      ==> Starting Serf agent...
      ==> Starting Serf agent RPC...
      ==> Serf agent running!
               Node name: 'debian03'
               Bind addr: '192.168.0.103:7946'
                RPC addr: '127.0.0.1:7373'
               Encrypted: false
                Snapshot: false
                 Profile: lan
      ==> Joining cluster...(replay: false)
          Join completed. Synced with 1 initial agents

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

          2015/12/02 10:50:11 [INFO] agent: Serf agent starting
          2015/12/02 10:50:11 [INFO] serf: EventMemberJoin: debian03 192.168.0.103
          2015/12/02 10:50:11 [INFO] agent: joining: [192.168.0.102] replay: false
          2015/12/02 10:50:11 [INFO] serf: EventMemberJoin: debian01 192.168.0.101
          2015/12/02 10:50:11 [INFO] serf: EventMemberJoin: debian02 192.168.0.102
          2015/12/02 10:50:11 [INFO] agent: joined: 1 nodes
          2015/12/02 10:50:12 [INFO] agent: Received event: member-join

      debian03はdebian01とdebian02が追加されたというイベントを受け取ります。またdebian03が追加されたというイベントはdebian02だけでなく、debian01にも伝播して通知され、3台のノードが同じクラスタに参加している状態になります。

      root@debian01:~# serf members
      debian01  192.168.33.101:7946  alive 
      debian02  192.168.33.102:7946  alive 
      debian03  192.168.33.103:7946  alive

      debian01のログ

      2015/12/02 10:55:33 [INFO] serf: EventMemberJoin: debian03 192.168.0.103
      2015/12/02 10:55:34 [INFO] agent: Received event: member-join

      ノードのクラスタからの離脱

      ノードをクラスタから離脱させるためにはそのノードのagentを停止させればOKです。正常終了した場合と、異常終了した場合とではこのときに他のサーバに通知されるイベントが異なります。

      正常終了

      正常終了するには以下方法があります。
      • serf leaveコマンドを実行
      • SIGINTあるいはCtrl-Cでserf agentプロセスを終了させる。
      正常終了させた場合は終了したという通知がそのagentから発せられクラスタの各ノードに伝播します。ここではdebian03で(フォアグランドで実行していた)agentをCtrl-Cで終了させてみます。

      debian03でCtrl-C

      ^C==> Caught signal: interrupt
      ==> Gracefully shutting down agent...
          2015/12/02 10:58:49 [INFO] agent: requesting graceful leave from Serf
          2015/12/02 10:58:49 [INFO] serf: EventMemberLeave: debian03 192.168.0.103
          2015/12/02 10:58:49 [INFO] agent: requesting serf shutdown
          2015/12/02 10:58:49 [INFO] agent: shutdown complete

       debian01,debian02にはそれぞれmember-leaveのイベントが通知されているのが分かります。
      debian01
      2015/12/02 11:04:51 [INFO] serf: EventMemberLeave: debian03 192.168.0.103
      2015/12/02 11:04:52 [INFO] agent: Received event: member-leave

      debian02
      2015/12/02 10:58:49 [INFO] serf: EventMemberLeave: debian03 192.168.0.103
      2015/12/02 10:58:50 [INFO] agent: Received event: member-leave

      この場合、メンバーの確認すると 正常終了したサーバはleftと表示されます。

      root@debian01:~# serf members
      debian01  192.168.33.101:7946  alive 
      debian02  192.168.33.102:7946  alive 
      debian03  192.168.33.103:7946  left

       

      異常終了

      SIGTERMでプロセスを停止した場合やサーバの電源OFFなど、強制的にagentが停止された場合は他のノードがそのことを感知してイベントとして通知されます。debian03のagentをSIGTERM(9)で停止してみます。

      root@debian03:~# ps -ef | grep -i serf
      root      3607  3592  0 19:48 pts/0    00:00:00 serf agent -node=debian03 -bind=192.168.33.103 -join=192.168.0.102
      root@debian03:~# kill -9 3607
      この場合は他のメンバーがdebian03がアクセス不可になっていることを検出する形になります。
      debian01

      2015/12/02 11:19:28 [INFO] memberlist: Suspect debian03 has failed, no acks received
      2015/12/02 11:19:30 [INFO] memberlist: Suspect debian03 has failed, no acks received
      2015/12/02 11:19:31 [INFO] memberlist: Suspect debian03 has failed, no acks received
      2015/12/02 11:19:33 [INFO] memberlist: Marking debian03 as failed, suspect timeout reached
      2015/12/02 11:19:33 [INFO] serf: EventMemberFailed: debian03 192.168.0.103
      2015/12/02 11:19:34 [INFO] agent: Received event: member-failed
      2015/12/02 11:19:42 [INFO] serf: attempting reconnect to debian03 192.168.0.103:7946
      2015/12/02 11:21:12 [INFO] serf: attempting reconnect to debian03 192.168.0.103:7946
      ...
      ...

      debian02
      2015/12/02 11:12:24 [INFO] memberlist: Suspect debian03 has failed, no acks received
      2015/12/02 11:12:27 [INFO] memberlist: Suspect debian03 has failed, no acks received
      2015/12/02 11:12:28 [INFO] memberlist: Suspect debian03 has failed, no acks received
      2015/12/02 11:12:29 [INFO] serf: EventMemberFailed: debian03 192.168.0.103
      2015/12/02 11:12:30 [INFO] agent: Received event: member-failed
      2015/12/02 11:14:05 [INFO] serf: attempting reconnect to debian03 192.168.0.103:7946
      .....


      debian01,debian02にはmember-failedのイベントが通知されているのが分かります。またイベントを受け取ったあとも一定間隔でdebian03へのアクセスを試み続けます。

      この場合にクラスタのメンバをチェックするとfailedと表示されます。

      root@debian01:~# serf members
      debian02  192.168.0.102:7946  alive  
      debian03  192.168.0.103:7946  failed 
      debian01  192.168.0.101:7946  alive


      まとめ

      serfの起動と停止をためしてみました。今回はサーバの死活だけでしたがserfを利用するとサーバの状態を把握したり、イベントを受けて任意のスクリプトを実行したりすることができます。クラスタの管理自体も非集中型でシンプルなものになっておりそれぞれのサーバにserfのバイナリをコピーするだけで構成することが可能です。

    コメント

    このブログの人気の投稿

    SuperMicro Update Managerを試してみる

    SuperMicro社が提供している有償ツールのSuperMicro Update Manager(SUM)を試してみました。このツールを利用するとIPMIと同じ感覚でBIOS設定の確認や変更、BIOSファームウエアの更新が可能です。

    SuperMicro Update Manager SUM紹介ベージhttps://www.supermicro.com/solutions/SMS_SUM.cfm

    Linux起動中にBIOSの設定を確認したくなることありませんか。Windows環境のマシンであればそのようなツールもあるよう気もしますが、Linux上となるとあまり聞かないと思います。以前、Linux上でEFI変数を利用する方法を試してみたのですが、設定らしきものはバイナリデータになっていて詳細不明で、設定の変更はブートデバイスの優先順位くらいしか変更できませんでした。SuperMicro社が提供しているSuperMicro Update Managerを利用すると簡単に(同社のMB限定ですが)OS起動中にBIOSの設定を確認したり変更したりすることが可能になります。

    SUMの機能などの詳細な説明は上記のWebページに詳しく紹介されていますのでそちらを参照ください。今回はBIOS周りの機能を試してみました。

    SUMではツールを利用して以下のことが可能です。
    BIOS設定の取得現在の設定やデフォルトの設定などをテキストファイルベースで確認できます。BIOS設定の変更テキストファイルベースで設定の変更ができます。ただし変更を反映するには再起動が必要です。BIOSファームウェアのアップデートBIOSをアップデートをそのままの環境で実行できます(DOS環境はいりません)。ただしアップデートを反映するには再起動が必要です。 また対象のサーバにアクセスする方法として二つの方法あります。
    リモート(Out-band)でアクセスする。別のマシンでSUMを実行してネットワーク経由で対象サーバにアクセスするローカル(In-band)でアクセスする。対象サーバ上で起動しているOS(Llnux)上でSUMを実行して自分自身にアクセスする。 IPMIと同様に実際にBIOSの設定を取得したり変更したりするのを担っているのはMB上に搭載されているコントローラです。したがって、リモートでアクセスする場合…

    SATA12台でのRAID構成可能な1Uサーバ

    最近のサーバでは1Uサイズでも2.5インチのドライブを10台から12台搭載できます。しかし搭載しているRAIDカードが8ポートまで対応の製品のためにRAIDカードに接続可能なディスクは最大8台までという制限があり、残りのドライブは通常のSATAポート等に接続しなくてはならないという製品がほとんどでした。


    そこでせっかく12台搭載できるのだから12台でRAIDを構成したいというご要望にお応えしてこちら(EZ1D-Scalable-SATA12)の製品をご用意しました。





    サーバに搭載可能な2.5インチドライブ12台全てを利用してRAIDアレイを構成することができます。デュアルソケット対応でアプリケーションの処理性能も充分、12台で構成されたRAIDの性能をフルに発揮することが可能です。

    12台でRAIDを構成することにより8台での構成の場合と比較してより柔軟にRAIDを構築することができるようになります。また8台の構成では現実的でなかった特殊なアレイ構成も可能となります。
    12台のドライブによる大容量ストレージ2台のホットスペアを備えたRAID6 用途に応じた複数のRAIDアレイを1つのサーバ上に構築RAID50やRAID60といった特殊なアレイの構成
    ありそうでなかった12台対応RAID搭載1Uサーバ。ぜひご検討ください。

    製品の紹介ページ
    EZ1D-Scalable-SATA12 主な仕様
    CPU 対応CPU第2世代インテル® Xeon® スケーラブル・プロセッサー搭載CPU数2
    メモリ 最大容量1.5TB(1536GB)スロット数24タイプECC対応 2666MHz DDR4 SDRAM
    ネットワーク デュアルポート 1Gbpsイーサネットデュアルポート 10GbpsイーサネットRAIDコントローラSATA12ポート対応 RAIDコントローラ
    RAID 0,1,5,6,10,50,60対応
    キャッシュメモリプロテクションモジュール搭載ドライブベイ12 ホットスワップ対応 2.5インチ SATA/SAS ドライブベイ

    GUIDパーティションとMBRブート

    GUIDパーティションのディスクからGRUBで通常(MBR)起動する際のメモ。なんとなくやってできていたので気にしていませんでしたが、UEFIでのブートを試した際に今まで勘違いしていたことが分かったのでその点のまとめ GUIDパーティションディスクからの起動   GUIDパーティションテーブル(GPT)の規格はUEFI(EFI)の規格とセットであるが、GUIDパーティションテーブルのディスクからの起動にはEFIブートが必須というわけではない。
      Windowsの場合は無理な場合が多いが、LinuxではGPTのディスクからも従来通りの方法(MBRを利用した方法)での起動は可能。

    GUIDパーティションテーブル   GUIDパーティションテーブルの先頭のセクタ(LBA0)は従来のMBRと同じものになっている。これは互換性や安全性のため。GPTに対応していない機器にディスクを接続してしまったときに、ディスクと認識されなかったり、さらには初期化のされていないディスクと勘違いされていきなり初期化されたりしないようにするため。
      従来のMBRパーティションでは、MBR内にパーティション情報を格納してたが、GPTではここにはパーティションを情報を格納しない。MBRにつづく第2セクタ(LBA1)にあるパーティションテーブルヘッダおよび第3セクタからはじまるパーティションエントリに情報を格納する。
      MBRパーテョンでは基本パーテョションが4つまでであったり、大きなサイズ(2TB以上)のディスクを扱えなかったりしたのは、MBR内のパーティション情報を格納する領域の大きさ的にそれが限界であったため。
      GPTではこのパーテョション情報を格納する領域は十分に広い。パーティションは128個まで、ディスクサイズは8ZiB(ゼビバイト)まで扱える(もちろん、情報が格納できるというだけで実際に使えるかどうかはOSなどの対応による)

    MBRブート   MBRブートでのブートローダはMBR内に格納する。MBRのサイズは全体で512B(1セクタ)であるが上記のパーティションテーブル情報分があるのでブートローダに利用できる領域は446Bしか用意されていない。
      このサイズでは多機能なブートローダは格納できない。そこでGRUBなどの多機能なブートローダでは、MBR内には多機能なブートローダの本…