在大多数情况下,静态Inventory文件可以很好的描述主机间的关系。尤其是服务器规模不大的情况的情况下,即便是手区来编辑更新Inventory文件也非常的方便快捷。
然而,我们所生活的时候是云计算和大规模集群的时代。在实际生产应用中,经常会遇到业务的快速发展或者流量的急剧增加等等情况,需要在短时间内向架构中添加几十台甚至上百台服务器来提高整个架构的处理能力。这个时候,手动管理Inventory文件不仅没有效率,而且非常的乏味。
此时,动态Inventory应运而生。Ansible通过调用第三方脚本来动态的配置Inventory文件。目前,一些知名的云主机供应商,如亚马逊AWS、Cobbler、gitalOcean、Lnode、OpenStack等提供了现成的脚本可供Ansible直接调用,其具体的用法,在对应的平台上都有详尽的官方文档说明显,这里我们就不在赘述。接下来我们将借助实际安全,详细介绍如何自行开发动态Inventory文件的脚本。
Ansible启用动态Inventory 是通过调用外部脚本(任何脚本都可以,二进制文件也可以,只要运行结果返回的是JSON 串就可以) 生成指定格式的JSON串 。Ansible可以对JSON格式的字符串对行解析,并最给将基转化为Ansible可用的Inventory文件格式。所以,所谓的动态Inventory文件脚本开发其实就是编写脚本根据具体环境将主机信息及关系(这些数据可以通过抓取数据库,调用外部API或者直接读取文件获得)以JSON格式来表示出来,并将其做为脚本输出结果传给Ansible。
需要注意的是,用于生成JSON代码的脚本必须支持两个选项:
--list
:返回所有的主机组信息,每个组都应该包含字典形式的主机列表,子组列表,如果需要的话还应该组变量,最简单的信息是只包含主机列表,返回的数据格式要是JSON格式的 --host <hostname>
:返回该主机的变量列表,或者是返回一个空的字典,JSON格式。 ansible all -i my-inventory-script -m ping
虽然在命令中并未体现,但Ansible默认是通过调用脚本的—list选项来获取JSON代码的。下面是一段由脚本生成的JSON代码:
"databases": {
"hosts": [
"192.168.28.71",
"192.168.28.72"
],
"vars": {
"ansible_ssh_user": "johndoe",
"ansible_ssh_private_key_file": "~/.ssh/mykey",
"example_variable": "value"
}
},
"_meta": {
"hostvars": {
"192.168.28.71": {
"host_specific_var": "bar"
},
"192.168.28.72": {
"host_specific_var": "foo"
}
}
}
}
在本例中,databases为主机组名,可自定义。hosts为固定字段,用于以列表形式定义主机组的主机。vars也为固定字段,用于为主机组设置主机组变量。字典_meta中定义的是主机变量。
主机变量并不是Inventory文件中必须的,所以_meta字典也不是必须生成的。当我们的Inventory脚本中生成_meta字典时,Ansible会将_meta信息存放在缓存中,当任务中需要调用这些主机变量时,会直接从缓存中读取,而不是调用一次变量就执行一次Inventory脚本,这样大大提高了运行效率。
原文出处——运维部落微信公众号