Overview
普段Ansibleを使っているがinventory管理が思いのほか大変で、ホスト追加の度にinventoryファイルを編集とかしてた。
が、 dynamic inventory というものがあるのを最近知ったので使ってみる。
簡単にいうと、動的にAnsibleのinventoryホストを生成することが出来る機能で、一々マシンの追加の度にinventoryファイルを編集とかしなくていい。人間に優しい。
あと既にサーバ監視にZabbixを使っていたのでZabbixのホスト一覧からinventoryを生成し、Zabbix管理下のホストを構成管理ということもしてみる。
Requirements
- Ansible (Tested on 1.8.1)
- Zabbix (Tested on 2.0.8)
- CentOS (Teted on 6.5)
Installation
dynamic inventoryを使うには-i
オプションにansibleが認識可能なJSON形式の結果を吐く実行可能なスクリプトを渡してやればいい。
形式さえ合ってればいいのでシェルスクリプトでもrubyでも何でも好きな言語で書ける。
例えばローカルの/etc/hosts
に存在するホスト名をinventoryとして使いたければ
#!/bin/bash
HOSTS=$(cat /etc/hosts | grep -v ^# | awk '{print $2}')
HOSTS=$(echo "$HOSTS" | sed -e 's/^\(.*\)$/"\1"/g')
HOSTS=$(echo $HOSTS | sed -e 's/\s/,/g')
echo "{\"all\": {\"hosts\": [$HOSTS]}}"
のようなスクリプトを書いて渡してやるだけでいい。
ansibleで使うには
$ ansible -i inventory.sh all -m ping
のようにする。
さらに/etc/ansible/hosts
にスクリプトを設置すればいちいち-i
オプションを使う必要もなくなる。
$ cp inventory.sh /etc/ansible/hosts && chmod +x /etc/ansible/hosts
$ ansible all -m ping
web1 | success >> {
"changed": false,
"ping": "pong"
}
web2 | success >> {
"changed": false,
"ping": "pong"
}
...(中略)...
素晴らしい。
JSONの形式は以下のような形式ならなんでもいい。
{
"databases" : {
"hosts" : [ "host1.example.com", "host2.example.com" ],
"vars" : {
"a" : true
}
},
"webservers" : [ "host2.example.com", "host3.example.com" ],
"atlanta" : {
"hosts" : [ "host1.example.com", "host4.example.com", "host5.example.com" ],
"vars" : {
"b" : false
},
"children": [ "marietta", "5points" ]
},
"marietta" : [ "host6.example.com" ],
"5points" : [ "host7.example.com" ],
"_meta" : {
"hostvars" : {
"host1.example.com" : {
"asdf" : 1234,
"ansible_ssh_host": "host1.example.com"
},
"host2.example.com" : {
"asdf" : 5678,
"ansible_ssh_host": "host2.example.com"
}
}
}
}
_meta
内にはhostvarsを入れられるのでhostごとに異なる情報があればここに入れておく。(ansible_ssh_port
, ansible_ssh_user
, ansible_ssh_host
等)
公式ドキュメント: Developing Dynamic Inventory Sources — Ansible Documentation
Zabbix連携
Ansibleが既に公式で配布しているZabbix用のdynamic inventoryスクリプトがあるのでこれを使います。
使ってみたがそのままでは動作しなかったのと、デフォルトではホストグループ単位でのグループ化しか出来なかったので少し修正して、
Zabbixのテンプレート単位でのinventory化も出来るようにします。
修正後のファイルはGistに公開してあります。
@@ -71,19 +71,41 @@ class ZabbixInventory(object):
'hosts': []
}
+ def templatestub(self):
+ return {
+ 'hosts': []
+ }
+
def get_host(self, api, name):
data = {}
return data
def get_list(self, api):
- hostsData = api.host.get({'output': 'extend', 'selectGroups': 'extend'})
-
+ hostsData = api.host.get(
+ {
+ 'output': 'extend',
+ 'selectGroups': 'extend',
+ 'selectInterfaces': 'extend',
+ 'selectInventory': 'extend'
+ }
+ )
+ templateData = api.template.get(
+ {
+ 'output': 'extend',
+ 'selectGroups': 'extend',
+ 'selectHosts': 'extend',
+ }
+ )
data = {}
data[self.defaultgroup] = self.hoststub()
+ data['_meta'] = {}
+ data['_meta']['hostvars'] = {}
for host in hostsData:
hostname = host['name']
data[self.defaultgroup]['hosts'].append(hostname)
+ data['_meta']['hostvars'][hostname] = host
+ data['_meta']['hostvars'][hostname]['ansible_ssh_host'] = hostname
for group in host['groups']:
groupname = group['name']
@@ -93,6 +115,18 @@ class ZabbixInventory(object):
data[groupname]['hosts'].append(hostname)
+ for template in templateData:
+ templatename = template['name']
+
+ for host in template['hosts']:
+ hostname = host['name']
+
+ if not templatename in data:
+ data[templatename] = self.templatestub()
+
- 修正したものをansibleのconfディレクトリにコピー
cp zabbix.py /etc/ansible/hosts
chmod +x /etc/ansible/hosts
cp zabbix.ini /etc/ansible/
- zabbixのpythonクライアントをインストール
pip install zabbix-api
- 確認
# ホストグループベースのansible実行
$ ansible webservers -m ping
web1 | success >> {
"changed": false,
"ping": "pong"
}
web2 | success >> {
"changed": false,
"ping": "pong"
}
...(中略)...
# テンプレートベースのansible実行
$ ansible "Template OS Linux" -m ping
web1 | success >> {
"changed": false,
"ping": "pong"
}
web2 | success >> {
"changed": false,
"ping": "pong"
}
...(中略)...
これでZabbix上のホストグループベースでのinventoryの生成と、テンプレートベースでのinventoryの生成が出来ました。
テンプレートベースでの構成管理が出来るので、テンプレートと密接に関わるUserParameterやLow Level Discoveryの構成管理は楽になると思います。
またスクリプトのZabbix APIのhost.getを叩いてる箇所に
'selectInventory': 'extend'
をパラメータに追加してホストインベントリも取得しているので
Zabbixでラック管理やシリアル管理、タグ管理等の資産管理をしている場合は
hostvarsを見て特定のラックのみ更新、特定のタグのマシンのみ更新とか出来ます。
他にもZabbix API次第でinventoryの生成方法を色々工夫出来ると思います。
あとはZabbixのディスカバリチェックで監視対象のホストをホストグループに追加したり
テンプレートにリンクさせたりすれば動的にinventoryを増やしたり減らしたり出来ます。
dynamic inventory用のスクリプト自体は公式が配布しているものを少し修正すれば
十分実用的になるので各々の環境に合わせたdynamic inventoryプラグインを作るのがよいかと思います。