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

第4回Consulのサービス検出と様々なインターフェース

前回までの連載は、Serfを使ったクラスタの構築や、イベントハンドラを使って一斉にコマンドを実行する方法を見てきました。今回からはSerfではなく、Consulを用いたクラスタの管理や、サービスの監視、自動処理のしかたを学んでいきます。

ConsulはSerfと同じく、面倒な手作業を自動化または省力化するための役割を持っています。ですが、両者の機能や使い方には様々な違いがあります。今回はSerfとConsulの違いと、Consulの基本的な機能・特徴について扱います。

Consulの主な機能と特徴

Consulは、Serfと同様にHashiCorpがオープンソースとして公開・開発しているソフトウェアです。Serfより後の2014年春に初リリースされ、以降はGitHubやIRCを通して議論・開発が行われています。

Consulの機能の1つに、クラスタのメンバー管理機能があります。これはSerfと同じ機能であり、Consulはクラスタ管理機能の一部に、Serfのモジュールを内包しています。Serfはクラスタ内のメンバー管理機能と、コマンドを同時実行するオーケストレーション機能を提供するためにも、Serfエージェント間の通信を土台としています。

リリース当初のConsulは、Serfの一部機能(メンバー管理)しか使えませんでした。現時点(v.0.5)では、イベント同時実行のオーケストレーション機能を含め、Serfが提供する機能の大部分はConsulに統合されています。

