容器云系列之基于Docker的Ansible自动化运维实现

本文简要介绍自动化运维工具Ansible基本概念及模块使用,并结合环境部署Ansible和可视化管理平台Ansible Tower。Ansible的自动化运维实现分三部分介绍:

容器云系列之基于Docker的Ansible自动化运维实现——介绍Ansible的基本概念和语法使用
容器云系列之Ansible部署使用——介绍Ansible的安装部署和使用
容器云系列之基于Docker部署Ansible-Tower——介绍使用Docker部署Ansible-Tower


1、Ansible基本概念

1.1 Ansible基本架构

Ansible是基于Python开发的自动化运维工具,可实现批量系统配置、批量程序部署、批量运行命令等功能。Ansible是基于模块化工作,真正具有批量部署的是ansible所运行的模块,ansible只是提供一种框架。ansible不需要在远程主机上安装client/agents,因为它们是基于ssh来和远程主机通讯的。

Ansible基本架构如下,包括modules、plugins、inventory、playbooks等模块。

容器云系列之基于Docker的Ansible自动化运维实现

  • Modules:包括core modules和custom modules。core modules是Ansible自带的模块,custom modules是核心模块功能不足时,用户可以添加的扩展模块
  • Plugins: 通过插件来实现数据传输、记录日志、发送邮件、连接inventory等功能
  • Playbooks: 剧本,通常为YAML格式文件,将多个任务定义在一个文件中,定义主机需要调用哪些模块来完成的功能
  • Inventory: 记录由Ansible管理的主机信息,包括端口、密码、ip等
  • Control node:Ansible安装的机器(不能为Windows服务器),可以在任何control node上运行ansible或ansible-playbook命令
  • Manage node:Ansible管理的hosts主机,在managed nodes没有安装Ansible
1.2 Ansible任务执行
1.2.1 Ansible任务执行模式

Ansible系统由控制主机对被管节点的操作方式可分为两类,即ad-hoc和playbook:

  • ad-hoc模式(点对点模式)

Ad-hoc模式支持使用ansible命令对多个manage hosts批量执行单条命令。ad-hoc命令是一种可以快速输入的命令,相当于bash中的一句shell命令。

  • playbook模式(剧本模式)

Playbook是Ansible主要管理方式,通过多个task集合完成一类功能,可以简单地把playbook理解为多条ad-hoc操作的配置文件。

1.2.2 Ansible执行流程

Ansible在运行时,首先读取配置文件ansible.cfg, 根据规则获取Inventory中的管理主机列表,并行的在这些主机中执行配置的任务, 最后等待执行返回的结果。

容器云系列之基于Docker的Ansible自动化运维实现

Ansible命令执行过程如下:

  1. 加载配置文件,默认/etc/ansible/ansible.cfg
  2. 查找对应的主机配置文件inventory,找到要执行的主机或者组
  3. 加载自己对应的模块文件,如command
  4. 通过ansible将模块或命令生成对应的临时py文件(python脚本), 并将该文件传输至远程服务器
  5. 对应执行home目录的.ansible/tmp/XXX/XXX.PY文件
  6. 给文件+x执行权限
  7. 执行并返回结果
  8. 删除临时py文件,sleep 0退出
1.3 Ansible配置详解
1.3.1 ansible配置文件

ansible的配置文件为/etc/ansible/ansible.cfg,ansible有许多参数,常见的参数如下:

容器云系列之基于Docker的Ansible自动化运维实现

1.3.2 Ansible Inventory文件

Ansible使用inventory定义管理的managed nodes和hosts,inventory的默认位置在/etc/ansible/hosts,也可以在命令中指定-I 参数。

1)Inventory常用的格式有INI和YAML两种,如下所示
容器云系列之基于Docker的Ansible自动化运维实现
2)如果主机名称遵循相似的命名模式,可以使用列表的方式标识各主机,例如:

[webservers]
www[01:50].example.com
[databases]
db-[a:f].example.com

3)主机变量: 可以在inventory中定义主机时为其添加主机变量以便于在playbook中使用。例如:

[webservers]
www1.com http_port=80 maxRequestsPerChild=808
www2.com http_port=8080 maxRequestsPerChild=909

4)Inventory参数说明
容器云系列之基于Docker的Ansible自动化运维实现
以下为例:

