使用Ansible动态清单+ Zabbix API进行动态配置和管理监控目标
概述
我平时使用Ansible,但是发现管理inventory很麻烦,每次添加主机都需要编辑inventory文件之类的操作。
最近我知道了dynamic inventory,所以想试用一下。
简单来说,这是一个可以动态生成Ansible inventory主机的功能,不需要每次添加机器都编辑inventory文件之类的操作。很贴心。
另外,我已经在使用Zabbix进行服务器监控,所以尝试从Zabbix的主机列表生成inventory,把Zabbix管控的主机也作为配置管理的一部分。
要求
-
- Ansible (Tested on 1.8.1)
-
- Zabbix (Tested on 2.0.8)
- CentOS (Teted on 6.5)
安装
只需要一个选项:要使用dynamic inventory,只需通过-i选项传递一个能让ansible能够识别的JSON格式结果输出的可执行脚本即可。只要格式正确,可以使用任何喜欢的语言编写,无论是shell脚本还是ruby脚本。
如果想要将本地的/etc/hosts中存在的主机名作为清单使用,可以这样做。
#!/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以便存放每个主机的不同信息。(例如ansible_ssh_port、ansible_ssh_user、ansible_ssh_host等)
公式文档:开发动态库存资源 —— Ansible 文档
Zabbix集成
因为Ansible已经在官方渠道提供了适用于Zabbix的动态清单脚本,所以我们将使用这个脚本。
我使用了它,但它的原样不能工作,而且默认情况下只能通过主机组来进行分组,所以我进行了一些修改,以便可以在Zabbix的模板级别上进行清单化。
我已经将修改后的文件发布在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和基于模板的生成,已经可以实现了。
由于可以进行基于模板的配置管理,我认为与模板紧密相关的UserParameter和Low Level Discovery的配置管理将变得更轻松。
另外,在脚本中调用Zabbix API的host.get方法的部分。
'selectInventory': 'extend'
由于将其作为参数添加并获取主机清单,因此如果在Zabbix中进行机架管理、串行管理、标签管理等资产管理的情况下,可以查看hostvars并进行仅更新特定机架或特定标签机器等操作。此外,我认为还可以根据Zabbix API来灵活地生成inventory的方法。
通过Zabbix的自动发现检查,您可以将要监视的主机添加到主机组中,或者将其链接到模板中,以动态地增加或减少清单。
对于dynamic inventory的脚本本身来说,如果稍作修改,官方提供的脚本就足够实用了,所以我认为最好根据各自的环境来创建适合的dynamic inventory插件。