通过ansible自动化部署zabbix应用
zabbix在实际的应用中,可能需要监控的主机非常多,而每个主机的操作系统类型、版本也都不尽相同,在这种环境下,通过手动安装zabbix的agent端已经不现实了,此时就需要借助自动化工具完成zabbix agent的安装和配置。
要对海量主机进行zabbix agent的部署,难点有几个方面,分别是:
1、要考虑每个主机的操作系统类型、版本
2、针对不同操作系统版本,需要安装不同类型的zabbix agent客户端版本
3、zabbix agent客户端安装完成后,还需要自动化的配置每个客户端
4、zabbix agent配置文件中有些配置参数可能和每个主机有关(例如IP地址),此时就需要将主机信息写入配置文件中,而每个主机的配置信息又各不相同。
5、每个主机上的配置文件自动配置后,最后还要启动主机上的zabbix agent服务。
针对上面的5个问题,如何来实现批量自动化部署和配置呢,这里我们介绍一款自动化工具ansible,通过此工具,就可以实现zabbix agent的批量自动化部署。下面我们将介绍ansible的入门与使用,最后介绍通过ansible-playbook自动化一键部署zabbix agent的方法。
一、 ansible介绍与安装使用
1.1、 ansible介绍与特点
ansible是一款自动化运维工具,基于Python开发,可以实现批量系统设置、批量程序部署、批量执行命令等功能。特点如下:
Ansible完全基于Python开发,要求python的版本为2.6以上。
Ansible丰富的内置模块,近600个模块完全满足日常功能所需
Ansible默认通过SSH协议管理机器,因此,客户端无需任何配置,管理端配置好后即可使用。
Ansible目前属于Redhat公司,最新版本为Ansible2.7。
ansible的在企业中的应用环境主要有如下几个方面:
应用代码自动化部署
系统管理配置自动化
支持持续交付自动化
支持云计算,大数据平台环境
批量任务执行可以写成脚本,不用分发到远程就可以执行
支持非root用户管理操作,支持sudo
使用python编写,维护更简单。
1.2、 ansible的安装
这里的安装环境是centos7.5版本操作系统,首先需要安装第三方epel源:
[root@ACA8D5EF ~]# yum install epel-release
Ansible依赖python环境,同时,Ansible已经是RHEL/Centos的一个组成部分,因此推荐通过yum安装ansible:
[root@ACA8D5EF ~]# yum install ansible
1.3、 ansible的命令套件
安装完ansible后,ansible一共提供了七个指令,分别是:ansible、ansible-doc、ansible-galaxy、ansible-lint、ansible-playbook、ansible-pull、ansible-vault 。
(1)、ansible
ansible是指令核心部分,其主要用于执行ad-hoc命令,即单条命令。默认后面需要跟主机和选项部分,默认不指定模块时,使用的是command模块。
(2)、ansible-doc
该指令用于查看模块信息,常用参数有两个-l 和 -s ,具体如下:
例如,列出所有已安装的模块:
# ansible-doc -l
查看具体某模块的用法,这里如查看command模块
# ansible-doc -s command
(3)、ansible-galaxy
ansible-galaxy 指令用于方便的从https://galaxy.ansible.com/ 站点下载第三方扩展模块,可以形象的理解其类似于centos下的yum、python下的pip或easy_install 。
(4)、ansible-lint
ansible-lint是对playbook的语法进行检查的一个工具。用法是ansible-lint playbook.yml 。
(5)、ansible-playbook
该指令是使用最多的指令,其通过读取playbook 文件后,执行相应的动作,这个后面会做为一个重点来讲。
(6)、ansible-pull
该指令使用需要谈到ansible的另一种模式:pull 模式,这和平常经常用的push模式刚好相反,其适用于以下场景:
有数量巨大的机器需要配置,即使使用非常高的线程还是要花费很多时间
要在一个没有网络连接的机器上运行Anisble,比如在启动之后安装。
(7)、ansible-vault
ansible-vault主要应用于配置文件中含有敏感信息,又不希望被人看到,vault可以帮你加密/解密这个配置文件,属高级用法。主要对于playbooks里比如涉及到配置密码或其他变量时,可以通过该指令加密,这样我们通过cat看到的是一个密码串类的文件,编辑的时候需要输入事先设定的密码才能打开。这种playbook文件在执行时,需要加上 –ask-vault-pass参数,同样需要输入密码后才能正常执行。
注:上面七个指令,用的最多的只有两个ansible 和ansible-playbook ,这两个一定要掌握,其它五个属于拓展或高级部分。
二、 ansible架构与运行原理
2.1、 ansible基本架构
下图是ansible的基本架构:
下面介绍下每个组成部分的含义:
核心:ansible
核心模块(Core Modules):是ansible自带的模块,Ansible模块资源分发到远程节点使其执行特定任务或匹配一个特定的状态。
扩展模块(Custom Modules):如果核心模块不足以完成某种功能,可以添加扩展模块。
插件(Plugins):完成较小型的任务。辅助模块来完成某个功能。
剧本(Playbooks):ansible的任务配置文件,将多个任务定义在剧本中,由ansible自动执行。例如安装一个nginx服务,那么我们可以把这拆分为几个任务放到一个playbook中。例如:第一步需要下载nginx的安装包。第二步我可能考虑需要做的就是将我事先写好的nginx.conf的配置文件下发的目标服务器上。第三步,我们需要把服务启动起来。第四步,我们可能需要检查端口是否正常开启。那么这些步骤可以通过playbook来进行整合,然后通过inventory来下发到想要执行剧本的主机上。
连接插件(Connectior Plugins):ansible基于连接插件连接到各个主机上,默认是基于SSH连接到目标机器上执行操作的,但是它还支持其他的连接方法,所以需要有连接插件,管理端支持local 、ssh、 paramiko三种方式连接被管理端。
主机清单(Host Inventory):定义ansible管理主机的策略,一般小型环境下只需要在host文件中写入主机的IP地址即可,但是到了中大型环境就需要使用静态inventory或者动态主机清单来生所需要执行的目标主机。
2.2、 ansible任务执行模式
ansible执行自动化任务,分为两种执行模式:
1、ad-hoc:单个模块,单条命令的批量执行,称之为ad-hoc
2、playbook:这个可以理解成为面向对象的编程,就像上面举例那样可以把多个想要执行的任务放到一个playbook中,当然多个任务在事物逻辑上最好是有上下联系的。通过多个任务可以完成一个总体的目标,这就是playbook。
三、 ansible主机和组的配置
3.1、简单的主机和组
ansible的配置文件位于/etc/ansible目录下,主要有ansible.cfg、hosts文件。本节重点介绍主机与组定义文件/etc/ansible/hosts.
/etc/ansible/hosts最简单的格式如下:
www.ixdba.net
[webservers]
ixdba1.net
ixdba2.net
[dbservers]
db.ixdba1.net
db.ixdba2.net
中括号中的名字代表组名,可以根据需求将庞大的主机分成具有标识的组,如上面分了两个组webservers和dbservers组;
主机(hosts)部分可以使用域名、主机名、IP地址表示;当然使用前两者时,也需要主机能反解析到相应的IP地址,一般此类配置中多使用IP地址;
未分组的机器需保留在hosts的顶部。
3.2、指定主机范围
可在/etc/ansible/hosts文件中,指定主机的范围,示例如下:
[web]
www[01:50].ixdba.net
[db]
db[a:f].ixdba.net
3.3、主机变量
以下是Hosts部分中经常用到的变量部分:
ansible_ssh_host #用于指定被管理的主机的真实IP
ansible_ssh_port #用于指定连接到被管理主机的ssh端口号,默认是22
ansible_ssh_user #ssh连接时默认使用的用户名
ansible_ssh_pass #ssh连接时的密码
ansible_sudo_pass #使用sudo连接用户时的密码
ansible_sudo_exec #如果sudo命令不在默认路径,需要指定sudo命令路径
ansible_ssh_private_key_file #秘钥文件路径,秘钥文件如果不想使用ssh-agent管理时可以使用此选项
ansible_shell_type #目标系统的shell的类型,默认sh
ansible_connection #SSH 连接的类型:local , ssh , paramiko,在 ansible1.2之前默认是 paramiko ,后来智能选择,优先使用基于ControlPersist 的ssh
ansible_pythoninterpreter #用来指定python解释器的路径,默认为/usr/bin/python 同样可以指定ruby 、perl的路径
ansible_interpreter #其他解释器路径,用法与ansible_python_interpreter类似,这里””可以是ruby或perl等其它语言
例子1:
[web]
192.168.78.11 http_port=80
192.168.78.12 http_port=80
还可以改成这样:
[web]
192.168.78.11
192.168.78.12
[web:vars]
http_port=80
例子2:
[webhost]
host1
host2
[dbhost]
host2
host3
[allhosts:children]
webhost
Dbhost
主机组可以包含主机组,主机的变量可以通过继承关系,继承到最高等级的组的变量。定义主机组之间的继承关系我们使用”:children”来表示.
四、 ansible.cfg与默认配置
/etc/ansible/ansible.cfg文件中定义了ansible的主机的默认配置部分,如默认是否需要输入密码、是否开启sudo认证、action_plugins插件的位置、hosts主机组的位置、是否开启log功能、默认端口、key文件位置等等。
#inventory = /etc/ansible/hosts 该参数表示资源清单inventory文件的位置,资源清单就是一些Ansible需要连接管理的主机列表
#library = /usr/share/my_modules/ Ansible的操作动作,无论是本地或远程,都使用一小段代码来执行,这小段代码称为模块,这个library参数就是指向存放Ansible模块的目录
#module_utils = /usr/share/my_module_utils/
#remote_tmp = ~/.ansible/tmp 指定远程执行的路径
#local_tmp = ~/.ansible/tmp ansible管理节点的执行路径
#forks = 5 forks 设置默认情况下Ansible最多能有多少个进程同时工作,默认设置最多5个进程并行处理。具体需要设置多少个,可以根据控制主机的性能和被管理节点的数量来确定。
#poll_interval = 15 轮询间隔
#sudo_user = root sudo使用的默认用户 ,默认是root
#ask_sudo_pass = True 是否需要用户输入sudo密码
#ask_pass = True 是否需要用户输入连接密码
#remote_port = 22 这是指定连接对端节点的管理端口,默认是22,除非设置了特殊的SSH端口,不然这个参数一般是不需要修改的
#module_lang = C 这是默认模块和系统之间通信的计算机语言,默认为’C’语言.
host_key_checking = False 跳过ssh首次连接提示验证部分,False表示跳过。#timeout = 10 连接超时时间
#module_name = command 指定ansible默认的执行模块
#nocolor = 1 默认ansible会为输出结果加上颜色,用来更好的区分状态信息和失败信息.如果你想关闭这一功能,可以把’nocolor’设置为‘1’:
#private_key_file=/path/to/file.pem 在使用ssh公钥私钥登录系统时候,使用的密钥路径。
五、 Ad-hoc与commands模块
5.1、Ad-Hoc 执行格式
Ad-Hoc 是指ansible下临时执行的一条命令,并且不需要保存的命令,对于复杂的命令后面会讲用playbook。讲到Ad-hoc 就要提到模块,所有的命令执行都要依赖于事先写好的模块,默认安装好的ansible里面已经自带了很多模块,如:command、raw、shell、file、cron等,具体可以通过ansible-doc -l 进行查看 。
ansible命令的常用选项:
-m MODULE_NAME:指定要执行的模块的名称,如果不指定-m选项,默认是COMMAND模块。
-a MODULE_ARGS,:指定执行模块对应的参数选项。
-k:提示输入SSH登录的密码而不是基于密钥的验证
-K:用于输入执行su或sudo操作时需要的认证密码。
-b:表示提升权限操作。
–become-method:指定提升权限的方法,常用的有 sudo和su,默认是sudo。
–become-user:指定执行 sudo或su命令时要切换到哪个用户下,默认是root用户。
-B SECONDS:后台运行超时时间
-C:测试一下会改变什么内容,不会真正去执行,主要用来测试一些可能发生的变化
-f FORKS,:设置ansible并行的任务数。默认值是5
-i INVENTORY: 指定主机清单文件的路径,默认为/etc/ansible/hosts。
一个ad-hoc命令的执行,需要按以下格式进行执行:
ansible 主机或组 -m 模块名 -a '模块参数' ansible参数
主机和组:是在/etc/ansible/hosts 里进行指定的部分,当然动态Inventory使用的是脚本从外部应用里获取的主机。
模块名:可以通过ansible-doc -l 查看目前安装的模块,默认不指定时,使用的是command模块,具体可以查看/etc/ansible/ansible.cfg 的“#module_name = command ” 部分,默认模块可以在该配置文件中进行修改;
模块参数:可以通过 “ansible-doc 模块名” 查看具体的用法及后面的参数;
ansible参数:可以通过ansible命令的帮忙信息里查看到,这里有很多参数可以供选择,如是否需要输入密码、是否sudo等。
5.2、commands模块
command模块包含如下选项:
creates:一个文件名,当该文件存在,则该命令不执行,反正,则执行。
free_form:要执行的linux指令
chdir:在执行指令之前,先切换到该指定的目录
removes:一个文件名,当该文件存在时,则该选项执行,反之,不执行。
注意:commands模块的执行,在远程主机上,需要有python环境的支持。
该模块通过-a跟上要执行的命令可以直接执行,不过命令里如果有带有特殊字符( “<“, “>”, “|”, “&”等)那么则执行不成功。
5.3、shell 模块
在远程节点上执行命令,用法和command一样,不过shell模块执行命令的时候使用的是/bin/sh,所以shell模块可以执行任何命令。
ansible 172.16.213.233 -m shell -a 'ps -ef|grep sshd'
ansible 172.16.213.233 -m shell -a 'sh /tmp/install.sh >/tmp/install.log'
上面这个命令是执行远程机器上的脚本,脚本路径为/tmp/install.sh(远程主机上的脚本,非本机的),然后将执行命令的结果存放在远程主机路径/tmp/install.log中,注意在进行保存文件的时候,写上全路径,否则就会保存在登录之后的默认路径中。
官方上说,command用起来更安全,更有可预知性。
5.4、raw模块
raw模块功能类似与前面说的command、shell能够完成的操作,raw也都能完成。不同的是,raw模块不需要远程主机上的python环境。
ansible要执行自动化操作,需要管理机上装ansible,客户机上也需要安装python,如果客户机上没有安装python模块,那么command、shell模块将无法工作,而raw却可以正常工作,因此,如果有的机器是没有装python,或者说安装的python版本在python2.4以下,就可以使用raw模块来装python、python-simplejson等。
如果有些机器压根就装不了python的话(比如交换机,路由器等),那么,直接用raw模块是最好的选择。
举例:
ansible 172.16.213.233 -m raw -a “ps -ef|grep sshd|awk ‘{print \$2}’ ”
ansible 172.16.213.107 -m raw -a "yum -y install python26" -k
raw模块和comand、shell模块不同的还有:raw没有chdir、creates、removes参数
[root@localhost ansible]# ansible 172.16.213.157 -m command -a 'chdir=/tmp touch test1.txt' -k
[root@localhost ansible]# ansible 172.16.213.157 -m shell -a 'chdir=/tmp touch test2.txt' -k
[root@localhost ansible]# ansible 172.16.213.157 -m raw -a 'chdir=/tmp touch test3.txt' -k
5.5、script模块
script模块是将管理端的shell脚本拷贝到被管理的远程主机上执行,其原理是先将shell复制到远程主机,再在远程主机上执行,此模块的执行,也不需要远程主机上的python环境。
ansible 172.16.213.233 -m script -a 'sh /tmp/install1.sh >/tmp/install.log'
脚本/tmp/install1.sh在管理端本机上,script 模块执行的时候将脚本传送到远程的172.16.213.233主机中,然后执行这个脚本,同时,将执行的输出日志文件保存在远程主机对应的路径/tmp/install.log下,这里保存日志文件的时候,最好用全路径。
六、 ansible其它常用功能模块
6.1、ping模块
测试主机是否是通的,用法很简单,不涉及参数:
[root@361way ~]# ansible 172.16.213.170 -m ping
172.16.213.170 | SUCCESS => {
"changed": false,
"ping": "pong"
}
6.2、file模块
file模块主要用于远程主机上的文件操作,file模块包含如下选项:
force:需要在两种情况下强制创建软链接,一种是源文件不存在但之后会建立的情况下;另一种是目标软链接已存在,需要先取消之前的软链,然后创建新的软链,有两个选项:yes|no
group:定义文件/目录的属组
mode:定义文件/目录的权限
owner:定义文件/目录的属主
path:必选项,定义文件/目录的路径
recurse:递归的设置文件的属性,只对目录有效
src:要被链接的源文件的路径,只应用于state=link的情况
dest:被链接到的目标路径,只应用于state=link的情况
state: 有如下几个选项:
directory:表示目录,如果目录不存在,则创建目录。
link:创建软链接
hard:创建硬链接
touch:如果文件不存在,则会创建一个新的文件,如果文件或目录已存在,则更新其最后修改时间
absent:删除目录、文件或者取消链接文件。
使用示例:
ansible 172.16.213.233 -m file -a "path=/mnt/abc123 state=directory"
ansible 172.16.213.233 -m file -a "path=/mnt/abc123 owner=nobody group=nobody mode=0644 recurse=yes"
ansible 172.16.213.233 -m file -a "path=/mnt/syncfile.txt owner=sshd group=sshd mode=0644"
ansible 172.16.213.233 -m file -a "path=/mnt/syncfile.txt mode=0444"
ansible 172.16.213.233 -m file -a "src=/etc/ssh/sshd_config dest=/mnt/sshd_config owner=sshd state=link"
ansible 172.16.213.233 -m file -a "path=/tmp/backup.tar.gz state=absent"
ansible 172.16.213.233 -m file -a "path=/tmp/ansibletemp state=touch"
6.3、copy模块
Copy模块用于复制文件到远程主机,copy模块包含如下选项:
backup:在覆盖之前将原文件备份,备份文件包含时间信息。有两个选项:yes|no
content:用于替代”src”,可以直接设定指定文件的值
dest:必选项。要将源文件复制到的远程主机的绝对路径,如果源文件是一个目录,那么该路径也必须是个目录
directory_mode:递归的设定目录的权限,默认为系统默认权限
force:如果目标主机包含该文件,但内容不同,如果设置为yes,则强制覆盖,如果为no,则只有当目标主机的目标位置不存在该文件时,才复制。默认为yes
others:所有的file模块里的选项都可以在这里使用
src:要复制到远程主机的文件在本地的地址,可以是绝对路径,也可以是相对路径。如果路径是一个目录,它将递归复制。在这种情况下,如果路径使用”/”来结尾,则只复制目录里的内容,如果没有使用”/”来结尾,则包含目录在内的整个内容全部复制,类似于rsync。
copy模块举例:
ansible 172.16.213.233 -m copy -a 'src=/etc/sudoers dest=/app/sudoers owner=root group=root mode=440 backup=yes'
ansible 172.16.213.233 -m copy -a "src=/etc/sudoers dest=/app/sudoers validate='visudo -cf %s'"
ansible 172.16.213.233 -m copy -a 'src=/etc/yum dest=/app/ owner=root group=root directory_mode=644'
ansible 172.16.213.233 -m copy -a 'src=/etc/yum/ dest=/app/bak owner=root group=root directory_mode=644'
6.4、service模块
用于管理远程主机上的服务,该模块包含如下选项:
enabled:是否开机启动 yes|no
name:必选项,服务名称
pattern:定义一个模式,如果通过status指令来查看服务的状态时,没有响应,就会通过ps指令在进程中根据该模式进行查找,如果匹配到,则认为该服务依然在运行
sleep:如果执行了restarted,在则stop和start之间沉睡几秒钟
state:对当前服务执行启动,停止、重启、重新加载等操作(started,stopped,restarted,reloaded)
使用示例:
ansible 172.16.213.233 -m service -a "name=httpd state=started"
ansible 172.16.213.233 -m service -a "name=httpd enabled=yes"
6.5、cron模块
用于管理计划任务,包含如下选项:
backup:对远程主机上的原任务计划内容修改之前做备份
cron_file:用来指定一个计划任务文件,也就是将计划任务写到远程主机上/etc/cron.d目录下,创建一个文件对应的计划任务。
day:日(1-31,,/2,……)
hour:小时(0-23,,/2,……)
minute:分钟(0-59,,/2,……)
month:月(1-12,,/2,……)
weekday:周(0-7,*,……)
job:要执行的任务,依赖于state=present
name:定义定时任务的描述信息
special_time: 特殊的时间范围,参数:reboot(重启时),annually(每年),monthly(每月),weekly(每周),daily(每天),hourly(每小时)
state:确认该任务计划是创建还是删除,有两个值可选,分别是present和absent,present表示创建定时任务,absent表示删除定时任务,默认为present。
user:以哪个用户的身份执行job指定的任务。
使用示例:
ansible 172.16.213.233 -m cron -a 'name="job for reboot" special_time=reboot job="/data/bootservice.sh"'
ansible 172.16.213.233 -m cron -a 'name="yum autoupdate" weekday="6" minute=20 hour=1 user="root" job="yum -y update"'
ansible 172.16.213.233 -m cron -a 'backup="True" name="autobackup" weekday="6" minute=30 hour=1 user="root" job="/home/ixdba/backup.sh"'
ansible 172.16.213.233 -m cron -a 'name="checkhttp" minute=30 hour=12 user="root" job="/home/ixdba/check_http.sh" cron_file="check_http_for_ansible" '
ansible 172.16.213.233 -m cron -a 'name="yum autoupdate" state=absent'
6.6、yum模块
使用yum包管理器来管理软件包,其选项有:
config_file:yum的配置文件
disable_gpg_check:关闭gpg_check
disablerepo:不启用某个源
enablerepo:启用某个源
name:要进行操作的软件包的名字,也可以传递一个url或者一个本地的rpm包的路径
state:表示要安装还是删除软件包,要安装软件包,可选择present(安装)、installed(安装)、 latest(安装最新版本),删除软件包可选择absent、removed。
示例如下:
ansible 172.16.213.77 -m yum -a "name=redis state=installed"
ansible 172.16.213.77 -m yum -a "name=redis state=removed"
ansible 172.16.213.77 -m yum -a "name=redis state=latest enablerepo=epel"
ansible 172.16.213.77 -m yum -a " name=http://mirrors.aliyun.com/centos/7.4.1708/os/x86_64/Packages/bash-4.2.46-28.el7.x86_64.rpm state=present "
6.7、user模块与group模块
user模块是请求的是useradd, userdel, usermod三个指令,goup模块请求的是groupadd, groupdel, groupmod 三个指令。
name # 指定用户名
group # 指定用户的主组
groups # 指定附加组,如果指定为(‘groups=’)表示删除所有组。
shell # 指定默认shell
state #设置帐号状态,不指定为默认为present,表示创建,指定值为absent表示删除
remove #当使用状态为state=absent时使用,类似于userdel –remove选项。
示例:
ansible 172.16.213.77 -m user -a "name=testuser1"
ansible 172.16.213.77 -m user -a "name=testuser2 groups=admins,developers" //添加用户时,同时添加附组
ansible 172.16.213.77 -m user -a "name=testuser3 state=absent remove=yes" //删除用户的同时 ,删除用记家目录
批量修改用户密码:
echo "123456" | openssl passwd -1 -salt $(< /dev/urandom tr -dc '[:alnum:]' | head -c 32) -stdin
$1$yjJ74Wid$x0QUaaHzA8EwWU2kG6SRB1
ansible 172.16.213.77 -m user -a 'name=testuser1 password="$1$Kklap7y3$3AYJdqrcmZUMt9W2/MYE4." '
-1:表示采用的是MD5加密算法。
-salt:指定salt值。在使用加密算法进行加密时,即使密码一样,salt不一样,所计算出来的hash值也不一样,除非密码一样,salt值也一样,计算出来的hash值才一样。
“< /dev/urandom tr -dc ‘[:alnum:]’ | head -c 32“产生一个随机的salt。
passwd的值不能是明文,passwd关键字后面应该是密文,且密文将被保存在/etc/shadow文件中。
6.8、synchronize模块
此模块通过调用rsync进行文件或目录同步。
archive:归档,相当于同时开启recursive(递归),links,perms,itmes,owner,group,-D选项都为yes,默认该选项为开启
checksum:跳过检测sum值,默认关闭
compress:是不开启压缩,默认开启
copy_links:复制链接文件,默认为no,注意后面还有一个links参数
delete:删除不存在的文件,默认为no
dest:目录路径
dest_prot:默认为22,ssh协议
mode:push和pull模块,push模块的话,一般用于从本机向远程主机上传文件,pull模式用于从远程主机上拉取文件
示例:
ansible 172.16.213.77 -m synchronize -a 'src=/mnt/a dest=/tmp'
ansible 172.16.213.77 -m synchronize -a 'mode=pull src=/mnt/a dest=/tmp'
6.9、setup模块
setup模块,主要用于获取主机信息,在playbooks里经常会用到的一个参数gather_facts就与该模块相关。setup模块下经常使用的一个参数是filter参数,具体使用示例如下(由于输出结果较多,这里只列命令不写结果):
[root@linux ~]# ansible 172.16.213.77 -m setup -a 'filter=ansible_*_mb'
表示查看主机内存信息
[root@linux ~]# ansible 172.16.213.77 -m setup -a 'filter=ansible_em[1-2]'
表示查看地接口为em1-2的网卡信息
[root@linux ~]# ansible all -m setup --tree /tmp/facts
表示将所有主机的信息输入到/tmp/facts目录下,每台主机的信息输入到主机名文件中(/etc/ansible/hosts里的主机名)
6.10、get_url模块
该模块主要用于从http、ftp、https服务器上下载文件(类似于wget),主要有如下选项:
sha256sum:下载完成后进行sha256 check;
timeout:下载超时时间,默认10s
url:下载的URL
url_password、url_username:主要用于需要用户名密码进行验证的情况
use_proxy:表示使用代理,代理需事先在环境变更中定义
示例:
ansible 172.16.213.77 -m get_url -a "url=http://172.16.213.157/Python-2.7.14.tgz dest=/mnt/python-2.7.14.tgz"
七、 ansible-playbook的使用
7.1、playbook简介
playbook字面意思,即剧本,现实中由演员按照剧本表演,在Ansible中,这次由计算机进行表演,由计算机安装,部署应用,提供对外服务,以及组织计算机处理各种各样的事情。
那么为什么要使用playbook呢?
执行一些简单的任务,使用ad-hoc命令可以方便的解决问题,但是有时一个设施过于复杂,需要大量的操作时候,执行的ad-hoc命令是不适合的,这时最好使用playbook,就像执行shell命令与写shell脚本一样,也可以理解为批处理任务,不过playbook有自己的语法格式。
7.2、playbook文件的格式
playbook文件由YAML语言编写。 YAML是一个类似 XML、JSON的标记性语言,YAML强调以数据为中心,并不是以标识语言为重点。因而YAML本身的定义比较简单,号称“一种人性化的数据格式语言”。首先学习了解一下YAML的格式,对后面书写playbook很有帮助。
以下为playbook常用到的YAML格式规范。
大小写敏感
使用空格作为嵌套缩进工具,缩进时不允许使用Tab键
缩进的空格数目不重要,只要相同层级的元素左侧对齐即可
使用“-”(横线) + 单个空格:表示单个列表项
使用 “:”(冒号) + 空格:表示单个键值对
使用”{}”表示一个键值表
文件的第一行应该以 ”—” (三个连字符)开始,表明YMAL文件的开始。
在同一行中,#之后的内容表示注释,类似于shell,python和ruby。
YMAL中的列表元素以”-”开头然后紧跟着一个空格,后面为元素内容。
同一个列表中的元素应该保持相同的缩进。否则会被当做错误处理。
play中hosts,variables,roles,tasks等对象的表示方法都是键值中间以”:”分隔表示,”:”后面还要增加一个空格。
下面是yaml文件的格式:
--- # 文档开始
- 第一章 简介
- 第二章 设计目录
# 客户订单
date: 2018-09-30
customer:
- name: Jai
items:
- no: 1234 #订单号
- descript: cpu
下面是Playbook文件格式例子:
- apple
- banana
- Orange
service: name=httpd state=restarted
等价于JSON的这种格式:
[
“apple”,
“banana”,
“orange”
]
playbook文件是通过ansible-playbook命令进行解析的,ansbile-playbook命令会根据自上而下的顺序依次执行playbook文件中的内容。同时,playbook开创了很多特性,它可以允许传输某个命令的状态到后面的指令,它也可以从一台机器的文件中抓取内容并附为变量,然后在另一台机器中使用,这使得playbook可以实现一些复杂的部署机制,这是ansible命令无法实现的。
7.3、playbook的构成
playbook是由一个或多个“play”组成的列表。play的主要功能在于,将事先合并为一组的主机装扮成事先通过ansible定义好的角色。将多个play组织在一个playbook中就可以让它们联同起来按事先编排的机制完成一系列复杂的任务。
其主要有以下四部分构成
target部分: 定义将要执行 playbook 的远程主机组
variable部分: 定义playbook运行时需要使用的变量
task部分: 定义将要在远程主机上执行的任务列表
handler部分: 定义task 执行完成以后需要调用的任务
而其对应的目录层为五个(视情况可变化),分别为:
vars 变量层
tasks 任务层
handlers 触发条件
files 文件
template 模板
7.4、playbook的语法详解
(1)、Hosts和Users
playbook中的每一个play的目的都是为了让某个或某些主机以某个指定的用户身份执行任务。
hosts:用于指定要执行指定任务的主机,每个playbook都必须指定hosts,hosts也可以使用通配符格式。主机或主机组在inventory清单中指定,可以使用系统默认的/etc/ansible/hosts,也可以自己编辑,在运行的时候加上-i选项,可指定自定义主机清单的位置。在运行清单文件的时候,–list-hosts选项会显示那些主机将会参与执行任务的过程中。
remote_user:用于指定在远程主机上执行任务的用户。可以指定任意用户,也可以使用sudo,但是用户必须要有执行相应任务的权限。
(2)、任务列表(tasks list)
play的主体部分是task list。
task list中的各任务按次序逐个在hosts中指定的所有主机上执行,即在所有主机上完成第一个任务后再开始第二个。在运行自上而下某playbook时,如果中途发生错误,则所有已执行任务都将回滚,因此在更正playbook后需要重新执行一次。
task的目的是使用指定的参数执行模块,而在模块参数中可以使用变量。模块执行是幂等的(幂等性; 即一个命令,即使执行一次或多次, 其结果也一样),这意味着多次执行是安全的,因为其结果均一致。tasks包含name和要执行的模块,name是可选的,只是为了便于用户阅读,建议加上去,模块是必须的,同时也要给予模块相应的参数。
定义tasks推荐使用module: options”的格式,例如:
service: name=httpd state=running
(3)、handlers
用于当关注的资源发生变化时采取一定的操作。handlers是和“notify”配合使用的。
“notify”这个动作可用于在每个play的最后被触发,这样可以避免多次有改变发生时,每次都执行指定的操作,通过“notify”,仅在所有的变化发生完成后一次性地执行指定操作。
在notify中列出的操作称为handler,也就是说notify用来调用handler中定义的操作。
注意:在 notify中定义的内容一定要和handlers中定义的“ - name”内容一样,这样才能达到触发的效果,否则会不生效。
(4)、tags
tags用于让用户选择运行或略过playbook中的部分代码。ansible具有幂等性,因此会自动跳过没有变化的部分;但是当一个playbook任务比较多时,一个一个的判断每个部分是否发生了变化,也需要很长时间。因此,如果确定某些部分没有发生变化,就可以通过tags跳过这些代码片断。
7.5、Playbook执行结果解析
使用ansible-playbook运行playbook文件,输出的内容为JSON格式。并且由不同颜色组成,便于识别。一般而言,输出内容中:
绿色代表执行成功,但系统保持原样
黄色代表系统状态发生改变,也就是执行的操作生效
红色代表执行失败,会显示错误信息。
一个简单的playbook文件:
- name: create user
hosts: 172.16.213.233
user: root
gather_facts: false
vars:
- user1: "testuser"
tasks:
- name: start createuser
user: name="{{ user1 }}"
上面的playbook 实现的功能是新增一个用户:
name参数对该playbook实现的功能做一个概述,后面执行过程中,会输出name的值;
hosts参数指定了对哪些主机进行操作。
user参数指定了使用什么用户登录到远程主机进行操作。
gather_facts参数指定了在下面任务执行前,是否先执行setup模块获取主机相关信息,这在后面的task会使用到setup获取的信息时需要用到。
vars参数,指定了变量,这里指字一个user1变量,其值为testuser,需要注意的是,变量值一定要用引号括起来。
tasks指定了一个任务,其下面的name参数同样是对任务的描述,在执行过程中会打印出来。user是一个模块,user后面的name是user模块里的一个参数,而增加的用户名字调用了上面user1变量的值。
7.6、收集facts信息
facts组件是Ansible用于采集被管理机器设备信息的一个功能。可以使用setup模块查机器的所有facts信息,facts信息包括远端主机发行版,IP地址,CPU核数,系统架构,主机名等等,可以使用filter来查看指定信息。整个facts信息被包装在一个json格式的数据结构中。
[root@ansible playbook]# ansible 172.16.213.233 -m setup
所有数据格式都是JSON格式,facts还支持查看指定信息,如下所示:
[root@ansible playbook]# ansible 172.16.213.233 -m setup -a 'filter=ansible_all_ipv4_addresses'
playbook在执行的时候,默认的第一个tasks就是收集远端被管主机的facts信息,如果后面的task不会使用到setup获取的信息时,可以禁止ansible收集facts,在playbook中的hosts指令下面设置“gather_facts: false”即可。默认gather_facts的值为true。
facts经常被用在条件语句和模板当中,也可以用于根据指定的标准创建动态主机组。
7.7、通过playbook自动化部署zabbix agent应用案例
下面是通过playbook自动化部署zabbix agent的一个yaml文件,内容如下:
- hosts: dlab
remote_user: root
gather_facts: yes
vars:
IPDD: "{{ ansible_default_ipv4['address'] }}"
tasks:
- name: update bash in cetnos 7 version
yum: name=https://repo.zabbix.com/zabbix/4.0/rhel/7/x86_64/zabbix-agent-4.0.0-2.el7.x86_64.rpm state=present
when: ansible_distribution == 'CentOS' and ansible_distribution_major_version == "7"
- name: update bash in cetnos 6 version
yum: name=https://repo.zabbix.com/zabbix/4.0/rhel/6/x86_64/zabbix-agent-4.0.1-1.el6.x86_64.rpm state=present
when: ansible_distribution == 'CentOS' and ansible_distribution_major_version == "6"
- name: Cofiguration zabbix-agent
copy: src=/app/zabbix_agentd.conf dest=/etc/zabbix/zabbix_agentd.conf
tags: zabbix_agentd.conf
- name: modif zabbix-agent.conf
lineinfile: dest=/etc/zabbix/zabbix_agentd.conf regexp=^Hostname=myip line=Hostname={{ IPDD }}
tags: zabbix_agentd.conf
- name: Start zabbix-agent
service: name=zabbix-agent state=started enabled=yes
tags: start zabbix-agent
这个playbook首先定义了一个主机组dlab,然后开启了gather_facts,接着,定义了一个变量IPDD,然后开始执行任务,第一个任务根据操作系统版本不同,安装不同的zabbix-agent,这里只涉及到了centos6.x和7.x版本,然后,将本地/app/zabbix_agentd.conf文件拷贝到远程dlab主机组,这是配置zabbix-agent,接下来,开始修改zabbix_agentd.conf文件中的内容,这里用到了lineinfile模块,这是个文件操作模块,它可以使用一个正则表达式替换、删除一个现有的行。最后一个任务是启动zabbix-agent服务。
好啦,自动化部署zabbix-agent,通过ansible就可以很轻松愉快的搞定了,而主机在部署zabbix以后,zabbix中可以通过开启自动发现功能,让zabbix web自动发现部署的主机,然后自动加入到zabbix web监控中,这样,从部署到主机接入zabbix web监控都是自动完成了。