some_host         ansible_ssh_port=2222     ansible_ssh_user=manager
aws_host          ansible_ssh_private_key_file=/home/example/.ssh/aws.pem
freebsd_host      ansible_python_interpreter=/usr/local/bin/python
ruby_module_host  ansible_ruby_interpreter=/usr/bin/ruby.1.9.3
1.4 Ansible常用命令

1)ansible命令集

容器云系列之基于Docker的Ansible自动化运维实现

其中,比较常用的是/usr/bin/ansible和/usr/bin/ansible-playbook

2)ansible命令详解

命令的具体格式如下:

ansible <host-pattern> [-f forks] [-m module_name] [-a args]

也可以通过ansible -h来查看帮助

容器云系列之基于Docker的Ansible自动化运维实现
容器云系列之基于Docker的Ansible自动化运维实现

1.5 Ansible常用模块

1)主机连通性测试

使用ansible node01 -m ping命令来进行主机连通性测试,效果如下:

[root@tango-01 /]# ansible node01 -m ping
192.168.112.101 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false, 
    "ping": "pong"
}

2)command模块

这个模块可以直接在远程主机上执行命令,并将结果返回本主机。

[root@tango-01 /]# ansible node01 -m command -a 'ss -ntl'
192.168.112.101 | CHANGED | rc=0 >>
State      Recv-Q Send-Q Local Address:Port               Peer Address:Port              
LISTEN     0      128    192.168.112.101:2380                     *:*                  
LISTEN     0      128          *:20180                    *:*                  
LISTEN     0      128          *:22                       *:*                  
LISTEN     0      100    127.0.0.1:25                       *:*                  

3)shell模块

shell模块可以在远程主机上调用shell解释器运行命令,支持shell的各种功能,例如管道等。

[root@tango-01 /]# ansible node01 -m shell -a 'cat /etc/passwd |grep "test001"'
192.168.112.101 | CHANGED | rc=0 >>
test001:x:1003:1003::/home/test001:/bin/bash

4)copy模块

这个模块用于将文件复制到远程主机,同时支持给定内容生成文件和修改权限等。

[root@tango-01 tmp]# ansible node01 -m copy -a 'src=/tmp/hello.txt dest=/tmp/'
192.168.112.101 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "checksum": "22596363b3de40b06f981fb85d82312e8c0ed511", 
    "dest": "/tmp/hello.txt", 
    "gid": 0, 
    "group": "root", 
    "md5sum": "6f5902ac237024bdd0c176cb93063dc4", 
    "mode": "0644", 
    "owner": "root", 
    "secontext": "unconfined_u:object_r:admin_home_t:s0", 
    "size": 12, 
    "src": "/root/.ansible/tmp/ansible-tmp-1605945209.06-2426-102860851170573/source", 
    "state": "file", 
    "uid": 0
}

5)file模块

该模块主要用于设置文件的属性,比如创建文件、创建链接文件、删除文件等。

[root@tango-01 tmp]# ansible node01 -m file -a 'path=/tmp/ansible state=directory'
192.168.112.101 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "gid": 0, 
    "group": "root", 
    "mode": "0755", 
    "owner": "root", 
    "path": "/tmp/ansible", 
    "secontext": "unconfined_u:object_r:user_tmp_t:s0", 
    "size": 6, 
    "state": "directory", 
    "uid": 0
}

6)fetch模块

该模块用于从远程某主机获取(复制)文件到本地。

[root@tango-01 tmp]# ansible node01 -m fetch -a 'src=/tmp/hello-01.txt dest=/tmp'
192.168.112.101 | CHANGED => {
    "changed": true, 
    "checksum": "22596363b3de40b06f981fb85d82312e8c0ed511", 
    "dest": "/tmp/192.168.112.101/tmp/hello-01.txt", 
    "md5sum": "6f5902ac237024bdd0c176cb93063dc4", 
    "remote_checksum": "22596363b3de40b06f981fb85d82312e8c0ed511", 
    "remote_md5sum": null
}

7)cron模块

该模块适用于管理cron计划任务的。

[root@tango-01 tmp]# ansible node01 -m cron -a 'name="ntp update every 5 min" minute=*/5 job="/sbin/ntpdate 172.17.0.1 &> /dev/null"'
192.168.112.101 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "envs": [], 
    "jobs": [
        "ntp update every 5 min"
    ]
}

在tango-centos01节点可以看到定义的cron计划任务:

