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

第8回(最終回) 定型作業を自動化するConsul Template

Consul Template

これまでの連載の応用として、最後にConsul Templateをご紹介します。SerfやConsulを使えば、複数台のサーバやLinuxコンテナ上で、様々な処理を同時に行うことができます(イベントハンドラ機能⁠⁠。実行は任意のタイミングで行えるだけでなく、ノードの増減やサービスの増減に応じて自動的に実行できることが特徴です。

自動実行は、増減のタイミングでコマンドを実行するだけでなく、管理用のファイルやロードバランサ等の設定ファイルを書き換えにも利用できます。通常は、設定を書き換えるためのスクリプトやプログラムを準備する必要がありました。

この設定ファイルの自動書き換えに特化したプログラムがConsul Templateです。その名前の通り、Consulクラスタと連携します。あらかじめテンプレート元になるファイルを用意しておくことで、Consul上でのノード名やIPアドレス等の情報を、自動的に設定ファイルに反映します。それだけでなく、オプションとしてコマンドの実行によるデーモンの再起動を行うことができます。

Consul Templateを活用する事で、たとえば/etc/hostsやAnsibleのインベントリなど、ホスト管理用のファイル書き換えができます。あるいは、NginxやApacheのプロキシ設定を動的に書き換えた後、デーモンの自動再起動も行います。

これは運用担当者にとっては非常に有用な機能です。クラウドのように、動的にIPアドレスが変化する環境でも、設定の追加や削除を正確かつ迅速に行えるようになります。また、開発担当者にとっても、検証環境などで設定変更をしたいとき、その都度自分で作業したり、運用担当とやりとりしたりする手間を軽減できます。

動作原理

Consul Templateはデーモンとしてサーバに常駐し、Consulサーバ上のKVSの情報をローカルまたはリモートから監視します図1⁠。Consulノードの状態やサービスの正常性に変化が発生すると、KVSの情報が書き換わります。

Consul TemplateはConsulの持つHTTPインターフェースを経由して、KVSの情報を常時監視しています。Consul TemplateがKVS値の変化を検出すると、テンプレート用ファイルを元に、新しいファイルを自動的に作成します。なお、ノード名やサービス名が変数として定義されている場合、それらもファイルに反映します。

このとき、ファイルを新しく作成だけでなくだけでなく、オプションで任意のコマンド実行もできます。たとえば、設定を反映するためのコマンドや、パーミッションの変更、デーモンの再起動などのコマンドを自動実行させることができます。

図1 Consul TemplateとConsulクラスタの関係
図1 Consul TemplateとConsulクラスタの関係

Consul Templateの利点

Consul Templateの利点の一つは、実行時にバイナリを1つしか必要としないため、起動や各種設定が非常にシンプルに行える点です。Consul TemplateはConsulサーバがローカルでもリモートでも動作するため、Consulエージェントが動いていないサーバ上でも使えます。

また、設定時の確認や動作検証を楽にするため、反映状況を画面に出すだけのドライモードを備えています。その他、デバッグの為の豊富なメッセージ情報の表示や、syslogにログを出力する機能も備えています。

セットアップ方法

consul-templateデーモン

Consul Templateはバイナリやパッケージが提供されていません。そのため、ソースコードを取得して、自分で環境を作ります。以下はLinux(CentOS)上で、Go言語の開発環境を整え、GitHubからソースコードを取得し、バイナリを作成します。

$ sudo yum -y install git golang
$ export GOPATH=/usr/local/src/go
$ git clone https://github.com/hashicorp/consul-template.git
$ cd consul-templae
$ make
$ sudo cp ./bin/consul-template /usr/bin/consul-template
$ consul-template --version
consul-template v0.7.1.dev

Consul環境のセットアップ

Consul Templateを動かす前提として、Consulが動いている必要があります。最低限、1台のConsulサーバ上でノードまたはサービスを認識します。動作にあたって、Consulが動作する環境をお持ちの場合は、そちらを利用することもできます。

ここでは例として、1台のConsulサーバと、2台のConsulクライアントでクラスタを構成します図2⁠。ノードは必要に応じて、増減して頂いて構いません。

図2 consul-templateをサーバ上に設定する構成
図2 consul-templateをサーバ上に設定する構成

Consulサーバでは、エージェントをサーバモードとして起動します。

$ consul agent -server -bootstrap-expect=1 -data-dir=/opt/consul/data -bind=192.168.39.3

Consulノードも同様に起動します。このとき-nodeで何らかのノード名称を指定しておきます。

$ consul agent -node=web1 -bind=192.168.39.11 -data-dir=/opt/consul/data -join=192.168.39.3

/etc/hostsを自動的に書き換えるには?

ローカル環境でサーバを立てると、ホスト名とIPアドレスの名前解決を行うためには、ローカルのDNSサーバを準備するか/etc/hostsファイルを書き換える必要があります。しかし、DNSサーバを立てると管理の手間が発生しますし、サーバが増減すると、都度DNSレコードを書き換えなくてはいけません。一方の/etc/hostsファイルの書き換えは管理は不要となりますが、やはり書き換えの手間が発生します。

/etc/hostsの管理は、Consul Templateを使うことで自動化できます。ConsulエージェントがConsulクラスタに参加した時点で、自動的にIPアドレス・ホスト名の情報を追加します。それだけでなく、Consulクラスタから離脱すると、自動的に設定を削除できます。

テンプレートファイルの用意

Consul Templateを実行する前にテンプレートとなるファイルを準備します。任意の場所でhosts-node.ctmplという名称のファイルを作成し、次の内容にします。

# consul nodes{{range nodes}}
{{.Address}}    {{.Node}}{{end}}

このように、テンプレートとはテキスト形式のファイルです。ノード名に応じて繰り返す範囲を{{range node}}{{end}}で指定します。{{.変数名}}では、ホスト名やIPアドレスを変数として扱えます。

ドライモードで動作確認

Consul Template起動時の書式は次の通りです。-consulで参照先のConsulサーバを指定します。-templateオプションで、どこにファイルを書き出し、何を実行するかを定義できます。複数行の実行が可能です。

$ consul-template -consul <ConsulサーバのIPアドレス>:<HTTPインターフェース> \
    -template "テンプレート元のファイル名:出力先ファイル名:コマンド(オプション)" \
    -template "同上" (オプション) \
    -dry (オプション)

-dryオプションを使うと、実際にファイルは出力しない代わりに、設定変更をリアルタイムで標準出力に表示します。ドライモードで起動してみましょう。

$ consul-template -consul 127.0.0.1:8500 \
    -template "./hosts-node.ctmpl:/etc/hosts" \
    -dry

起動すると、その時点でConsulクラスタを形成しているノード情報の一覧が表示されます。Consulサーバが1台しかない状態では、次のような表示となります。

# consul nodes
192.168.39.3    sion.pocketstudio.nnet

この状態で、ConsulクライアントをConsulクラスタにjoinさせると、自動的に画面が切り替わります。web1・web2それぞれのクライアントを起動すると、次のようにホスト名・IPアドレスが自動的に反映されます。

# consul nodes
192.168.39.3    sion.pocketstudio.net
192.168.39.11    web1
192.168.39.12    web2

またエージェントを停止したりクラスタから離脱すると、自動的に離脱したホスト情報が削除されることも確認できます。以下はweb1を停止したときの表示です。

# consul nodes
192.168.39.3    sion.pocketstudio.net
192.168.39.12    web2

このように動作確認して問題がなければ、実際に設定を反映してみましょう。一旦consul-templateはCtrl+Cで停止した後、再び起動し直します。

$ consul-template -consul 127.0.0.1:8500 \
    -template "./hosts-node.ctmpl:/etc/hosts"

 今度は-dryオプションがないため、ノードの状態変化が発生すると、都度/etc/hostsを直接書き換えられることがわかります。

サービス毎に応じてグルーピングするには?

先の例では、Consulクライアントのノードであれば、無条件にテンプレートに反映していました。Consul Templateはサービス毎にファイルを書き換えることができます。次のテンプレートを用意してみましょう。新しく{{range services}}という項目が増えています。これはサービス単位で繰り返すことを表すテンプレートの記法です。

{{range services}}# {{.Name}}{{range service .Name}}
{{.Address}}    {{.Node}}{{end}}

{{end}}

このテンプレートを使ってconsul-templateを実行すると、/etc/hostsはConsulのサービス名称毎にグループ化されて表示されますので、どのサーバが何の役割を持っているか確認する用途に使う事もできます。

# consul
192.168.39.3    consul-server

# web-server
192.168.39.11   web1
192.168.39.12   web2

Webサーバへの応用例

Consulはエージェントの参加・離脱だけでなく、サービスの正常性についても検出することができます。これを応用すると、Webサーバが正常に応答している時だけ、自動的にproxy設定に登録する事ができます。

Nginxを使ってproxyを使う場合であれば、次のproxy.confのようなテンプレートファイルを用意します。新しくservice "web"という項目が増えています。これは、Consul上でwebという名称のサービスが存在する場合のみ、そのポートやアドレスを追加するものです。

upstream frontend { {{range service "web"}}
    server {{.Address}}:{{.Port}};{{end}}
}

server {
    listen 80 default_server;
    location / {
        proxy_pass http://frontend;
    }
}

各々のConsulクライアントでは、Consulの設定ファイルを用意し、エージェント起動時に読み込ませます。次の設定は、10秒毎にローカルのWebサーバにアクセスし、応答があればwebという名称のサービスが正常に稼働していると定義するものです。

{
  "service": {
    "name": "web",
    "tags": [ "nginx" ],
    "port": 80,
    "check": {
      "script": "curl http://127.0.0.1:80/ >/dev/null 2>&1",
      "interval": "15s",
      "timeout": "5s"
    }
  }
}

Consul Templateでは、設定を反映するためにNginxの再起動オプションを付与して起動します。また、Consulサーバが応答しない場合は30秒でリトライする設定も追加しました。

$ consul-template \
    -consul 127.0.0.1:8500 \
    -template "/opt/consul-template/nginx.conf:/etc/nginx/conf.d/proxy.conf:service nginx restart" \
    -retry 30s

これで、Consulクライアントの状態だけでなく、クライアント上のサービスの稼働状態に応じて自動的にNginxの設定ファイルを書き換えられるようになります。

今回のまとめ

Consul単体でのオーケストレーション機能を使うには、自分で実行用のスクリプトを用意する面倒さがありました。Consul Templateは日常業務における面倒な設定作業を、Consulのサービス検出機能と連携して自動的に処理してくれます。設定ファイルの書き換えとコマンドが実行できる場面であれば、監視の自動設定であったり、デプロイ用ツールの自動実行などに応用が期待できます。

連載のまとめ

一連の連載を通して、SerfやConsulの基本的な使い方や応用方法を見てきました。紹介した以外にも、多くの設定オプションが用意されています。

自動化や効率化にあたって、必要とされている機能や役割は、皆さんの現場によって異なると思います。もし活用できそうな場面があれば、SerfやConsulを使うことで、本来やりたいことや業務に集中することへの貢献ができればと願っています。

参考情報

おすすめ記事

記事・ニュース一覧