您的位置:首页 > 运维架构

自动化运维工具Ansible之动态inventory文件

2015-08-11 11:46 656 查看
去年的时候开发了一个自动化运维的小系统,用的就是Ansible 的python API,其中动态从数据库获取主机组合主机变量的功能,着实费了老大的劲,最后用了个很鸡肋的方法实现了。最近几个月把Ansible的官方文档通看了一遍,哎,想死的心都有了,文档里面已经写的很清楚如何实现动态inventory文件了,就怪当时自己太着急,没仔细看文档。

自己开发的动态inventory脚本文件,只需要支持两个参数即可:
--list 返回所有的主机组信息,每个组都应该包含字典形式的主机列表,子组列表,如果需要的话还应该组变量,最简单的信息是只包含主机列表,返回的数据格式要是JSON格式的。
--host <hostname> 返回该主机的变量列表,或者是返回一个空的字典,JSON格式。

参数--list访问脚本的时候,返回数据结果:

{
"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" ]
}


databses,webservers,atlanta,marietta,5points为主机组名称,hosts为该主机组下的主机列表,vars为主机组的变量,children为该主机组的子组列表。

参数--host <hostname>访问脚本的时候,返回的数据结果,如果没有主机变量则返回一个空的字典:
{
"favcolor"   : "red",
"ntpserver"  : "wolf.example.com",
"monitoring" : "pack.example.com"
}


但是如果针对每个主机都调用一次`--host`的话,将会产生大量的资源开销。在Ansible1.3或之后的版本中,如果脚本返回了一个称为`_meta`的顶级元素,该元素中如果包含着`hostvars`关键字,那么就可以将所有主机的变量都返回。脚本也不会再为每个主机都调用一次`--host`,这讲节省大量的资源开销,同时也方便的客户端的缓存。
返回的`_meta`类似如下格式:

{

# results of inventory script as above go here
# ...

"_meta" : {
"hostvars" : {
"moocow.example.com"     : { "asdf" : 1234 },
"llama.example.com"      : { "asdf" : 5678 },
}
}

}
所返回的变量可以在模板中引用。
示例:

动态脚本内容

[root@web1 ~]# cat /etc/ansible/getHosts.py
#!/usr/bin/python
import argparse
try:
import json
except ImportError:
import simplejson as json

'''这里是模拟数据,工作上一般该数据都是从数据库或者缓存中读取的'''
mockData = {
"webservers":{
"hosts": ["192.168.1.65"],
"vars":{
"http_port":8888,
"max_clients":789
}
},

"databases":{
"hosts":["192.168.1.65"],
"vars":{
"action":"Restart MySQL server."
}
}
}
'''模拟数据结束'''
def getList():
'''get list hosts group'''
print json.dumps(mockData)

def getVars(host):
'''Get variables about a specific host'''
print json.dumps(mockData[host]["vars"])

if __name__ == "__main__":

parser = argparse.ArgumentParser()
parser.add_argument('--list',action='store_true',dest='list',help='get all hosts')
parser.add_argument('--host',action='store',dest='host',help='get all hosts')
args = parser.parse_args()

if args.list:
getList()

if args.host:
getVars(args.host)
该脚本支持两个参数--list和--host。

playbook内容:
[root@web1 ~]# cat /etc/ansible/test.yml
---
- hosts: webservers
remote_user: root
tasks:
- name: config httpd.file
template: src=/etc/ansible/httpd.j2 dest=/etc/httpd.conf
执行命令:

[root@web1 ansible]# ansible-playbook -i /etc/ansible/getHosts.py /etc/ansible/test.yml

PLAY [webservers] *************************************************************

GATHERING FACTS ***************************************************************
ok: [192.168.1.65]

TASK: [config httpd.file] *****************************************************
changed: [192.168.1.65]

PLAY RECAP ********************************************************************
192.168.1.65               : ok=2    changed=1    unreachable=0    failed=0

[root@web1 ansible]# ansible -i /etc/ansible/getHosts.py databases -m shell -a "echo {{ action }}"192.168.1.65 | success | rc=0 >>
Restart MySQL server.
Python API调用动态inventory:
[root@web1 ~]# cat an.py
#!/usr/bin/env python

import ansible.runner

runner = ansible.runner.Runner(
module_name='shell',
module_args='echo {{ action }}',
pattern='databases',
host_list='/etc/ansible/getHosts.py',
forks=10
)

data = runner.run()
print data
[root@web1 ~]# python an.py
{'dark': {}, 'contacted': {u'192.168.1.65': {u'cmd': u'echo Restart MySQL server.', u'end': u'2015-08-07 15:26:02.141350', u'stdout': u'Restart MySQL server.', u'changed': True, u'start': u'2015-08-07 15:26:02.128109', u'delta': u'0:00:00.013241', u'stderr': u'', u'rc': 0, 'invocation': {'module_name': 'shell', 'module_args': u'echo Restart MySQL server.'}, u'warnings': []}}}
总的来说,只要脚本文件支持--list和--host <hostname>参数,并且返回的结果是文档所指定的格式,就不会出现什么问题。
好吧,就写到这了,赶紧更新自己的运维系统中的动态脚本去.......
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息