zoukankan      html  css  js  c++  java
  • 第2天:Ansible-Inventory管理

    在Ansible中,将可管理的服务器集合成为Inventory。因此,Inventory管理便是服务器管理。

    hosts文件位置

    我们知道,Ansible在执行操作时,首先需要确定对哪些服务器执行操作。默认情况下,Ansible读取/etc/ansible/hosts文件中的服务器配置,获取需要操作的服务器列表。Ansible定义与获取服务器列表的方式比这个要灵活的多。

    在Ansible中,有三种方式指定hosts文件:

      1)默认读取/etc/ansible/hosts文件

      2)通过命令行参数的 -i 指定hosts文件

      3)通过ansible.cfg文件的inventory选项

    ansible命令的--list-hosts选项用来显示匹配的服务器列表,我们可以通过该参数验证服务器的匹配情况

    [heboan@c1 ~]$ ansible test --list-hosts
      hosts (2):
        192.168.88.2
        192.168.88.3

    我们在家目录下创建个hosts,然后用-i指定这个hosts

    [heboan@c1 ~]$ cat hosts
    [test]
    192.168.20.1
    192.168.20.2
    [heboan@c1 ~]$ 
    [heboan@c1 ~]$ ansible test -i hosts --list-hosts
      hosts (2):
        192.168.20.1
        192.168.20.2
    [heboan@c1 ~]$ 
    [heboan@c1 ~]$ ansible test --list-hosts   #默认情况
      hosts (2):
        192.168.88.2
        192.168.88.3

    我们也可以在ansible.cfg中通过inventory选项指定hosts文件路径

    [heboan@c1 ~]$ cat /etc/ansible/ansible.cfg 
    [defaults]
    remote_port = 2202
    remote_user = heboan
    inventory = /home/heboan/hosts
    [heboan@c1 ~]$ 
    [heboan@c1 ~]$ ansible test --list-hosts
      hosts (2):
        192.168.20.1
        192.168.20.2

    灵活定义hosts文件内容

    Ansible支持更加灵活的方式定义hosts文件,例如将服务器进行分组,以便对不同的服务器类型进行不同的操作, 如下

    mail.heboan.com    #不属于任何一个组
    
    [webservers]
    foo.heboan.com
    bar.heboan.com
    
    [dbserver]
    one.heboan.com
    two.heboan.com
    three.heboan.com

    在服务器匹配时,all或星号是一个特殊的名称,用于匹配所有的服务器

    [heboan@c1 ~]$ ansible '*' --list-hosts
      hosts (6):
        mail.heboan.com
        foo.heboan.com
        bar.heboan.com
        one.heboan.com
        two.heboan.com
        three.heboan.com
    匹配所有服务器

    使用组名,匹配该组所有服务器

    [heboan@c1 ~]$ ansible dbserver --list-hosts
      hosts (3):
        one.heboan.com
        two.heboan.com
        three.heboan.com
    匹配组服务器

     Ansible也可以定义一个组,这个组下面定义的不是服务器列表,而是包含其他组的名称, 通过":children"的方式来声明

    [common:children]
    webserver
    dbserver

    如果我有一批服务器,并且这些服务器有相同的模式,我们可以向下面这样定义服务器

    [webservers]
    web[1:3].heboan.com
    bar.heboan.com
    
    [dbservers]
    db[a:d].heboan.com

    灵活匹配hosts文件内容

    规则 含义
    192.168.88.2或c2.heboan.com 匹配模板IP地址或服务器名,如果有多个ip或服务器,使用":"分隔
    webservers  匹配目标组为webservers,多个组使用":"分隔
     all或'*'  匹配所有服务器
     webservers:!dbservers  匹配在webservers中,不在dbservers组中的服务器
     webservers:&dbservers  匹配同时在webservers组以及在dbservers组中的服务器
     *.example.com或192.168.*  使用通配符匹配
     webservers[0],webservers[1:],webservers[-1]  使用索引或切片操作的方式匹配组中的服务器
     ~(web|db).*example.com  以~开头的匹配,表示使用正则表达式匹配

    动态Inventory获取

    从前面的介绍可以看到,Ansible提供给你了非常灵活的方式来编写hosts文件,可以节省不必要的时间浪费、提高工作效率。此外,Ansible还可以通过调用云计算服务的API,编写自定义脚本的方式获取服务器列表。如果公司有使用CMDB系统来管理服务器,那么,我们可以通过读取CMDB数据库中的记录得到服务器列表。

    既然 我们可以通过调用云计算系统的API,或者读取CMDB系统的数据库获取服务器列表,那么,再将服务器地址写入hosts文件就显得比较冗余,且没有任何必要

    一个动态获取服务器列表的脚本必须支持如下两个命令行参数:

      1)--host=<hostname>: 用于列出某台服务器的详细信息

      2)--list:用于列出群组以及群组中的服务器

    例如,我们才CMDB系统库中包含了一些服务器的信息, 如果将这些服务器信息从数据库中拷贝到hosts文件中,效果如下:

    [root@c1 ~]# cat /etc/ansible/hosts
    [test]
    192.168.88.2 ansible_user=heboan ansible_port=22
    192.168.88.3 ansible_user=heboan ansible_port=22
    
    [uat]
    192.168.88.4 ansible_user=heboan ansible_port=22

    按照Ansible的约定,我们需要编写一个动态脚本来获取服务器的列表,这个脚本必须支持--list选项和--host选项。其中,--list选项以json的格式返回以组名为key,服务器列表为value的数据。--host返回一个字典,该字典中包含了这个服务器的详细信息,如下:

    [heboan@c1 ~]$ python hosts.py --list
    {
        "test": [
            "192.168.88.2", 
            "192.168.88.3"
        ], 
        "uat": [
            "192.168.88.4"
        ]
    }
    [heboan@c1 ~]$ 
    [heboan@c1 ~]$ python hosts.py --host='192.168.88.2'
    {
        "ansible_port": "22", 
        "asnible_user": "heboan"
    }

    接下来我们来看下如何编写这样一个动态获取服务器的脚本。假设。我们的CMDB数据库中,存在一张名为hosts的表:

    CREATE TABLE  hosts(
    id int(11) NOT NULL PRIMARY KEY AUTO_INCREMENT,
    host varchar(15) DEFAULT NULL,
    groupname varchar(15) DEFAULT NULL,
    username varchar(15) DEFAULT NULL,
    port int(11) DEFAULT NULL
    );
    
    INSERT INTO hosts values(null, '192.168.88.2', 'test', 'heboan', 22);
    INSERT INTO hosts values(null, '192.168.88.3', 'test', 'heboan', 22);
    INSERT INTO hosts values(null, '192.168.88.3', 'uat', 'heboan', 22);

    下面是动态获取服务器列表的程序

    #!/usr/bin/python
    #_*_ coding: UTF-8 _*_
    
    import argparse
    import json
    from collections import defaultdict
    from contextlib import contextmanager
    import pymysql
    
    def to_json(in_dict):
        return json.dumps(in_dict, sort_keys=True, indent=4)
    
    
    @contextmanager
    def get_conn(**kwargs):
        conn = pymysql.connect(**kwargs)
        try:
            yield conn
        finally:
            conn.close()
    
    
    def parse_args():
        parser = argparse.ArgumentParser(description='Heboan Inventory Module')
        group = parser.add_mutually_exclusive_group(required=True)
        group.add_argument('--list', action='store_true', help='list active servers')
        group.add_argument('--host', help='List details about the specific host')
        return parser.parse_args()
    
    
    def list_all_hosts(conn):
        hosts = defaultdict(list)
    
        with conn as cur:
            cur.execute('select * from hosts')
            rows = cur.fetchall()
            for row in rows:
                no, host, group, user, port = row
                hosts[group].append(host)
            return hosts
    
    def get_host_detail(conn, host):
        details = {}
        with conn as cur:
            cur.execute("select * from hosts where host='{}'".format(host))
            rows = cur.fetchall()
            if rows:
                no, host, group, user, port = rows[0]
                details.update(asnible_user=user, ansible_port=port)
        return details
    
    def main():
        parser = parse_args()
        with get_conn(host='127.0.0.1', user='root', password='root', db='cmdb' ) as conn:
            if parser.list:
                hosts = list_all_hosts(conn)
                print(to_json(hosts))
            else:
                details = get_host_detail(conn, parser.host)
                print(to_json(details))
    
    if __name__ == '__main__':
        main()
    hosts.py

    为了让我们动态获取服务器列表程序能够应用在Ansible中,需要为hosts.py加上可执行权限。其他使用方式和普通的hosts文件一模一样。

    定义服务器变量

    ...

  • 相关阅读:
    钻进 Linux 内核看个究竟
    如何监控 Linux 服务器状态?
    树莓派使用 OLED 屏显示图片及文字
    动态代理学习(二)JDK动态代理源码分析
    动态代理学习(一)自己动手模拟JDK动态代理
    SpringCloudGateWay学习 之 从函数式编程到lambda
    leetCode刷题 | 两数相加
    leetCode刷题 | 两数之和
    数据结构 | 再也不怕被问栈跟队列了
    算法 | 链表的应用,缓存失效算法
  • 原文地址:https://www.cnblogs.com/sellsa/p/9946448.html
Copyright © 2011-2022 走看看