[root@tango-centos01 tmp]# cat /etc/passwd | cut -f 1 -d : |xargs -I {} crontab -l -u {}
#Ansible: ntp update every 5 min
*/5 * * * * /sbin/ntpdate 172.17.0.1 &> /dev/null

8)yum模块

顾名思义,该模块主要用于软件的安装。

[root@tango-01 /]# ansible node01 -m yum -a 'name=httpd state=present'
192.168.112.101 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "changes": {
        "installed": [
            "httpd"
        ]
    }, 
    "msg": "", 
    "rc": 0, 
    "results": [
        "Loaded plugins: fastestmirror\nLoading mirror speeds from cached hostfile\n * base: mirrors.cn99.com\n * extras: mirrors.cn99.com\n * updates: mirror.bit.edu.cn\nResolving Dependencies\n--> Running transaction check\n---> Package httpd.x86_64 0:2.4.6-97.el7.centos will be installed\n--> Processing Dependency: httpd-tools = 2.4.6-97.el7.centos for package: httpd-2.4.6-97.el7.centos.x86_64\n--> Processing Dependency: /etc/mime.types for package: httpd-2.4.6-97.el7.centos.x86_64\n--> Processing Dependency: libaprutil-1.so.0()(64bit) for package: httpd-2.4.6-97.el7.centos.x86_64\n--> Processing Dependency: libapr-1.so.0()(64bit) for package: httpd-2.4.6-97.el7.centos.x86_64\n--> Running transaction check\n---> Package apr.x86_64 0:1.4.8-7.el7 will be installed\n---> Package apr-util.x86_64 0:1.5.2-6.el7 will be installed\n---> Package httpd-tools.x86_64 0:2.4.6-97.el7.centos will be installed\n---> Package mailcap.noarch 0:2.1.41-2.el7 will be installed\n--> Finished Dependency Resolution\n\nDependencies Resolved\n\n================================================================================\n Package           Arch         Version                     Repository     Size\n================================================================================\nInstalling:\n httpd             x86_64       2.4.6-97.el7.centos         updates       2.7 M\nInstalling for dependencies:\n apr               x86_64       1.4.8-7.el7                 base          104 k\n apr-util          x86_64       1.5.2-6.el7                 base           92 k\n httpd-tools       x86_64       2.4.6-97.el7.centos         updates        93 k\n mailcap           noarch       2.1.41-2.el7                base           31 k\n\nTransaction Summary\n================================================================================\nInstall  1 Package (+4 Dependent packages)\n\nTotal download size: 3.0 M\nInstalled size: 10 M\nDownloading packages:\n--------------------------------------------------------------------------------\nTotal                                              453 kB/s | 3.0 MB  00:06     \nRunning transaction check\nRunning transaction test\nTransaction test succeeded\nRunning transaction\n  Installing : apr-1.4.8-7.el7.x86_64                                       1/5 \n  Installing : apr-util-1.5.2-6.el7.x86_64                                  2/5 \n  Installing : httpd-tools-2.4.6-97.el7.centos.x86_64                       3/5 \n  Installing : mailcap-2.1.41-2.el7.noarch                                  4/5 \n  Installing : httpd-2.4.6-97.el7.centos.x86_64                             5/5 \n  Verifying  : httpd-2.4.6-97.el7.centos.x86_64                             1/5 \n  Verifying  : apr-1.4.8-7.el7.x86_64                                       2/5 \n  Verifying  : mailcap-2.1.41-2.el7.noarch                                  3/5 \n  Verifying  : httpd-tools-2.4.6-97.el7.centos.x86_64                       4/5 \n  Verifying  : apr-util-1.5.2-6.el7.x86_64                                  5/5 \n\nInstalled:\n  httpd.x86_64 0:2.4.6-97.el7.centos                                            \n\nDependency Installed:\n  apr.x86_64 0:1.4.8-7.el7                     apr-util.x86_64 0:1.5.2-6.el7    \n  httpd-tools.x86_64 0:2.4.6-97.el7.centos     mailcap.noarch 0:2.1.41-2.el7    \n\nComplete!\n"
    ]
}

9)service 模块
该模块用于服务程序的管理。

[root@tango-01 /]# ansible node01 -m service -a 'name=docker state=started enabled=true'
192.168.112.101 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false, 
    "enabled": true, 
    "name": "docker", 
    "state": "started",

10)user模块

该模块主要是用来管理用户账号。

