Python中的 ansible 动态Inventory 脚本

1. 什么是 Ansible 动态 Inventory

在使用 Ansible 管理大量的服务器时,我们需要将这些服务器组织起来,形成一个组。我们需要将其打上标签,例如 Web 服务器,数据库服务器,应用服务器等等。这样,在我们需要对这些服务器进行一些操作的时候,只需要找到相应的标签,就可以完成一系列操作,非常方便。

Ansible 动态 Inventory 是一种自动生成 Inventory 文件的方法。在这种方法中,我们可以通过脚本来自动生成 Inventory 文件,而无需手动编写 Inventory 文件,这大大简化了配置工作。

2. Ansible 动态 Inventory 脚本的调用方式

在 Ansible 中,我们可以通过调用脚本的方式来生成动态 Inventory。调用脚本的方式非常简单,只需要在调用 Ansible 命令时加上 --inventory-file 参数,指定脚本的路径即可。

ansible-playbook --inventory-file=/path/to/inventory_script.py playbook.yml

3. 编写 Ansible 动态 Inventory 脚本的步骤

3.1 写脚本框架

首先,我们需要写出脚本的框架。脚本框架一般包含如下内容:

#!/usr/bin/env python

import argparse

import json

class DynamicInventory(object):

def __init__(self):

self.inventory = {}

self.read_cli_args()

# ...

DynamicInventory()

在这个脚本框架中,我们首先引入 argparse 和 json 两个库,因为我们需要使用命令行参数和 Json 格式来访问和表达 Inventory 数据。

然后,我们创建了一个 DynamicInventory 类,并定义了一个 inventory 成员变量,用于存储自动生成的 Inventory 信息。之后,我们在构造函数中调用了一个 read_cli_args 方法。

这样,一个空的脚本框架就创建完成了。

3.2 读取命令行参数

读取命令行参数的代码如下:

def read_cli_args(self):

parser = argparse.ArgumentParser(description='Produce an Ansible Inventory file based on some external inventory.')

parser.add_argument('--list', action='store_true', default=True, help='List instances (default: True)')

parser.add_argument('--host', action='store', help='Get all the variables about a specific instance')

args = parser.parse_args()

if not (args.list or args.host):

parser.error('You must specify --list or --host')

self.args = args

在这个方法中,我们首先创建了一个 ArgumentParser 对象,并定义了两个参数:--list 和 --host,用来控制返回的 Inventory 内容和查询某个主机的详细信息。我们还设置了一个默认值,即 --list 参数为 True。

之后,我们判断用户是否指定了 --list 或者 --host,如果没有指定,将会抛出一个异常。

最后,我们将命令行参数保存在 self.args 变量中。

3.3 生成 Inventory 信息

生成 Inventory 信息的代码如下:

def generate_inventory(self):

result = {}

# ...

self.inventory = result

return self.inventory

在这个方法中,我们首先创建了一个 result 字典,用于存储生成的 Inventory 信息。

然后,我们根据 read_cli_args 方法中保存的命令行参数,生成需要返回的 Inventory 信息。具体的生成方法将在下面的章节中讲述。

最后,我们将 result 赋值给 inventory 变量,并将其返回。

3.4 处理 Inventory 数据

在 generate_inventory 方法中,我们根据命令行参数生成了 Inventory 信息。因此,我们需要处理生成的信息并返回。具体的处理方式视实际需求而定,下面是一个简单的示例:

if self.args.list:

result['_meta'] = {'hostvars': {}}

result['group1'] = {'hosts': ['web1', 'web2'], 'vars': {}}

result['group2'] = {'hosts': ['app1', 'app2'], 'vars': {}}

在这个示例中,我们首先判断用户是否指定了 --list 参数。如果指定了,我们就创建一个 _meta 字典,用于存储主机变量,因为 Ansible 动态 Inventory 脚本需要返回所有主机的变量信息。

之后,我们创建了两个组,group1 和 group2。每个组中,我们分别指定了该组包含的主机,以及该组的变量信息。

