サービス検出を使った自動化を行うために、Consulを使って具体的にクライアント・サーバ構成を構築しましょう。複数のサーバ上でサービスを定義し、NginxのDNSラウンドロビンを行う方法を見ていきます。
サービスの可用性を高めるConsul
複数台のサーバ構成によって、Webサーバであれば通信量やアクセスの負荷分散を図ることができます。あるいは、データベースやキャッシュ用のサーバを冗長化構成にすることで、障害発生時におけるサービスの継続性(稼動時間)を高めることもできます。
クラウド技術の普及により、インフラであるサーバ環境は簡単に増減できるようになりました。その一方で、負荷分散や冗長化は、手動で行う設定に頼りがち。動的に変わるサーバ環境に応じて設定を変更するためには、何らかの手間なり工夫が求められています。
このような課題を簡単に解決すべく登場したのがConsulです。Consulが持つ機能の1つにサービス検出(service discovery)があります。Consulが認識するサービスとは、対象となるWebサーバやデータベースのデーモンが存在しているかどうかだけでに限りません。指定のポート番号に対するアクセスの正常性も判別することができます。
また、Consulは独自にDNSを持ちます。そのため、ローカル環境やプライベートなネットワーク空間内でも利用可能です。活用できるのは、ホスト名からIPアドレスの名前解決を自動的に行えるだけでなく、サービス検出に応じた動的な名前解決もできます。これを使えば、クライアント側はホスト名を定義しておくだけで、正常に稼働しているキャッシュ用サーバやデータベースのIPアドレスを知るような応用が可能です。
Consulは、そのサービス状況をConsulのDNSやHTTPのインターフェースから参照できるだけではありません。サービスが正常か異常か、それらの変化が発生したタイミングで、任意の処理を自動的に行うこともできます。
このConsulの機能を使えば、Webサーバの負荷分散の自動化も行えます。Webサーバ上でApacheやNginxなどのサービスが応答する間、負荷分散の対象となるだけでなく、正常に応答できないときは自動的に対象から外すことも容易になります。
Nginxの負荷分散にConsulを使うには
それでは、実際にConsulを使って、サービス検出の流れや挙動を見ていきましょう。ここでは、ローカル環境でNginxのDNSラウンドロビンを行います。
同一ネットワーク上で、3台のサーバ(インスタンスや仮想サーバ等)を用意します。それぞれのサーバ上でconsulエージェントを稼働し、Nginxの負荷分散環境を構築します(図1)。
- Consulサーバ:HTTP・DNSインターフェースを持つ。1台(192.168.39.3)のみ。
- Consulクライアント:サービスが稼働する環境を想定。2台(192.168.39.11、192.168.39.12)で構成。
Consulサーバのセットアップ
Consulのセットアップの他に、DNSの名前解決用にBINDとdnsmasqをセットアップします。
まず、ConsulサーバではConsulエージェントを“server”モードとして起動します。
セットアップ後は、Consulサーバを次のように実行します。nohup
を使ってバックグラウンドでConsulサーバを起動するのは、ログアウト後もエージェントを起動し続けるためです。
正常に起動したかどうかは、consul members
コマンドでも確認できます。「Type」が「server」となっていることに注意します。
次にdnsmasqの設定を行います。ConsulのDNSインターフェースはポート8600を使用するため、アプリケーションやdig
等のコマンドでConsulの名前解決を行う場合は、都度明示しなくてはいけません。ポートを指定しなくても、アプリケーションやcurl
やping
等のツールで名前解決を手軽に行うのがdnsmasqです。
以下はCentOSにおけるセットアップ例です。
必要に応じて/etc/resolv.conf
も書き換えます。自分自身で名前解決を行うためnameserver 127.0.0.1
を既存の指定よりも前の行に記述します。
それからdnsmasqを起動します。
正常に名前解決を行えるか確認します。host
コマンドを使い、server
というノード名称を持つIPアドレスを確認します。
名前解決の確認ができれば、同様にping
などコマンドライン上から利用できることがわかります。
これでConsulサーバー側の準備が完了しました。
Consulクライアントのセットアップ
次は、Consulノード側のセットアップです。Consulエージェントを“client”モードとして稼働し、サーバ上のNginxを“web”という名称のサービスとしてConsulに登録します。1台目のNginxサーバの名前をnode1
、2台目をnode2
と設定することにします。
まず始めに、Nginxのセットアップを行います。
curl
を使って動作確認をします。正常に設定が終わっていれば、次のようにnode1
という文字列が画面に表示されます。これはホスト名を確認用するためでなく、サービス正常性を確認するConsulのヘルスチェック用としても使います。
次にConsulエージェントのセットアップです。先ほどのConsulサーバと同様に行います。
以上の動作を2台目のサーバでも繰り返します。このとき、ホスト名のnode1
の箇所はnonde2
に置き換えての実行をお願いします。
Consulへのサービス登録準備
それではConsulにサービスを登録します。サービス登録には、Consulエージェントを起動し、Consulサーバに接続する必要があります。
あらかじめ、設定ファイルを置くためのディレクトリを作成します。さらに、サービス定義用のファイルを作成します。ファイルの書式はJSON形式です。
ここでは“web”という名称のサービスを定義します。タグにはnginx
を指定しています。重要なのはcheck
で囲まれたブロックです。script
で“web”サービスが正常(passed)とみなす条件を指定しています。内容はcurl
コマンドでconsu.html
が取得可能かで判断します。またinterval
は、このscript
を実行する間隔です。10s
は10秒ごとにという指定です(任意の秒数を指定できます)。さらにtimeout
でタイムアウト秒数を指定しました。
今回はcurl
を使いましたが、ping
でも任意のコマンドを指定できます。Consulは終了コードによってサービスの状態を区別します。終了コード0
であれば正常(passing)と見なされます。1
の場合は警告(warning)であり、終了コードが無い場合は障害(failing)となります。
Consulエージェントの起動とサービス登録
準備が整ったら次のようにConsulを起動します。
ここで指定したオプションは、それぞれ次のような意味があります。
-data-dir
- Consul用のデータ保存に使うディレクトリです。
-node
- このConsulノードの名称であり、Consulクラスタ内で重複できません。
-bind
- 使用するIPアドレスを明示しています。
-config-dir
- 設定ファイル用のディレクトリを指定し、対象以下の
.json
ファイルを読み込みます。
-join
- ConsulサーバのIPアドレスを指定します。この例では
192.168.39.3
です。
正常に実行すると、次のようにメッセージが画面に表示され、この時点でConsulクライアントとして登録されただけでなく、web
サービスが認識されたことがわかります。
consul members
コマンドを実行すると、Consulクラスタとしてのメンバ情報も確認できます。
動作確認として、Consulサーバ上(192.168.39.3)で名前解決の確認を行いましょう。Consulはノード(サーバ、クライアントどちらも含みます)のIPアドレスをノード名称で名前解決できます。
この機能を使えば、クラウドのように動的にIPアドレスが変わる環境でも、Consulエージェントでクラスタを構成する限り、同じホスト名称でアクセスし続けることができます。
更にweb
サービスの登録状況を確認します。Consulは登録したサービス名で名前解決が可能です。先ほど登録したサービスweb
の情報を持つIPアドレスを調べるには、web.service.consul
という名前で名前解決を試みます。正常に処理されると、次のようにIPアドレスを確認できます。
同様にcurl
を使って動作確認してみましょう。ホスト名をweb.service.consul
と指定することで、Consulとdnsmasqが自動的に名前解決をしてくれます。
2台目のサービスを登録
それでは、もう1台のConsulクライアントを起動します。先ほどと設定は同じですが、-node
のノード名称と-bind
のIPアドレスが違うだけです。
この状態でconsul members
コマンドを実行すると、新しくConsulクライアントが追加されたことがわかります。
また、サービスweb
が登録されているかどうかも、再びdig
コマンドで確認します。すると、次のように2つのIPアドレスが表示されることがわかります。
この状態でweb
サービスに対するDNSラウンドロビンが行えるようになります。curl
コマンドを何度か実行すると、2台に交互にアクセスしていることが確認できます。
サービス障害と名前解決
引き続きConsulのサービス検出機能を見ていきます。例えば、障害によってNginxが停止したらどうなるでしょうか。node1サーバにログインし、nginxを停止します。
Consulサーバ上でdig
を実行すると、停止したnode1のIPアドレスは表示されず、node2のIPアドレスのみ表示されていることがわかります。
まとめ
今回はNginxのサービス検出をDNSで行う方法を見てきました。Nginxに限らず、Consulはスクリプトで識別できるものであれば、プロセスの存在状況や、APIの処理結果など、任意のものをサービスとして定義できます。
次回はこのサービス検出をトリガとして、自動処理に応用したり、複数台のサーバー上でコマンドを実行する方法を見ていきます。
参考情報