本文简要介绍自动化运维工具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等模块。
- 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中的管理主机列表,并行的在这些主机中执行配置的任务, 最后等待执行返回的结果。
Ansible命令执行过程如下:
- 加载配置文件,默认/etc/ansible/ansible.cfg
- 查找对应的主机配置文件inventory,找到要执行的主机或者组
- 加载自己对应的模块文件,如command
- 通过ansible将模块或命令生成对应的临时py文件(python脚本), 并将该文件传输至远程服务器
- 对应执行home目录的.ansible/tmp/XXX/XXX.PY文件
- 给文件+x执行权限
- 执行并返回结果
- 删除临时py文件,sleep 0退出
1.3 Ansible配置详解
1.3.1 ansible配置文件
ansible的配置文件为/etc/ansible/ansible.cfg,ansible有许多参数,常见的参数如下:
1.3.2 Ansible Inventory文件
Ansible使用inventory定义管理的managed nodes和hosts,inventory的默认位置在/etc/ansible/hosts,也可以在命令中指定-I
1)Inventory常用的格式有INI和YAML两种,如下所示
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参数说明
以下为例:
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命令集
其中,比较常用的是/usr/bin/ansible和/usr/bin/ansible-playbook
2)ansible命令详解
命令的具体格式如下:
ansible <host-pattern> [-f forks] [-m module_name] [-a args]
也可以通过ansible -h来查看帮助
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格式:
- 文件的第一行应该以 “—” (三个连字符)开始,表明YMAL文件的开始。
- 在同一行中,#之后的内容表示注释,类似于shell,python和ruby。
- YMAL中的列表元素以”-”开头然后紧跟着一个空格,后面为元素内容。
- 同一个列表中的元素应该保持相同的缩进。否则会被当做错误处理。
- 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、报告结果
现在可以看看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的安装部署过程。
参考资料
- https://docs.ansible.com/ansible/latest/user_guide
- http://www.ansible.com.cn/
- https://www.cnblogs.com/keerya/p/7987886.html
- https://www.cnblogs.com/liuyansheng/p/6093139.html
- https://blog.csdn.net/len9596/article/details/82656902
转载请注明原文地址:https://blog.csdn.net/solihawk/article/details/121958764
文章会同步在公众号“牧羊人的方向”更新,感兴趣的可以关注公众号,谢谢!