使用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插件。

bannerAds