Ansible 2.0 になって使えるモジュールが大幅に増えましたが、その中に Consul 関係のモジュールがいくつかあります。前から気になってたので、ちょっと試してみました。
今回のお試し環境
ホストOS
- OS X Yosemite 10.10.5
- VirtualBox 5.0.10
- Vagrant 1.8.1
- Ansible 2.0.1
ゲストOS
- CentOS 7.2
Playbook
昨年末に Web サーバ1台、MariaDB サーバ1台、Cloudera QuickStart VM で Consul クラスタを組む playbook を作ったので、今回はこれを使いました。
- consul モジュールの検証に使った playbook
- muziyoshiz/hashicorp-sample: Sample configurations of HashiCorp tools
vagrant up
で以下の4台が起動して、Consul クラスタを組む- consul1: Consul サーバ
- mariadb1: MariaDB サーバ
- cdh-quickstart: Cloudera QuickStart VM
- manager1: Web サーバ(FuelPHP)
- この playbook の詳細は、2015年12月に発表したスライド2件(Embulk 関連、Otto 関連) - 無印吉澤 のスライドを参考のこと

Ansible 2.0 対応
以前作った playbook のままだと Ansible 2.0 での実行時に WARNING が出たので、事前に少し修正しました。
今回は 2.0 への移行については触れないので、そちらに興味のある方は、先週末に職場ブログに書いた記事をご参考ください。Ansible 2.0 への移行方法、移行時の注意点に関する詳細をまとめています。
話はちょっとズレますが、Consul は yum で配布されていないので、以下のように zip を落として解凍して……という処理をいちいち書いてます。Ansible 2.0 にアップグレードしたので、block を使って少し書き換えました。
hashicorp-sample/ansible/roles/consul_agents/centos7/tasks/main.yml
# Install unzip - name: Install unzip for unarchive module yum: name=unzip state=present # Install Consul if not installed - name: Check if consul is installed stat: path=/usr/local/bin/consul register: consul_bin - block: - name: Download and unzip Consul {{ consul_version }} command unarchive: src="https://releases.hashicorp.com/consul/{{ consul_version }}/consul_{{ consul_version }}_linux_amd64.zip" dest=/home/vagrant copy=no - name: Add execution permission to consul command file: path=/home/vagrant/consul state=file mode="0755" - name: Move consul command command: mv /home/vagrant/consul /usr/local/bin/consul when: not consul_bin.stat.exists # Create Consul agent common setting - name: Create consul setting directory file: path=/etc/consul.d state=directory owner=root group=root mode=0755 - name: Create common consul setting template: src="consul.service" dest="/etc/systemd/system/consul.service" owner=root group=root mode=0644 # Reload files under /etc/systemd/system - name: Call daemon-reload explicitly because service module does not call it command: systemctl daemon-reload # Start consul and create autostart setting - name: Autostart Consul service: name=consul state=started enabled=yes
Consul 関係のモジュール
Ansible 2.0 Has Arrived によると、Ansible 2.0 は200個以上の新モジュールを含む、とのこと。All Modules — Ansible Documentation を見る限り、Consul 関係では以下の4個が新たに追加されたようです。
- consul (E) - Add, modify & delete services within a consul cluster.
- consul_acl (E) - manipulate consul acl keys and rules
- consul_kv (E) - Manipulate entries in the key/value store of a consul cluster.
- consul_session (E) - manipulate consul sessions
今回は、一番使いそうな consul モジュールを試してみました。
consul モジュールで書き換えるとこうなる before/after
before
consul モジュールを使わない場合、Consul にサービスを追加する playbook はこんな感じになります。これは、何らかの管理機能を提供する Web サーバを、Consul にサービスとして登録する例です。
hashicorp-sample/ansible/roles/managers/tasks/main.yml
# Create Consul client settings - name: Create manager service information for consul template: src="consul/manager.json" dest="/etc/consul.d/manager.json" owner=root group=root mode=0644 - name: Restart consul service: name=consul state=restarted
hashicorp-sample/ansible/roles/managers/templates/consul/manager.json
{ "service": { "name": "manager", "port": 80, "check": { "script": "curl localhost:80 >/dev/null 2>&1", "interval": "15s" } } }
after
単純に考えると、こう書けば OK そうな気がします。Before とは違って、テンプレートは不要になります。簡潔ですね。
- name: Register manager service consul: service_name: manager service_port: 80 script: "curl localhost:80 >/dev/null 2>&1" interval: 15s
これを実行すると、こんなエラーが出て失敗します。
TASK [cdh_quickstart : Register manager service] ******************************* fatal: [cdh-quickstart]: FAILED! => {"changed": false, "failed": true, "msg": "python-consul required for this module. see http://python-consul.readthedocs.org/en/latest/#installation"}
consul モジュールのページを見て、最初はホストOSに python-consul を入れろということなのか?と誤解してしまったのですが、ゲストOSの方に入れないと駄目みたいです。python-consul のインストールには pip が必要なので、修正後は以下のようになります。
- name: Install pip yum: name=python-pip state=present - name: Install python-consul pip: name=python-consul state=present - name: Register manager service consul: service_name: manager service_port: 80 script: "curl localhost:80 >/dev/null 2>&1" interval: 15s
これで python-consul のエラーは出なくなったのですが、今度は以下のエラーが出たり出なかったりするようになりました……。
TASK [managers : Register manager service] ************************************* fatal: [managers]: FAILED! => {"changed": false, "failed": true, "msg": "Could not connect to consul agent at localhost:8500, error was HTTPConnectionPool(host='localhost', port=8500): Max retries exceeded with url: /v1/agent/services (Caused by NewConnectionError('<requests.packages.urllib3.connection.HTTPConnection object at 0xef5650>: Failed to establish a new connection: [Errno 111] \\xe6\\x8e\\xa5\\xe7\\xb6\\x9a\\xe3\\x82\\x92\\xe6\\x8b\\x92\\xe5\\x90\\xa6\\xe3\\x81\\x95\\xe3\\x82\\x8c\\xe3\\x81\\xbe\\xe3\\x81\\x97\\xe3\\x81\\x9f',))"}
ローカルで動作する consul agent に接続できない、というメッセージに見えます。このタスクより前に agent は起動しているんですが……。色々試してみたところ、consul モジュールの実行前に agent を再起動すれば、このエラーは出なくなりました。
最終形はこんな感じ。
hashicorp-sample/ansible/roles/managers/tasks/main.yml
- name: Install pip yum: name=python-pip state=present - name: Install python-consul pip: name=python-consul state=present - name: Restart consul service: name=consul state=restarted - name: Register manager service consul: service_name: manager service_port: 80 script: "curl localhost:80 >/dev/null 2>&1" interval: 15s
この hashicorp-sample は dnsmasq の設定も行っているので、$ dig @127.0.0.1 -p 8600 impala.service.consul SRV
と問い合わせると IP アドレスが返されます。また、この manager の Nginx を停止させると、IPアドレスが返されなくなります。
まとめ
pip と python-consul のインストールを要求される割に、consul モジュールを使わない場合と比べて、それほど簡潔な表記にはなりませんでした。1台のマシンで複数のサービスを起動するような場合には、テンプレートファイルを減らすことができるので、それがメリットでしょうか?
あと、これはユースケースによっては致命的だと思うのですが、 consul モジュールで登録したサービスは consul agent を再起動すると消えてしまいます 。実サービスで使う場合、consul agent が落ちるたびに playbook を最初から実行しなおし、という想定なのでしょうか。また、今回のように Vagrant の provisioner として Ansible を使う場合も、playbook は(明示しないと)初回起動時にしか実行されないので、これはちょっと不便ですね。
とりあえず動かすことはできたものの、個人的にはこのモジュールの使いどころがちょっと良くわからないな……という感想でした。