機能だけでなく、SerfとConsulはコマンドライン上での操作も部分的に似ています(例:メンバーの一覧を表示するconsul members⁠。ですが、Consulの機能はSerfのメンバー管理やオーケストレーションだけではありません。

Serfでできなかったサービス監視を実現

SerfとConsulの違いは何でしょうか。両者の一番大きな違いは、サービス監視の有無です。ConsulはWebサーバやデータベースの状況変化をトリガとして、様々な自動処理に応用することができます。

Serfが自動実行するイベントの発生タイミングは、あくまでSerfエージェント間の通信状況か、ユーザ自身によるイベント実行が必要です。そのため、もしSerfエージェントが正常に動いていたとしても、Webサーバやデータベースに問題が発生している場合もあり、それを直接Serfエージェントが知ることができません。

このSerfの弱点を解決するのが、Consulです。Consulは、Serfと同様の機能に加え、任意のサービスに対する状態監視を行うことができます。Consulにおけるサービスとは、Consulの中でApache HTTP Server・NginxのようなWebサーバ、MySQLやPostgreSQLのデータベース、各種デーモン等の稼働状況を定義するものです。

図1 SerfとConsulで異なるクラスタ範囲
図1 SerfとConsulで異なるクラスタ範囲

Consulはそれぞれのサービスに対する正常性の確認(ヘルスチェック)を行います。また、監視対象はサーバの中だけに限りません。ネットワーク機器に対するpingや、クラウド上のサービスAPIをアクセスした結果に対してもサービスとして定義できます。

そして、そのサービス状態はConsulのインターフェースを通して参照できます。Web UIを通せば、人によって視覚的にサービス状態を参照できます。DNSインターフェースであれば、サービスの正常性とDNSの名前解決をリアルタイムに同期します。HTTPインターフェースはREST APIを通してサービス状態を参照できるだけでなく、その変化に応じて任意のコマンドの自動実行も可能となります。

Consulの主な機能

Consulの主な機能は、次の通りです。

  • サービス検出機能と障害検知
  • キーバリューストレージ機能と複数のインターフェース
  • マルチデータセンター対応
  • 周辺ツールとの連携

これらのConsulが提供する機能群は、Serfと同様に、何らかのシステム変化に対する自動的な処理機能を提供するものです。以下では、それぞれの機能について詳しく見ていきます。

サービス検出機能(service discovery)

サービス検出とは、Consulクラスタが稼働するシステム全体において、どのサーバ上でどのようなサービスが稼働しているか、そして、それらは正常か異常かどうかを確認する機能です。

Consulクライアントは、主にサーバ上のデーモン(NginxやMySQL等)をサービスとして定義します。サービスの定義はエージェント起動時にJSON形式の書式で定義するか、後述するREST APIを通して行います。以下はサービスの定義例です

Webサーバを監視する定義
{
  "service": {                                      # サービスの定義開始
    "name": "web",                                  # サービス名称を「web
    "port": 80,                                     # ポート番号は「80
    "check": {                                      # ヘルスチェックの定義開始
      "script": "curl localhost:80 >/dev/null 2>&1",# curlでローカル環境の監視
      "interval": "10s"                             # 監視間隔
    }
  }
}

定義されたサービスに対して、Consulクライアントは定期的にヘルスチェックを実行します。ヘルスチェックはサービス毎に任意の秒数で指定します。

Consulクライアントはサービス毎に正常か異常かを把握し、この情報に変化があれば直ちにConsulサーバに通知します。また、このサービスはREST APIを使った登録も可能です。

サービスの情報はConsulサーバ上のKVSに格納され、この情報はWeb UIやDNS・HTTPの各インターフェースから参照できます。

図2 Consulのサービス検出と参照
図2 Consulのサービス検出と参照

キーバリューストレージ(以下KVS)

KVSはConsulサーバが持っている機能の1つです。KVSは「キー」「バリュー」という一対の組み合わせを持つデータベースの役割を持っています。

KVSにはConsul内部でシステムが自動的に使用する領域と、ユーザが自由に利用できる領域があります。システム領域には、Consulエージェントから送られてきたサービス検出の情報や、ヘルスチェック情報に加え、Consulサーバの管理情報が含まれています。

Web UI・DNS・HTTPの各インターフェース

Consulメンバーやサービス状態は、複数のインターフェースを通して参照・変更できます。

Web UI

ブラウザを通し、人の目でデータセンター(ネットワーク)毎にConsulノードの稼働状況や、その上で動いているサービスの稼働状況を視覚的に把握できます。各サービスのヘルスチェックの詳細だけでなく、KVSのデータ参照・更新も行えます。

DNSインターフェース

hostコマンドやdigコマンドでConsulノード名やサービス名称の名前解決ができます。これを応用して、ローカル環境におけるホスト名・IPアドレスの名前解決を自動的に行ったり、WebサーバやデータベースのDNSラウンドロビンに応用したりできます。

HTTPインターフェース

REST APIを通してKVSの情報を取得し、編集することができます。Web UI自身、実際はREST APIを通して様々な情報を取得しています。

マルチデータセンター対応

複数のネットワークを跨がってConsulサーバ同士のクラスタを形成します。これは、ローカルのConsulサーバ・クライアント間で通信するものとは別に、リモート上の異なるConsulクラスタと通信ができるようにします。

この機能によって、リモートからConsulクラスタのメンバー情報を参照するだけでなく、サービス状況についても確認できます。

周辺ツールとの連携

ConsulはAPIを持っていますので、(周辺ツール)[http://www.consul.io/downloads_tools.html]と連携してConsulの機能を拡張できます。

HashiCorpが提供しているオフィシャルツールは3つです。

Envconsul

ConsulのKVSを通して環境変数の取得・設定を行うツール。KVSのデータ変更をトリガに、任意のコマンド実行も可能。

Consul Replicate

ConsulのKVSを複数のデータセンターでも利用できるように複製するツール。

Consul Template

サービスの状態変更時、既定のテンプレートを元に動的に設定ファイルを作成し、必要に応じて任意のコマンド実行による再起動が行えるツール。

その他、各種の開発言語に対応したライブラリや、Consul-Alertsのようにコミュニティ有志によるツールもあります。

Consulはクライアント・サーバ型の構成

Consulは「consul」というバイナリファイル1つで実行できるものです。起動時にサーバモードとして動作するか、あるいはクライアントとして動作するかを選びます。また、Serfと異なり、Consulはクライアント・サーバ型の構成です。

図3 Consulの構成
図3 Consulの構成

Consulサーバ

Consulサーバの役割は主にデータの保全です。Consulクライアントからクライアント上の様々なデータを取得し、それを自身のKVSに保管します。データは保管しておくだけでなく、Consulサーバには、次の役割があります。

  • Consulノードの情報を記録する
  • KVSにデータを格納する
  • 複数のインターフェースからKVSの情報を返す
  • 他のネットワーク上のConsulサーバと通信する

ConsulクライアントはSerfのように複数ですが、Consulサーバも複数のクラスタを構成します。Consulサーバはマスタとスレーブに分かれており、通常はマスタが全ての情報を管理します。もしマスタに障害があれば、残ったスレーブのうちのどれか1台がマスタに昇格します。

このような冗長性を確保するために3台以上での構成が推奨されています(Raftプロトコルを用いた通信を行い、相互監視するため⁠⁠。なお、Consulの機能確認や動作検証が目的であれば、1台からでも動作します。

Consulノード

Consulノードは、Consulサーバの手足のような役割を持ちます。コマンドラインのクライアントとして、サーバに対して命令を出し、情報を取得します。

また、自分自身の死活監視や、自身のサーバ上などで稼働するリソースを確認します。実際にサービスの検出や、死活状況の確認を行うのはノードです。各々のノードで逐次状況の監視を行い、変化があれば、直ちにサーバ側に伝えます。

Consulの活用例:DNSインターフェースを通した汎用メンバー管理

Consulが独特なのはDNSのインターフェースを兼ね備えていることです。たとえば、インターネットに出ていないローカル空間における名前解決は、通常内部にDNSサーバを立てたり、あるいは台数が少なければ/etc/hostsを管理します。ところが、クラウド環境やコンテナ・仮想化環境においては、頻繁にホストやコンテナの追加・削除が繰り返されます。

そのような場合、都度DNSサーバの設定を書き換えたり、各サーバのhostsを書き換えたりするのはかなりの手間になります。これをSerfを使って/etc/hostsの書き換えやDNSサーバのゾーンファイルを書き換える方法もありますが、Consulを使えば、Consulのメンバー情報だけでなく、その中のアプリケーションに関する名前解決もできるようになります。

たとえば、単純にホスト名の追加・削除だけであれば、Consulエージェントの追加・削除だけで自動的に名前解決できます。便利なのは、特定のアプリケーションの稼働状況、たとえばポート80番の応答があればWebサーバが稼働しているとみなし、その稼働しているWebサーバの情報で名前解決ができます。

Consulは監視ツールなのでしょうか?

Consulにはクライアントを通して、サーバ内で何のプロセスが稼働しているかや、コマンドラインの実行結果を基に正常か異常かを判断する仕組みがあります。これは以前からある監視ツールとは何が違うのでしょうか?

死活監視を行いますが、これまでの監視ツールとは違ったものと言えます。たとえば、Consulは、Zabbixのようにサーバ内のプロセス稼働状況監視や、コマンドを実行した結果の正常性を評価することはできます。決定的に違うのは、監視の主導権がエージェントにある点です。Zabbixでは通常、監視の主導権はサーバ側にあり、サーバが、クライアントに対して状態を訊ね、その結果をサーバに返します。つまり、サーバが障害で停止したり、経路上のネットワークに問題があると、一次対応コマンドの実行をトリガとするだけでなく、監視そのものが停止してしまいます。

一方のConsulの場合、あくまで監視の主体はクライアント側にあります。何をどのように、どのくらいの時間間隔で監視するかは全てクライアントが決めることです。サーバはあくまでクライアントからの情報を保存しておくための役割と、その結果を返すためのインターフェースを持っているにすぎません。そして、その変化があれば何かアクションを起こし、元の状態に戻そうとします(これは、Consulの中ではアンチエントロピーと呼ばれている機能です⁠⁠。

そしてConsulの大きな特徴の1つであるイベントハンドラは、このクライアントの状況変化をトリガとするだけでなく、KVS上のデータの変化に応じて様々なアクションを起こすような応用に使えます。

まとめ

Consulの概要とSerfの違いは、単純にクライアント・サーバ型の違いだけでなく、機能面でも監視するためのレイヤーが違うことを見てきました。次回はConsulを使ってクラスタを構成し、設定方法や様々なインターフェースの扱い方を見て行きます。

参考資料

おすすめ記事

記事・ニュース一覧