[root@tango-01 /]# ansible node01 -m user -a "name=test002 password=123"
[WARNING]: The input password appears not to have been hashed. The 'password' argument must be encrypted for this module to work properly.
192.168.112.101 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "comment": "", 
    "create_home": true, 
    "group": 1004, 
    "home": "/home/test002", 
    "name": "test002", 
    "password": "NOT_LOGGING_PASSWORD", 
    "shell": "/bin/bash", 
    "state": "present", 
    "system": false, 
    "uid": 1004
}

11)group模块

该模块主要用于添加或删除组。

[root@tango-01 /]# ansible node01 -m group -a 'name=test02 gid=1100'
192.168.112.101 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "gid": 1100, 
    "name": "test02", 
    "state": "present", 
    "system": false
}

12)setup模块

该模块主要用于收集信息,是通过调用facts组件来实现的。

[root@tango-01 tmp]# ansible node01 -m setup -a 'filter="*mem*"'
192.168.112.101 | SUCCESS => {
    "ansible_facts": {
        "ansible_memfree_mb": 60, 
        "ansible_memory_mb": {
            "nocache": {
                "free": 196, 
                "used": 780
            }, 
            "real": {
                "free": 60, 
                "total": 976, 
                "used": 916
            }, 
            "swap": {
                "cached": 17, 
                "free": 1962, 
                "total": 2047, 
                "used": 85
            }
        }, 
        "ansible_memtotal_mb": 976, 
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false
}
1.6 Ansible Playbook

Playbook是ansible用于配置、部署和管理被控节点的剧本,通过playbook的详细描述,执行其中的一系列tasks ,可以让远端主机达到预期的状态。playbook就像ansible控制器给被控节点列出的的一系列 tibo-do-list ,而被控节点必须要完成。

1.6.1 Ansible playbook格式

Playbook由YMAL语言编写,YMAL格式是类似于JSON的文件格式,便于人理解和阅读,同时便于书写。以下为playbook常用到的YMAL格式:

  1. 文件的第一行应该以 “—” (三个连字符)开始,表明YMAL文件的开始。
  2. 在同一行中,#之后的内容表示注释,类似于shell,python和ruby。
  3. YMAL中的列表元素以”-”开头然后紧跟着一个空格,后面为元素内容。
  4. 同一个列表中的元素应该保持相同的缩进。否则会被当做错误处理。
  5. play中hosts,variables,roles,tasks等对象的表示方法都是键值中间以":“分隔表示,”:"后面还要增加一个空格。

以下是一个playbook仅包含一个play:

---
- hosts: webservers
  vars:
    http_port: 80
    max_clients: 200
  remote_user: root
  tasks:
  - name: ensure apache is at the latest version
    yum: pkg=httpd state=latest
  - name: write the apache config file
    template: src=/srv/httpd.j2 dest=/etc/httpd.conf
    notify:
    - restart apache
  - name: ensure apache is running
    service: name=httpd state=started
  handlers:
    - name: restart apache
      service: name=httpd state=restarted

在以上Playbook中,包括以下元素:

  • Hosts主机:使用hosts指示使用哪个主机或主机组来运行下面的tasks,每个playbook都必须指定hosts
  • remote_user:指定远端主机中的哪个用户来登录远端系统,在远端系统执行task的用户,可以任意指定,也可以使用sudo,但是用户必须要有执行相应task的权限
  • tasks:指定远端主机将要执行的一系列动作,tasks的核心为ansible的模块,tasks包含name和要执行的模块。一个task在其所对应的所有主机上(通过 host pattern 匹配的所有主机)执行完毕之后,下一个task才会执行。如果一个host执行task失败,这个host将会从整个playbook的rotation中移除。
  • Handlers:在发生改变时执行的操作,‘notify’下列出的即是handlers。’notify’ actions会在playbook的每一个task结束时被触发,而且即使有多个不同的task通知改动的发生,‘notify’ actions 只会被触发一次
1.6.2 Ansible playbook示例

1)定义playbook

[root@tango-01 ansible]# vim nginx.yml
---
- hosts: node01
  remote_user: root
  tasks:
    - name: install nginx
      yum: name=nginx state=present
    - name: copy nginx.conf
      copy: src=/usr/local/docker/app/ansible/nginx.conf dest=/etc/nginx/nginx.conf backup=yes
      notify: reload
      tags: reloadnginx
    - name: start nginx service
      service: name=nginx state=started
      tags: startnginx
  handlers:
    - name: reload
      service: name=nginx state=restarted
  • notify: reload#当nginx.conf发生改变时,通知给相应的handlers
  • tags: reloadnginx#打标签

