配套51CTO视频课程(付费) https://edu.51cto.com/course/27273.html
场景
在实际工作环境中,较大的企业通常有内部的CMDB管理系统,每个部门基本也都有开发自己的运管系统之类,比如最基础的本部门有哪些机器,它们都是什么配置,基本都是通过运管系统管理。这套内部系统可能已经使用很长时间,内部也形成了一定的规范,比如初始化机器会有脚本自动注册机器基础信息到系统中,也就是说相应的运管系统才保存在一手完整的元数据信息,当然这一类的运管系统通常都有API对外暴露供用户使用,比如调curl某个地址,返回全部机器IP等
换句话说,我们使用Ansible管理的机器IP地址,可能来自于某个接口返回的信息里,或者说存放在某个数据库里,此时我们当然可以每次接口有数据更新,人工将更新的内容拷贝到我们的主机清单里,这种方式缺点显而易见,当机器规模比较大,更新较为频繁,手动维护两者之间的同步,费时费力,难保不出错
此时我们就想,能不能写一个脚本,自动调用运管系统里的相关接口,获取指定的IP列表呢,比如调A脚本功能是返回全部WEB机器列表,B脚本功能是返回全部数据库机器列表,由于每次执行playboook这些脚本都重新执行一次,即每次都动态拿到IP列表,这样只要接口不变,脚本只要写一次即可长久使用,不用担心两边IP列表不同步的问题
类似这种需求,就需要用到Ansible动态获取主机清单的功能(dynamic inventory),与之对应之前手动写死机器列表的方法,称之为静态主机清单(static inventory)
实现方式
具体来说,我们需要准备一个可执行文件,充当主机清单用。所谓可执行即拥有+x
权限,该文件可以是脚本文件,如python、php脚本,也可以是二进制文件,比如go、c语言编译后的二进制可执行脚本,这个脚本准备好之后,使用方法类似如下
ansible-playbook test1.yaml -i ${my-inventory-script}
-i
参数相信大家已经熟悉了,之前我们用它是接静态主机清单文件,该参数同样可以接动态主机清单文件
那么这个脚本具体该有些什么内容呢,简单来说这个脚本返回的是主机清单里该有的信息,也就是:机器IP、机器分组、主机变量、组变量这些,比如下面的示例
return {
'mygroup1': {
'hosts': ['192.168.31.100', '192.168.31.101'],
'vars': {
'mytest_var1': 'hello1',
'mytest_var2': 'hello2',
'mytest_common': 'hello_common'
}
},
'mygroup2': {
'hosts': ['192.168.31.102'],
'vars': {
'mytest_var3': 'hello3',
'mytest_common': 'hello_common'
}
},
'_meta': {
'hostvars': {
'192.168.31.100': {
'host_specific_var': 'foo100'
},
'192.168.31.101': {
'host_specific_var': 'bar101'
}
}
}
}
上面的返回信息是以python语言写的,其它编程语言情况类似,如果把上面的返回信息转成我们之前学过的主机清单样式,类似下面这样
# cat /etc/ansible/hosts
[mygroup1]
192.168.31.100 host_specific_var=foo100
192.168.31.101 host_specific_var=bar101
[mygroup2]
192.168.31.102
[mygroup1:vars]
mytest_var1=hello1
mytest_var2=hello2
mytest_common=hello_common
[mygroup2:vars]
mytest_var3=hello3
mytest_common=hello_common
整体来说,Ansible规定了一个动态获取主机清单的脚本,需要支持两个参数即,--list
和 --host HOST
./my-inventory-script --list
使用来返回主机清单信息的,如上面所示,返回的数据是JSON格式
./my-inventory-script --host HOST
这里的HOST指的就是主机清单IP地址,正常是循环调用这个接口来得到主机变量的,不过一般我们用`--list`返回的信息使其带有 _meta ,这个特殊信息用来表示主机变量,那么只需要让这个接口返回"空",即可,返回的数据是JSON格式
python获取动态主机清单实践
我们以python语言为例,演示以下具体用法
脚本地址 https://gitee.com/as4k/ysansible/tree/master/dynamic-inventory
python代码细节,我就不多说了,如果需要大家可自行到网上百度学习,我们直接执行看下效果
# ls
inventory.py README.md test1.yaml
# ansible all -i inventory.py -m ping
# ansible-playbook test1.yaml -i inventory.py
大家自己写脚本测试,可以使用下面这个命令,进行快速测试
./inventory.py --list | python -c "import json,sys; obj=json.load(sys.stdin); print(json.dumps(obj, indent=4))" && echo
参考资料
https://docs.ansible.com/ansible/latest/user_guide/intro_dynamic_inventory.html
https://docs.ansible.com/ansible/latest/dev_guide/developing_inventory.html