Ansible自动化运维:技术与最佳实践
上QQ阅读APP看书,第一时间看更新

第3章 Ansible组件介绍

经过前面2章的介绍,我们已经熟悉了Ansible的一些安装与简单使用。从本章开始我们将全面介绍Ansible的各种组件。这些也是我们使用Ansible的过程中必须理解的知识点。本章将通过介绍和讲解Ansible日常中经常使用的一些组件,使我们能对Ansibl e有一个全面的了解。

3.1 Ansible Inventory

在大规模的配置管理工作中我们需要管理不同业务的不同机器,这些机器的信息都存放在Ansible的Inventory组件里面。在我们工作中配置部署针对的主机必须先存放在Inventory里面,这样才能使用Ansible对它进行操作。默认Ansible的Inventory是一个静态的INI格式的文件/etc/ansible/hosts,当然,还可以通过ANSIBLE_HOSTS环境变量指定或者运行ansible和ansible-playbook的时候 用-i参数临时设置。

1.定义主机和主机组

下面我们来看一下如何在默认的Inventory文件中定义一些主机和主机组,具体如下:

        1172.17.42.101    ansible_ssh_pass='123456'
        2172.17.42.102    ansible_ssh_pass='123456'
        3 [docker]
        4172.17.42.10[1:3]
        5 [docker:vars]
        6 ansible_ssh_pass='123456'
        7 [ansible:children]
        8 docker

·第1行定义了一个主机是172.17.42.101,然后使用Inventory内置变量定义了SSH登录密码。

·第2行定义了一个主机是172.17.42.102,然后使用Inventory内置变量定义了SSH登录密码。

·第3行定义了一个组叫docker。

·第4行定义了docker组下面4台主机从172.17.42.101到172.17.42.103。

·第5行到第6行针对docker组使用Inventory内置变量定义了SSH登录密码。

·第7行到第8行定义了一个组叫ansible,这个组下面包含docker组。

ansible_ssh_pass参数是Ansible Inventory内置参数,在本节的最后一小节会进行相关的介绍。Inventory文件一般用来定义远端主机的认证信息,比如SSH登录密码、用户名以及key相关信息。当然,Inventory文件也支持主机或者主机组的便利定义。添加完主机和主机组后我们就可以使用Ansible命令针对这些主机进行操作和管理了。下面是分别针对不同的主机和主机组进行Ansible的ping模块检测,ping模块是Ansible中一个连通性检测的模块。当然,Ansible还内置大量的其他模块,后续章节我们也会慢慢接触。

        [root@Master ~]# ansible 172.17.42.101:172.17.42.102-m ping -o
        172.17.42.101 — success >> {"changed": false, "ping": "pong"}

        172.17.42.102 — success >> {"changed": false, "ping": "pong"}

        [root@Master ~]# ansible docker -m ping -o
        172.17.42.101 — success >> {"changed": false, "ping": "pong"}

        172.17.42.103 — success >> {"changed": false, "ping": "pong"}

        172.17.42.102 — success >> {"changed": false, "ping": "pong"}

        [root@Master ~]# ansible ansible -m ping -o
        172.17.42.102 — success >> {"changed": false, "ping": "pong"}

        172.17.42.103 — success >> {"changed": false, "ping": "pong"}

        172.17.42.101 — success >> {"changed": false, "ping": "pong"}

2.多个Inventory列表

通过上一小节对Inventory的介绍,我们知道Ansible默认的Inventory文件是一个INI的静态文件,其实Ansible还支持多个Inventory文件,这样我们就可以很方便地管理不同业务或者不同环境中的机器了。如何使用多个Inventoy文件呢?

首先需要修改ansible.cfg中hosts文件的定义,或者使用ANSIBLE_HOSTS环境变量定义。这里我们准备一个文件夹,里面将存放多个Inventory文件,如以下目录所示:

        [root@Master ~]# tree inventory/
        inventory/
        ├── docker
        └── hosts

不同的文件可以存放不同的主机,我们来分别看一下文件的内容:

        [root@Master ~]# cat inventory/hosts
        172.17.42.101    ansible_ssh_pass='123456'
        172.17.42.102    ansible_ssh_pass='123456'
        [root@Master ~]# cat inventory/docker
        [docker]
        172.17.42.10[1:3]
        [docker:vars]
        ansible_ssh_pass='123456'
        [ansible:children]
        docker

最后我们修改了ansible.cfg文件中inventory的值,这里不再指向一个文件,而是指向一个目录,修改如下:

        inventory   = /root/inventory/