2)测试运行结果

[root@tango-01 ansible]# ansible-playbook nginx.yml

PLAY [node01] *************************************************************************************************************************************************************

TASK [Gathering Facts] ****************************************************************************************************************************************************
ok: [192.168.112.101]

TASK [install nginx] ******************************************************************************************************************************************************
ok: [192.168.112.101]

TASK [copy nginx.conf] ****************************************************************************************************************************************************
changed: [192.168.112.101]

TASK [start nginx service] ************************************************************************************************************************************************
changed: [192.168.112.101]

RUNNING HANDLER [reload] **************************************************************************************************************************************************
changed: [192.168.112.101]

PLAY RECAP ****************************************************************************************************************************************************************
192.168.112.101            : ok=5    changed=3    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

[root@tango-01 ansible]#

使用ansible-playbook运行playbook文件,得到如下输出信息,输出内容为JSON格式。执行有三个步骤:1、收集facts; 2、执行tasks ;3、报告结果

容器云系列之基于Docker的Ansible自动化运维实现

现在可以看看192.168.112.101机器的端口是否开启:

[root@tango-01 ansible]# ansible node01 -m shell -a 'ss -nutlp |grep nginx'
192.168.112.101 | CHANGED | rc=0 >>
tcp    LISTEN     0      128       *:80                    *:*                   users:(("nginx",pid=3755,fd=6),("nginx",pid=3754,fd=6))

3)测试标签

我们在里面已经打上了一个标签,所以可以直接引用标签。但是需要先把服务关闭,再来运行剧本并引用标签:

[root@tango-01 ansible]# ansible node01 -m shell -a 'systemctl stop nginx'
192.168.112.101 | CHANGED | rc=0 >>

[root@tango-01 ansible]# ansible-playbook nginx.yml -t startnginx

PLAY [node01] *************************************************************************************************************************************************************

TASK [Gathering Facts] ****************************************************************************************************************************************************
ok: [192.168.112.101]

TASK [start nginx service] ************************************************************************************************************************************************
changed: [192.168.112.101]

PLAY RECAP ****************************************************************************************************************************************************************
192.168.112.101            : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0  

4)测试notify

notify的触发条件是配置文件被改变,把配置文件中的端口改一下:

[root@tango-01 ansible]# vi nginx.conf
        listen       8080;

然后重新加载一下这个剧本,执行的就是reload段以及我们定义的notify部分:

[root@tango-01 ansible]# ansible-playbook nginx.yml -t reloadnginx

PLAY [node01] *************************************************************************************************************************************************************

TASK [Gathering Facts] ****************************************************************************************************************************************************
ok: [192.168.112.101]

TASK [copy nginx.conf] ****************************************************************************************************************************************************
changed: [192.168.112.101]

RUNNING HANDLER [reload] **************************************************************************************************************************************************
changed: [192.168.112.101]

PLAY RECAP ****************************************************************************************************************************************************************
192.168.112.101            : ok=3    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0  

再来看一看nginx端口号:

[root@tango-01 ansible]# ansible node01 -m shell -a 'ss -ntlp | grep nginx'
192.168.112.101 | CHANGED | rc=0 >>
LISTEN     0      128          *:8080                     *:*                   users:(("nginx",pid=4273,fd=6),("nginx",pid=4272,fd=6))

可以看出,nginx端口已经变成了8080。

下一篇将继续介绍Ansible的安装部署过程。


参考资料

  1. https://docs.ansible.com/ansible/latest/user_guide
  2. http://www.ansible.com.cn/
  3. https://www.cnblogs.com/keerya/p/7987886.html
  4. https://www.cnblogs.com/liuyansheng/p/6093139.html
  5. https://blog.csdn.net/len9596/article/details/82656902

转载请注明原文地址:https://blog.csdn.net/solihawk/article/details/121958764
文章会同步在公众号“牧羊人的方向”更新,感兴趣的可以关注公众号,谢谢!
容器云系列之基于Docker的Ansible自动化运维实现

上一篇:eclipse 发布web工程,修改tomcat端口


下一篇:Spotlight监控Oracle--Spotlight On Oracle安装和使用