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监控都是自动完成了。

文档更新时间: 2018-12-12 15:22   作者:李延召