最后,我们将生成的 result 字典返回。

4. 完整 Ansible 动态 Inventory 脚本示例

下面是一个完整的 Ansible 动态 Inventory 脚本示例:

#!/usr/bin/env python

import argparse

import json

class DynamicInventory(object):

def __init__(self):

self.inventory = {}

self.read_cli_args()

# Called with `--list`.

if self.args.list:

self.inventory = self.generate_inventory()

# Called with `--host [hostname]`.

elif self.args.host:

# Not implemented, since we return _meta info `--list`.

self.inventory = self.generate_inventory()

print(json.dumps(self.inventory))

# Our generate method that dynamically creates an Ansible inventory.

def generate_inventory(self):

result = {}

# DATA SOURCE

web1 = {'hostname': '10.0.0.10', 'ansible_ssh_user': 'ubuntu', 'ansible_ssh_private_key_file': '/path/to/key'}

web2 = {'hostname': '10.0.0.11', 'ansible_ssh_user': 'ubuntu', 'ansible_ssh_private_key_file': '/path/to/key'}

app1 = {'hostname': '10.0.0.12', 'ansible_ssh_user': 'ubuntu', 'ansible_ssh_private_key_file': '/path/to/key'}

app2 = {'hostname': '10.0.0.13', 'ansible_ssh_user': 'ubuntu', 'ansible_ssh_private_key_file': '/path/to/key'}

# WEB GROUP

web_group = {'hosts': ['web1', 'web2'], 'vars': {}}

web_group['vars']['ansible_ssh_common_args'] = '-o ProxyCommand="ssh -W %h:%p -q proxy.dfw1.example.com"'

web_group['vars']['ansible_python_interpreter'] = '/usr/bin/python3'

# APP GROUP

app_group = {'hosts': ['app1', 'app2'], 'vars': {}}

app_group['vars']['ansible_ssh_common_args'] = '-o ProxyCommand="ssh -W %h:%p -q proxy.dfw1.example.com"'

app_group['vars']['ansible_python_interpreter'] = '/usr/bin/python3'

# ADD GROUPS TO RESULT

result['_meta'] = {'hostvars': {}}

result['web'] = web_group

result['app'] = app_group

return result

# Read the command line args passed to the script.

def read_cli_args(self):

parser = argparse.ArgumentParser(description='Produce an Ansible Inventory file based on some external inventory.')

parser.add_argument('--list', action='store_true', default=True, help='List instances (default: True)')

parser.add_argument('--host', action='store', help='Get all the variables about a specific instance')

args = parser.parse_args()

if not (args.list or args.host):

parser.error('You must specify --list or --host')

self.args = args

# Get the inventory.

DynamicInventory()

在这个示例中,我们根据不同的命令行参数,返回了不同的 Inventory 数据。具体来说,如果用户指定了 --list 参数,我们将返回一个包含所有主机信息的 JSON 对象,否则,我们将返回特定主机的详细信息。

生成的 Inventory 数据的样式如下:

{

"_meta": {

"hostvars": {}

},

"web": {

"hosts": [

"web1",

"web2"

],

"vars": {

"ansible_python_interpreter": "/usr/bin/python3",

"ansible_ssh_common_args": "-o ProxyCommand=\"ssh -W %h:%p -q proxy.dfw1.example.com\""

}

},

"app": {

"hosts": [

"app1",

"app2"

],

"vars": {

"ansible_python_interpreter": "/usr/bin/python3",

"ansible_ssh_common_args": "-o ProxyCommand=\"ssh -W %h:%p -q proxy.dfw1.example.com\""

}

}

}

5. 总结

使用 Ansible 动态 Inventory,可以方便地将大量服务器组织起来,并且通过编写脚本自动生成 Inventory 文件,可以极大地简化配置工作。本文对 Ansible 动态 Inventory 的使用方法进行了详细介绍,并给出了一个完整的 Ansible 动态 Inventory 脚本示例,供大家参考。

后端开发标签