这样我们就可以使用Ansible的list-hosts参数来进行如下验证:

        [root@Master ~]# ansible 172.17.42.101:172.17.42.102--list-hosts
            172.17.42.101
            172.17.42.102
        [root@Master ~]# ansible docker --list-hosts
            172.17.42.101
            172.17.42.102
            172.17.42.103
        [root@Master ~]# ansible ansible --list-hosts
            172.17.42.101
            172.17.42.102
            172.17.42.103

其实Ansible中的多个Inventory跟单个文件没什么区别,我们也可以容易定义或者引用多个Inventory,甚至可以把不同环境的主机或者不同业务的主机放在不同的Inventory文件里面,方便日后维护。

3动态Inventory

在实际应用部署中会有大量的主机列表。如果手动维护这些列表将是一个非常繁琐的事情。其实Ansible还支持动态的Inventory,动态Inventory就是Ansible所有的Inventory文件里面的主机列表和变量信息都支持从外部拉取。比如我们可以从CMDB系统和Zabbix监控系统拉取所有的主机信息,然后使用Ansible进行管理。这样一来我们就可以很方便地将Ansible与其他运维系统结合起来。关于引用动态Inventory的功能配置起来也很简单。我们只需要把ansible.cfg文件中inventory的定义值改成一个执行脚本即可。这个脚本的内容不受任何编程语言限制,但是这个脚本使用参数时有一定的规范并且对脚本执行的结果也有要求。这个脚本需要支持两个参数:

·--list或者-l,这个参数运行后会显示所有的主机以及主机组的信息(JSON格式)。

·--host或者-H,这个参数后面需要指定一个host,运行结果会返回这台主机的所有信息(包括认证信息、主机变量等),也是JSON格式。

下面我们通过一个简单的例子了解动态Inventory实现流程。这里编写了一个简单hosts.py脚本,代码如下:

        #! /usr/bin/env python
        # -*- coding: utf-8-*-
        import argparse
        import sys
        import json
        def lists():
            r = {}
            h=[ '172.17.42.10' + str(i) for i in range(1,4) ]
            hosts={' hosts' : h}
            r[' docker' ] = hosts
            return json.dumps(r, indent=4)

        def hosts(name):
            r = {' ansible_ssh_pass' : '123456' }
            cpis=dict(r.items())
            return json.dumps(cpis)

        if __name__ == ' __main__' :
            parser = argparse.ArgumentParser()
            parser.add_argument(' -l' , ' --list' , help=' hosts list' , action=' store_
                                  true' )
            parser.add_argument(' -H' , ' --host' , help=' hosts vars' )
            args = vars(parser.parse_args())

            if args[' list' ]:
                print lists()
            elif args[' host' ]:
                print hosts(args[' host' ])
            else:
                parser.print_help()

这个脚本定义了两个函数:lists函数在指定--list参数后执行,hosts函数会在指定--host参数后执行。脚本的每个函数都会返回一个JSON,运行结果如下:

        [root@Master ~]# python hosts.py  --list
        {
            "docker": {
                "hosts": [
                    "172.17.42.101",
                    "172.17.42.102",
                    "172.17.42.103"
                ]
            }
        }
        [root@Master ~]# python hosts.py  -H 172.17.42.102
        {"ansible_ssh_pass": "123456"}

这里定义了一个docker组且组里定义了3台主机,然后定义每台设备的SSH密码。ansible_ssh_pass是Inventory内置的参数,下一节会详细解释。最后我们来执行临时指定这个hosts.py脚本,没修改ansible.cfg文件,运行结果如下:

        [root@Master ~]# ansible   -i hosts.py 172.17.42.102:172.17.42.103   -m
            ping -o
        172.17.42.102 — success >> {"changed": false, "ping": "pong"}

        172.17.42.103 — success >> {"changed": false, "ping": "pong"}

        [root@Master ~]# ansible  -i hosts.py docker  -m ping -o
        172.17.42.101 — success >> {"changed": false, "ping": "pong"}

        172.17.42.102 — success >> {"changed": false, "ping": "pong"}

        172.17.42.103 — success >> {"changed": false, "ping": "pong"}

本节只是简单地编写了一个Inventory脚本,希望读者能理解这个原理,在实际工作中可以根据自己的需求编写相应的脚本。目前官方也有一些关于从cobbler和AWS获取主机或者主机组相关的Invento ry脚本,有兴趣的读者可以自己查阅。

4.Inventory内置参数

这里介绍Ansible Inventory内置的一些参数,这些参数在我们实际工作中也会经常使用,我们可以直接在Inventory文件中定义它,当然动态的Inventory也可以使用它,如表3-1所示。

表3-1 Inventory内置参数