自动化运维工具—ansible详解
一、ansible 简介
1、ansible 是什么?
Ansible是目前最流行的自动化运维工具,基于Python开发,集成了众多运维工具(SaltStack puppet、chef、func、fabric)的优点,用于批量系统配置、批量实现程序部署和批量。执行命令和其他功能。
Ansible是基于paramiko开发的,基于模块化工作。不具备批量部署的能力。批量部署实际上做的是ansible运行的一个模块,它只提供了框架。 Ansible基于ssh与远程主机通信,因此无需在远程主机上安装客户端/代理。 Ansible 被红帽正式收购,是最受认可且易于上手和学习的自动化运维工具。这是每个运维工程师必须掌握的技能之一。
2、ansible 特点
部署很简单,只需在主控端部署Ansible环境即可,控制端不需要做任何事情。设备管理默认使用SSH协议。维护操作模块,可以实现大部分日常操作。它功能强大且可扩展,支持API 和自定义模块,可通过强大的配置和状态管理进行轻量级定制。 Agent必须安装在客户端,只需要在操作系统上更新即可。 ——AWX 平台提供功能强大且易于使用的Web 管理和REST API 界面。
3、ansible 架构图
上图中主要模块有:
Ansible:Ansible 核心程序。
HostInventory:记录Ansible 管理的主机信息,例如端口、密码和IP。
Playbook:“脚本”YAML 格式文件。多个任务定义在一个文件中,该文件定义了主机应该调用哪个模块来完成功能。
CoreModules:核心模块。其主要操作是调用核心模块来完成管理任务。
CustomModules:自定义模块,可以完成核心模块无法完成的功能,并且支持多种语言。
ConnectionPlugins:用于Ansible 和主机通信的连接插件
二、ansible 任务执行
1、ansible 任务执行模式
Ansible 系统的控制主机与被管节点交互的方式可以分为两类:ad hoc 和playbook。
Ad hoc 模式(点对点模式)支持使用单个模块批量执行单个命令。即席命令是您可以立即输入且不需要保存的命令。相当于bash的语句shell。 Playbook模式是Ansible的主要管理方式,也是Ansible强大功能的关键。 Playbook通过多个任务集完成某些功能,例如安装和部署Web服务或数据库服务器的批量备份。 Playbook可以简单理解为组合了多个ad hoc操作的配置文件。 与shell 脚本类似,您可以在滚动模式(roll mode)下执行多个步骤,以及多个脚本导入。
2、ansible 执行流程
简单来说,Ansible 在运行时,首先读取ansible.cfg 中的配置,按照规则获取清单中的托管主机列表,在这些主机上并行运行配置的任务,最后等待结果被退回。通过执行。
3、ansible 命令执行过程
加载您自己的配置文件。默认为/etc/ansible/ansible.cfg。通过搜索对应的主机配置文件找到您要运行的主机或组。生成相应的模块。或者通过ansible的临时py文件(Python脚本)运行命令并将文件传输到远程服务器。授予文件+x 执行权限。运行并返回结果,删除临时py文件,并以sleep 0退出。
三、ansible 配置详解
1、ansible 安装方式
安装Ansible有两种常用的方法:yum安装和pip程序安装。
2、使用 yum 安装
yum安装就是我们熟悉的安装方式。您需要先安装epel-release 包,然后再安装ansible。
yum 安装epel-release -y
yum 安装ansible y
3、ansible 程序结构
安装目录如下(yum安装)。
配置文件目录:/etc/ansible/
可执行文件目录:/usr/bin/
Lib库依赖目录:/usr/lib/pythonX.X/site-packages/ansible/
帮助文档目录:/usr/share/doc/ansible-X.X.X/
man文档目录:/usr/share/man/man1/
4、ansible配置文件查找顺序
在这方面,Ansible 与其他服务有很大不同。这里的配置文件搜索按以下顺序搜索多个位置:
检查环境变量ANSIBLE_CONFIG指向的路径文件(export ANSIBLE_CONFIG=/etc/ansible.cfg)。检查当前目录中的ansible.cfg 配置文件。配置文件在etc目录下。
5、ansible配置文件
ansible 配置文件是/etc/ansible/ansible.cfg。 Ansible 有很多参数。以下是一些常用参数。
inventory=/etc/ansible/hosts #该参数表示资源清单inventory文件的位置
library=/usr/share/ansible #指向Ansible模块存储的目录。支持多个目录,只要目录之间用冒号(:) 分隔即可。
forks=5 #并发连接数,默认5
sudo_user=root #设置运行命令的默认用户
Remote_port=22 #指定连接被管节点的管理端口。默认为端口22。我们建议更改它以使其更安全。
host_key_checking=False #设置是否检查SSH主机的密钥。值为True/False。关闭后的第一个连接不会提示您配置实例。
timeout=60 #设置SSH连接超时时间,单位为秒
log_path=/var/log/ansible.log #指定保存ansible日志的文件(默认不记录日志)
6、ansible主机清单
在配置文件中,我们提到了资源列表。这是一个主机列表,包含ansible 需要连接和管理的主机列表。我们来看看他是如何定义的。
1. 直接指定主机地址或主机名。
#green.example.com
#blue.example.com
#192.168.100.1
#192.168.100.10
2. 定义主机组[组名称]并向其添加地址或主机名。
[mysql_测试]
192.168.253.159
192.168.253.160
192.168.253.153
192.168.153.[199:202]
3. [网页]
网1
网2
[web:vars]
ansible_ssh_root=\’根\’
ansible_ssh_pass=\’1\’
4. [网页]
网1
网2
[数据库]
数据库1
数据库2
【接待:名小朋友】
网络
数据库
ansible 主机–list-hosts
需要注意的是,这里的群组成员可以使用通配符进行匹配,标准化管理变得简单方便。 您可以根据自己的实际情况配置主机列表。具体操作如下。
[root@server ~]# vim /etc/ansible/hosts
[网络]
192.168.37.122
192.168.37.133
四、ansible 常用命令
1、ansible 命令集
/usr/bin/ansibleAnsibe AD-Hoc 临时命令执行工具。通常用于运行临时命令。
/usr/bin/ansible-doc Ansible模块功能查看工具
/usr/bin/ansible-galaxy 是基于网络下载/上传优秀代码和角色模块的官网平台。
/usr/bin/ansible-playbookAnsible 自定义自动化任务集编排工具
/usr/bin/ansible-pullAnsible是远程运行命令的工具(很少使用,在使用大量机器时使用,并且对运维架构能力要求较高)。
/usr/bin/ansible-vault Ansible 文件加密工具
/usr/bin/ansible-consoleAnsible 是一个基于Linux 控制台界面的命令执行工具,允许用户交互。
其中,我们经常使用/usr/bin/ansible和/usr/bin/ansible-playbook。
2、ansible-doc 命令
ansible-doc命令常用于获取模块信息和使用帮助。常见用法包括:
ansible-doc -l #获取所有模块的信息
ansible-doc -s MOD_NAME #获取指定模块的使用帮助
您还可以查看ansible-doc 的完整用法。
[root@server ~]# ansible-doc
用法: ansible-doc [选项] [模块.]
选项:
-h, –help 显示此帮助消息并退出# 命令参数显示API 文档
-l, –list 可用模块列表#可用模块列表
-M MODULE_PATH, –module-path=MODULE_PATH#指定模块路径
指定模块库的路径(默认=无)
-s, –snippet Display the playbook snippet for the specified module#显示指定模块在playbook中的使用情况
-v, –verbose 详细模式(详细使用-vvv,使用-vvvv启用) # 显示ansible-doc的版本号并显示模块列表。
连接调试)
–version 显示程序的版本号并退出
我们来看一个与mysql相关的例子。
[root@server ~]# ansible-doc -l |grep mysql
mysql_db 远程添加或删除MySQL 数据库.
mysql_replication 管理MySQL 复制
mysql_user 在MySQL 数据库中添加或删除用户.
mysql_variables 管理MySQL 全局变量
[root@server ~]# ansible-doc -s mysql_user
2、ansible 命令详解
该命令的具体格式为:
ansible 主机模式[-f forks] [-m module_name] [-a args]
Ansible 主机列表中的主机组-f 启用的线程数-m 模块-a 模块必需的参数
您还可以使用ansible -h 显示帮助。下面我们列出了一些更常用的选项并解释了它们的含义。
-a MODULE_ARGS #模块参数。如果执行默认的COMMAND模块,则为“date”、“pwd”等命令参数。
-k, –ask-pass #询问SSH密码。登录密码,提示输入SSH 密码,而不是假设基于密钥的身份验证
–ask-su-pass #su 询问密码。 su 切换密码
-K, –ask-sudo-pass #sudo 询问密码。如果提示输入密码,请使用sudo。 sudo 代表权限提升操作。
–ask-vault-pass #询问保管库密码。假设您设置了加密密码,请使用此选项访问
-B SECONDS #后台执行超时
– 可以模拟C#执行环境,进行预运行,并进行错误检查和测试。
-c CONNECTION #使用的连接类型
-f FORKS #并行任务数量,默认为5
-i INVENTORY # 指定主机列表的路径。默认为/etc/ansible/hosts。
–list-hosts #检查现有主机
-m MODULE_NAME #执行模块的名称。默认情况下使用命令模块,因此如果您只想运行单个命令,则不需要-m 参数。
-o #尝试压缩输出并将所有结果打印在一行上。通常用于收集工具。
-s #使用sudo命令
-U SUDO_USER #指定运行sudo 的用户。默认是root用户。
-T TIMEOUT # 指定SSH 的默认超时时间。默认为10 秒,可以在配置文件中更改。
-u REMOTE_USER #远程用户,默认为root用户
-v #显示详细信息,也支持-vvv,-vvvv可以显示更详细的信息
3、ansible 配置公私钥
前面我们提到Ansible是基于ssh协议实现的,所以设置公钥和私钥的方法与ssh协议相同。以下是具体步骤:
#1. 生成私钥
[root@server ~]# ssh-keygen
#2. 将私钥分发给主机
[root@server ~]# ssh-copy-id root@192.168.37.122
[root@server ~]# ssh-copy-id root@192.168.37.133
这样的话就可以实现免密码登录,使得实验过程更加顺利。 如果出现以下错误请注意:
-bash: ssh-copy-id:命令未找到
接下来,您将看到需要安装一个软件包。
yum -y 安装openssh 客户端
只需安装该软件包即可。
五、ansible 常用模块
1、主机连通性测试
使用ansible web -m ping 命令运行主机连接测试。结果如下。
[root@server ~]# ansible web -mping
192.168.37.122 | 成功={
‘修改’: false,
\’Pin\’: \’Pon\’
}
192.168.37.133 | 成功={
‘修改’: false,
\’Pin\’: \’Pon\’
}
这表明主机已连接。只有这样,后续的操作才能顺利进行。
2、command 模块
该模块可以直接在远程主机上执行命令并将结果返回给本地主机。 一个例子是:
[root@server ~]# ansible web -m 命令-a \’ss -ntl\’
192.168.37.122 | 成功|
状态Recv-Q Send-Q 本地地址: 端口对等地址: 端口
请听0 128 *:111 *:*
请听0 5 192.168.122.1:53 *:*
请听0 128 *:22 *:*
请听0 128 127.0.0.1:631 *:*
请听0 128 *:23000 *:*
请听0 100 127.0.0.1:25 *:*
请听0 128 :111 :*
请听0 128 :22 :*
请听0 128 :1:631 :*
请听0 100 :1:25 :*
192.168.37.133 | 成功|
状态Recv-Q Send-Q 本地地址: 端口对等地址: 端口
请听0 128 *:111 *:*
请听0 128 *:22 *:*
请听0 128 127.0.0.1:631 *:*
请听0 128 *:23000 *:*
请听0 100 127.0.0.1:25 *:*
请听0 128 :111 :*
请听0 128 :22 :*
请听0 128 :1:631 :*
请听0 100 :1:25 :*
命令模块接受命令名称后以空格分隔的参数列表。指定的命令将在所有选定的节点上执行。 $HOME 和\’\”,\”\”,\”|\”,\”;\”,\”\’ 等操作不能通过shell 进行(您必须使用(shell) 模块来实现这些功能)。请注意,该命令不支持管道命令。 我们来看看这个模块中的一些常用命令。
chdir # 运行命令之前先切换到该目录
executable # 切换shell 来执行命令。您必须使用命令的绝对路径
free_form # 要执行的Linux命令通常由Ansible的-a参数替换。
如果该文件存在,则该命令不会被执行,而是用于判断。
删除# 个文件名。如果该文件不存在,则不会执行该命令。
我们来看看运行这些命令的效果。
[root@server ~]# ansible web -m command -a \’chdir=/data/ls\’ #先切换到/data/目录,然后运行\’ls\’ 命令
192.168.37.122 | 成功|
哦.jpg
快速DFS
莫格数据
暂时的
网络
wKgleloeYoCAMLtZAAAWeekAtkc497.jpg
192.168.37.133 | 成功|
哦.jpg
快速DFS
莫格数据
暂时的
网络
wKgleloeYoCAMLtZAAAWeekAtkc497.jpg
[root@server ~]# ansible web -m command -a \’creates=/data/aaa.jpg ls\’ #如果/data/aaa.jpg存在则不会执行\’ls\’命令
192.168.37.122 | 成功|
/data/aaa.jpg 被跳过,因为它存在
192.168.37.133 | 成功|
/data/aaa.jpg 被跳过,因为它存在
[root@server ~]# ansible web -m command -a \’removes=/data/aaa.jpg cat /data/a\’ #如果/data/aaa.jpg存在,则使用\’cat /data/a\’ 命令执行
192.168.37.122 | 成功|
你好
192.168.37.133 |
SUCCESS | rc=0 >>
hello
3、shell 模块
shell模块可以在远程主机上调用shell解释器运行命令,支持shell的各种功能,例如管道等。
[root@server ~]# ansible web -m shell -a \’cat /etc/passwd |grep \”keer\”\’
192.168.37.122 | SUCCESS | rc=0 >>
keer:x:10001:1000:keer:/home/keer:/bin/sh
192.168.37.133 | SUCCESS | rc=0 >>
keer:x:10001:10001::/home/keer:/bin/sh
只要是我们的shell命令,都可以通过这个模块在远程主机上运行,这里就不一一举例了。
4、copy 模块
这个模块用于将文件复制到远程主机,同时支持给定内容生成文件和修改权限等。 其相关选项如下:
src #被复制到远程主机的本地文件。可以是绝对路径,也可以是相对路径。如果路径是一个目录,则会递归复制,用法类似于\”rsync\”
content #用于替换\”src\”,可以直接指定文件的值
dest #必选项,将源文件复制到的远程主机的绝对路径
backup #当文件内容发生改变后,在覆盖之前把源文件备份,备份文件包含时间信息
directory_mode #递归设定目录的权限,默认为系统默认权限
force #当目标主机包含该文件,但内容不同时,设为\”yes\”,表示强制覆盖;设为\”no\”,表示目标主机的目标位置不存在该文件才复制。默认为\”yes\”
others #所有的 file 模块中的选项可以在这里使用
用法举例如下: ① 复制文件:
[root@server ~]# ansible web -m copy -a \’src=~/hello dest=/data/hello\’
192.168.37.122 | SUCCESS => {
\”changed\”: true,
\”checksum\”: \”22596363b3de40b06f981fb85d82312e8c0ed511\”,
\”dest\”: \”/data/hello\”,
\”gid\”: 0,
\”group\”: \”root\”,
\”md5sum\”: \”6f5902ac237024bdd0c176cb93063dc4\”,
\”mode\”: \”0644\”,
\”owner\”: \”root\”,
\”size\”: 12,
\”src\”: \”/root/.ansible/tmp/ansible-tmp-1512437093.55-228281064292921/source\”,
\”state\”: \”file\”,
\”uid\”: 0
}
192.168.37.133 | SUCCESS => {
\”changed\”: true,
\”checksum\”: \”22596363b3de40b06f981fb85d82312e8c0ed511\”,
\”dest\”: \”/data/hello\”,
\”gid\”: 0,
\”group\”: \”root\”,
\”md5sum\”: \”6f5902ac237024bdd0c176cb93063dc4\”,
\”mode\”: \”0644\”,
\”owner\”: \”root\”,
\”size\”: 12,
\”src\”: \”/root/.ansible/tmp/ansible-tmp-1512437093.74-44694985235189/source\”,
\”state\”: \”file\”,
\”uid\”: 0
}
② 给定内容生成文件,并制定权限
[root@server ~]# ansible web -m copy -a \’content=\”I am keer\\n\” dest=/data/name mode=666\’
192.168.37.122 | SUCCESS => {
\”changed\”: true,
\”checksum\”: \”0421570938940ea784f9d8598dab87f07685b968\”,
\”dest\”: \”/data/name\”,
\”gid\”: 0,
\”group\”: \”root\”,
\”md5sum\”: \”497fa8386590a5fc89090725b07f175c\”,
\”mode\”: \”0666\”,
\”owner\”: \”root\”,
\”size\”: 10,
\”src\”: \”/root/.ansible/tmp/ansible-tmp-1512437327.37-199512601767687/source\”,
\”state\”: \”file\”,
\”uid\”: 0
}
192.168.37.133 | SUCCESS => {
\”changed\”: true,
\”checksum\”: \”0421570938940ea784f9d8598dab87f07685b968\”,
\”dest\”: \”/data/name\”,
\”gid\”: 0,
\”group\”: \”root\”,
\”md5sum\”: \”497fa8386590a5fc89090725b07f175c\”,
\”mode\”: \”0666\”,
\”owner\”: \”root\”,
\”size\”: 10,
\”src\”: \”/root/.ansible/tmp/ansible-tmp-1512437327.55-218104039503110/source\”,
\”state\”: \”file\”,
\”uid\”: 0
}
我们现在可以去查看一下我们生成的文件及其权限:
[root@server ~]# ansible web -m shell -a \’ls -l /data/\’
192.168.37.122 | SUCCESS | rc=0 >>
total 28
-rw-rw-rw- 1 root root 12 Dec 6 09:45 name
192.168.37.133 | SUCCESS | rc=0 >>
total 40
-rw-rw-rw- 1 root root 12 Dec 5 09:45 name
可以看出我们的name文件已经生成,并且权限为666。 ③ 关于覆盖 我们把文件的内容修改一下,然后选择覆盖备份:
[root@server ~]# ansible web -m copy -a \’content=\”I am keerya\\n\” backup=yes dest=/data/name mode=666\’
192.168.37.122 | SUCCESS => {
\”backup_file\”: \”/data/name.4394.2017-12-06@09:46:25~\”,
\”changed\”: true,
\”checksum\”: \”064a68908ab9971ee85dbc08ea038387598e3778\”,
\”dest\”: \”/data/name\”,
\”gid\”: 0,
\”group\”: \”root\”,
\”md5sum\”: \”8ca7c11385856155af52e560f608891c\”,
\”mode\”: \”0666\”,
\”owner\”: \”root\”,
\”size\”: 12,
\”src\”: \”/root/.ansible/tmp/ansible-tmp-1512438383.78-228128616784888/source\”,
\”state\”: \”file\”,
\”uid\”: 0
}
192.168.37.133 | SUCCESS => {
\”backup_file\”: \”/data/name.5962.2017-12-05@09:46:24~\”,
\”changed\”: true,
\”checksum\”: \”064a68908ab9971ee85dbc08ea038387598e3778\”,
\”dest\”: \”/data/name\”,
\”gid\”: 0,
\”group\”: \”root\”,
\”md5sum\”: \”8ca7c11385856155af52e560f608891c\”,
\”mode\”: \”0666\”,
\”owner\”: \”root\”,
\”size\”: 12,
\”src\”: \”/root/.ansible/tmp/ansible-tmp-1512438384.0-170718946740009/source\”,
\”state\”: \”file\”,
\”uid\”: 0
}
现在我们可以去查看一下:
[root@server ~]# ansible web -m shell -a \’ls -l /data/\’
192.168.37.122 | SUCCESS | rc=0 >>
total 28
-rw-rw-rw- 1 root root 12 Dec 6 09:46 name
-rw-rw-rw- 1 root root 10 Dec 6 09:45 name.4394.2017-12-06@09:46:25~
192.168.37.133 | SUCCESS | rc=0 >>
total 40
-rw-rw-rw- 1 root root 12 Dec 5 09:46 name
-rw-rw-rw- 1 root root 10 Dec 5 09:45 name.5962.2017-12-05@09:46:24~
可以看出,我们的源文件已经被备份,我们还可以查看一下name文件的内容:
[root@server ~]# ansible web -m shell -a \’cat /data/name\’
192.168.37.122 | SUCCESS | rc=0 >>
I am keerya
192.168.37.133 | SUCCESS | rc=0 >>
I am keerya
证明,这正是我们新导入的文件的内容。
5、file 模块
该模块主要用于设置文件的属性,比如创建文件、创建链接文件、删除文件等。 下面是一些常见的命令:
force #需要在两种情况下强制创建软链接,一种是源文件不存在,但之后会建立的情况下;另一种是目标软链接已存在,需要先取消之前的软链,然后创建新的软链,有两个选项:yes|no
group #定义文件/目录的属组。后面可以加上
mode:定义文件/目录的权限
owner #定义文件/目录的属主。后面必须跟上
path:定义文件/目录的路径
recurse #递归设置文件的属性,只对目录有效,后面跟上
src:被链接的源文件路径,只应用于state=link的情况
dest #被链接到的路径,只应用于state=link的情况
state #状态,有以下选项:
directory:如果目录不存在,就创建目录 link:创建软链接 hard:创建硬链接 touch:如果文件不存在,则会创建一个新的文件,如果文件或目录已存在,则更新其最后修改时间 absent:删除目录、文件或者取消链接文件
用法举例如下: ① 创建目录:
[root@server ~]# ansible web -m file -a \’path=/data/app state=directory\’
192.168.37.122 | SUCCESS => {
\”changed\”: true,
\”gid\”: 0,
\”group\”: \”root\”,
\”mode\”: \”0755\”,
\”owner\”: \”root\”,
\”path\”: \”/data/app\”,
\”size\”: 6,
\”state\”: \”directory\”,
\”uid\”: 0
}
192.168.37.133 | SUCCESS => {
\”changed\”: true,
\”gid\”: 0,
\”group\”: \”root\”,
\”mode\”: \”0755\”,
\”owner\”: \”root\”,
\”path\”: \”/data/app\”,
\”size\”: 4096,
\”state\”: \”directory\”,
\”uid\”: 0
}
我们可以查看一下:
[root@server ~]# ansible web -m shell -a \’ls -l /data\’
192.168.37.122 | SUCCESS | rc=0 >>
total 28
drwxr-xr-x 2 root root 6 Dec 6 10:21 app
192.168.37.133 | SUCCESS | rc=0 >>
total 44
drwxr-xr-x 2 root root 4096 Dec 5 10:21 app
可以看出,我们的目录已经创建完成。 ② 创建链接文件
[root@server ~]# ansible web -m file -a \’path=/data/bbb.jpg src=/data/aaa.jpg state=link\’
192.168.37.122 | SUCCESS => {
\”changed\”: true,
\”dest\”: \”/data/bbb.jpg\”,
\”gid\”: 0,
\”group\”: \”root\”,
\”mode\”: \”0777\”,
\”owner\”: \”root\”,
\”size\”: 7,
\”src\”: \”aaa.jpg\”,
\”state\”: \”link\”,
\”uid\”: 0
}
192.168.37.133 | SUCCESS => {
\”changed\”: true,
\”dest\”: \”/data/bbb.jpg\”,
\”gid\”: 0,
\”group\”: \”root\”,
\”mode\”: \”0777\”,
\”owner\”: \”root\”,
\”size\”: 7,
\”src\”: \”aaa.jpg\”,
\”state\”: \”link\”,
\”uid\”: 0
}
我们可以去查看一下:
[root@server ~]# ansible web -m shell -a \’ls -l /data\’
192.168.37.122 | SUCCESS | rc=0 >>
total 28
-rw-r–r– 1 root root 5649 Dec 5 13:49 aaa.jpg
lrwxrwxrwx 1 root root 7 Dec 6 10:25 bbb.jpg -> aaa.jpg
192.168.37.133 | SUCCESS | rc=0 >>
total 44
-rw-r–r– 1 root root 5649 Dec 4 14:44 aaa.jpg
lrwxrwxrwx 1 root root 7 Dec 5 10:25 bbb.jpg -> aaa.jpg
我们的链接文件已经创建成功。 ③ 删除文件
[root@server ~]# ansible web -m file -a \’path=/data/a state=absent\’
192.168.37.122 | SUCCESS => {
\”changed\”: true,
\”path\”: \”/data/a\”,
\”state\”: \”absent\”
}
192.168.37.133 | SUCCESS => {
\”changed\”: true,
\”path\”: \”/data/a\”,
\”state\”: \”absent\”
}
我们可以查看一下:
[root@server ~]# ansible web -m shell -a \’ls /data/a\’
192.168.37.122 | FAILED | rc=2 >>
ls: cannot access /data/a: No such file or directory
192.168.37.133 | FAILED | rc=2 >>
ls: cannot access /data/a: No such file or directory
发现已经没有这个文件了。
6、fetch 模块
该模块用于从远程某主机获取(复制)文件到本地。 有两个选项:
dest:用来存放文件的目录
src:在远程拉取的文件,并且必须是一个file,不能是目录
具体举例如下:
[root@server ~]# ansible web -m fetch -a \’src=/data/hello dest=/data\’
192.168.37.122 | SUCCESS => {
\”changed\”: true,
\”checksum\”: \”22596363b3de40b06f981fb85d82312e8c0ed511\”,
\”dest\”: \”/data/192.168.37.122/data/hello\”,
\”md5sum\”: \”6f5902ac237024bdd0c176cb93063dc4\”,
\”remote_checksum\”: \”22596363b3de40b06f981fb85d82312e8c0ed511\”,
\”remote_md5sum\”: null
}
192.168.37.133 | SUCCESS => {
\”changed\”: true,
\”checksum\”: \”22596363b3de40b06f981fb85d82312e8c0ed511\”,
\”dest\”: \”/data/192.168.37.133/data/hello\”,
\”md5sum\”: \”6f5902ac237024bdd0c176cb93063dc4\”,
\”remote_checksum\”: \”22596363b3de40b06f981fb85d82312e8c0ed511\”,
\”remote_md5sum\”: null
}
我们可以在本机上查看一下文件是否复制成功。要注意,文件保存的路径是我们设置的接收目录下的被管制主机ip目录下:
[root@server ~]# cd /data/
[root@server data]# ls
1 192.168.37.122 192.168.37.133 fastdfs web
[root@server data]# cd 192.168.37.122
[root@server 192.168.37.122]# ls
data
[root@server 192.168.37.122]# cd data/
[root@server data]# ls
hello
[root@server data]# pwd
/data/192.168.37.122/data
7、cron 模块
该模块适用于管理cron计划任务的。 其使用的语法跟我们的crontab文件中的语法一致,同时,可以指定以下选项:
day= #日应该运行的工作( 1-31, , /2, )
hour= # 小时 ( 0-23, , /2, )
minute= #分钟( 0-59, , /2, )
month= # 月( 1-12, *, /2, )
weekday= # 周 ( 0-6 for Sunday-Saturday, )
job= #指明运行的命令是什么
name= #定时任务描述
reboot # 任务在重启时运行,不建议使用,建议使用special_time
special_time #特殊的时间范围,参数:reboot(重启时),annually(每年),monthly(每月),weekly(每周),daily(每天),hourly(每小时)
state #指定状态,present表示添加定时任务,也是默认设置,absent表示删除定时任务
user # 以哪个用户的身份执行
举例如下: ① 添加计划任务
[root@server ~]# ansible web -m cron -a \’name=\”ntp update every 5 min\” minute=*/5 job=\”/sbin/ntpdate 172.17.0.1 &> /dev/null\”\’
192.168.37.122 | SUCCESS => {
\”changed\”: true,
\”envs\”: [],
\”jobs\”: [
\”ntp update every 5 min\”
]
}
192.168.37.133 | SUCCESS => {
\”changed\”: true,
\”envs\”: [],
\”jobs\”: [
\”ntp update every 5 min\”
]
}
我们可以去查看一下:
[root@server ~]# ansible web -m shell -a \’crontab -l\’
192.168.37.122 | SUCCESS | rc=0 >>
#Ansible: ntp update every 5 min
*/5 * * * * /sbin/ntpdate 172.17.0.1 &> /dev/null
192.168.37.133 | SUCCESS | rc=0 >>
#Ansible: ntp update every 5 min
*/5 * * * * /sbin/ntpdate 172.17.0.1 &> /dev/null
可以看出,我们的计划任务已经设置成功了。 ② 删除计划任务 如果我们的计划任务添加错误,想要删除的话,则执行以下操作: 首先我们查看一下现有的计划任务:
[root@server ~]# ansible web -m shell -a \’crontab -l\’
192.168.37.122 | SUCCESS | rc=0 >>
#Ansible: ntp update every 5 min
*/5 * * * * /sbin/ntpdate 172.17.0.1 &> /dev/null
#Ansible: df everyday
* 15 * * * df -lh >> /tmp/disk_total &> /dev/null
192.168.37.133 | SUCCESS | rc=0 >>
#Ansible: ntp update every 5 min
*/5 * * * * /sbin/ntpdate 172.17.0.1 &> /dev/null
#Ansible: df everyday
* 15 * * * df -lh >> /tmp/disk_total &> /dev/null
然后执行删除操作:
[root@server ~]# ansible web -m cron -a \’name=\”df everyday\” hour=15 job=\”df -lh >> /tmp/disk_total &> /dev/null\” state=absent\’
192.168.37.122 | SUCCESS => {
\”changed\”: true,
\”envs\”: [],
\”jobs\”: [
\”ntp update every 5 min\”
]
}
192.168.37.133 | SUCCESS => {
\”changed\”: true,
\”envs\”: [],
\”jobs\”: [
\”ntp update every 5 min\”
]
}
删除完成后,我们再查看一下现有的计划任务确认一下:
[root@server ~]# ansible web -m shell -a \’crontab -l\’
192.168.37.122 | SUCCESS | rc=0 >>
#Ansible: ntp update every 5 min
*/5 * * * * /sbin/ntpdate 172.17.0.1 &> /dev/null
192.168.37.133 | SUCCESS | rc=0 >>
#Ansible: ntp update every 5 min
*/5 * * * * /sbin/ntpdate 172.17.0.1 &> /dev/null
我们的删除操作已经成功。
8、yum 模块
顾名思义,该模块主要用于软件的安装。 其选项如下:
name= #所安装的包的名称
state= #present—>安装, latest—>安装最新的, absent—> 卸载软件。
update_cache #强制更新yum的缓存
conf_file #指定远程yum安装时所依赖的配置文件(安装本地已有的包)。
disable_gpg_check #是否禁止GPG checking,只用于presentor latest。
disablerepo #临时禁止使用yum库。 只用于安装或更新时。
enablerepo #临时使用的yum库。只用于安装或更新时。
下面我们就来安装一个包试试看:
[root@server ~]# ansible web -m yum -a \’name=htop state=present\’
192.168.37.122 | SUCCESS => {
\”changed\”: true,
\”msg\”: \”\”,
\”rc\”: 0,
\”results\”: [
\”Loaded plugins: fastestmirror, langpacks\\nLoading mirror speeds from cached hostfile\\nResolving Dependencies\\n–> Running transaction check\\n—> Package htop.x86_64 0:2.0.2-1.el7 will be installed\\n–> Finished Dependency Resolution\\n\\nDependencies Resolved\\n\\n================================================================================\\n Package Arch Version Repository Size\\n================================================================================\\nInstalling:\\n htop x86_64 2.0.2-1.el7 epel 98 k\\n\\nTransaction Summary\\n================================================================================\\nInstall 1 Package\\n\\nTotal download size: 98 k\\nInstalled size: 207 k\\nDownloading packages:\\nRunning transaction check\\nRunning transaction test\\nTransaction test succeeded\\nRunning transaction\\n Installing : htop-2.0.2-1.el7.x86_64 1/1 \\n Verifying : htop-2.0.2-1.el7.x86_64 1/1 \\n\\nInstalled:\\n htop.x86_64 0:2.0.2-1.el7 \\n\\nComplete!\\n\”
]
}
192.168.37.133 | SUCCESS => {
\”changed\”: true,
\”msg\”: \”Warning: RPMDB altered outside of yum.\\n** Found 3 pre-existing rpmdb problem(s), \’yum check\’ output follows:\\nipa-client-4.4.0-12.el7.centos.x86_64 has installed conflicts freeipa-client: ipa-client-4.4.0-12.el7.centos.x86_64\\nipa-client-common-4.4.0-12.el7.centos.noarch has installed conflicts freeipa-client-common: ipa-client-common-4.4.0-12.el7.centos.noarch\\nipa-common-4.4.0-12.el7.centos.noarch has installed conflicts freeipa-common: ipa-common-4.4.0-12.el7.centos.noarch\\n\”,
\”rc\”: 0,
\”results\”: [
\”Loaded plugins: fastestmirror, langpacks\\nLoading mirror speeds from cached hostfile\\nResolving Dependencies\\n–> Running transaction check\\n—> Package htop.x86_64 0:2.0.2-1.el7 will be installed\\n–> Finished Dependency Resolution\\n\\nDependencies Resolved\\n\\n================================================================================\\n Package Arch Version Repository Size\\n================================================================================\\nInstalling:\\n htop x86_64 2.0.2-1.el7 epel 98 k\\n\\nTransaction Summary\\n================================================================================\\nInstall 1 Package\\n\\nTotal download size: 98 k\\nInstalled size: 207 k\\nDownloading packages:\\nRunning transaction check\\nRunning transaction test\\nTransaction test succeeded\\nRunning transaction\\n Installing : htop-2.0.2-1.el7.x86_64 1/1 \\n Verifying : htop-2.0.2-1.el7.x86_64 1/1 \\n\\nInstalled:\\n htop.x86_64 0:2.0.2-1.el7 \\n\\nComplete!\\n\”
]
}
安装成功。
9、service 模块
该模块用于服务程序的管理。 其主要选项如下:
arguments #命令行提供额外的参数
enabled #设置开机启动。
name= #服务名称
runlevel #开机启动的级别,一般不用指定。
sleep #在重启服务的过程中,是否等待。如在服务关闭以后等待2秒再启动。(定义在剧本中。)
state #有四种状态,分别为:started—>启动服务, stopped—>停止服务, restarted—>重启服务, reloaded—>重载配置
下面是一些例子: ① 开启服务并设置自启动
[root@server ~]# ansible web -m service -a \’name=nginx state=started enabled=true\’
192.168.37.122 | SUCCESS => {
\”changed\”: true,
\”enabled\”: true,
\”name\”: \”nginx\”,
\”state\”: \”started\”,
……
}
192.168.37.133 | SUCCESS => {
\”changed\”: true,
\”enabled\”: true,
\”name\”: \”nginx\”,
\”state\”: \”started\”,
……
}
我们可以去查看一下端口是否打开:
[root@server ~]# ansible web -m shell -a \’ss -ntl\’
192.168.37.122 | SUCCESS | rc=0 >>
State Recv-Q Send-Q Local Address:Port Peer Address:Port
LISTEN 0 128 *:80 *:*
192.168.37.133 | SUCCESS | rc=0 >>
State Recv-Q Send-Q Local Address:Port Peer Address:Port
LISTEN 0 128 *:80 *:*
可以看出我们的80端口已经打开。 ② 关闭服务 我们也可以通过该模块来关闭我们的服务:
[root@server ~]# ansible web -m service -a \’name=nginx state=stopped\’
192.168.37.122 | SUCCESS => {
\”changed\”: true,
\”name\”: \”nginx\”,
\”state\”: \”stopped\”,
……
}
192.168.37.133 | SUCCESS => {
\”changed\”: true,
\”name\”: \”nginx\”,
\”state\”: \”stopped\”,
……
}
一样的,我们来查看一下端口:
[root@server ~]# ansible web -m shell -a \’ss -ntl | grep 80\’
192.168.37.122 | FAILED | rc=1 >>
192.168.37.133 | FAILED | rc=1 >>
可以看出,我们已经没有80端口了,说明我们的nginx服务已经关闭了。
10、user 模块
该模块主要是用来管理用户账号。 其主要选项如下:
comment # 用户的描述信息
createhome # 是否创建家目录
force # 在使用state=absent时, 行为与userdel –force一致.
group # 指定基本组
groups # 指定附加组,如果指定为(groups=)表示删除所有组
home # 指定用户家目录
move_home # 如果设置为home=时, 试图将用户主目录移动到指定的目录
name # 指定用户名
non_unique # 该选项允许改变非唯一的用户ID值
password # 指定用户密码,对密码加密可以使用python的crypt和passlib
remove # 在使用state=absent时, 行为是与userdel –remove一致
shell # 指定默认shell
state # 设置帐号状态,不指定为创建,指定值为absent表示删除
system # 当创建一个用户,设置这个用户是系统用户。这个设置不能更改现有用户
uid # 指定用户的uid
举例如下: ① 添加一个用户并指定其 uid
[root@server ~]# ansible web -m user -a \’name=keer uid=11111\’
192.168.37.122 | SUCCESS => {
\”changed\”: true,
\”comment\”: \”\”,
\”createhome\”: true,
\”group\”: 11111,
\”home\”: \”/home/keer\”,
\”name\”: \”keer\”,
\”shell\”: \”/bin/bash\”,
\”state\”: \”present\”,
\”stderr\”: \”useradd: warning: the home directory already exists.\\nNot copying any file from skel directory into it.\\nCreating mailbox file: File exists\\n\”,
\”system\”: false,
\”uid\”: 11111
}
192.168.37.133 | SUCCESS => {
\”changed\”: true,
\”comment\”: \”\”,
\”createhome\”: true,
\”group\”: 11111,
\”home\”: \”/home/keer\”,
\”name\”: \”keer\”,
\”shell\”: \”/bin/bash\”,
\”state\”: \”present\”,
\”stderr\”: \”useradd: warning: the home directory already exists.\\nNot copying any file from skel directory into it.\\nCreating mailbox file: File exists\\n\”,
\”system\”: false,
\”uid\”: 11111
}
添加完成,我们可以去查看一下:
[root@server ~]# ansible web -m shell -a \’cat /etc/passwd |grep keer\’
192.168.37.122 | SUCCESS | rc=0 >>
keer:x:11111:11111::/home/keer:/bin/bash
192.168.37.133 | SUCCESS | rc=0 >>
keer:x:11111:11111::/home/keer:/bin/bash
② 删除用户
[root@server ~]# ansible web -m user -a \’name=keer state=absent\’
192.168.37.122 | SUCCESS => {
\”changed\”: true,
\”force\”: false,
\”name\”: \”keer\”,
\”remove\”: false,
\”state\”: \”absent\”
}
192.168.37.133 | SUCCESS => {
\”changed\”: true,
\”force\”: false,
\”name\”: \”keer\”,
\”remove\”: false,
\”state\”: \”absent\”
}
一样的,删除之后,我们去看一下:
[root@server ~]# ansible web -m shell -a \’cat /etc/passwd |grep keer\’
192.168.37.122 | FAILED | rc=1 >>
192.168.37.133 | FAILED | rc=1 >>
发现已经没有这个用户了。
11、group 模块
该模块主要用于添加或删除组。 常用的选项如下:
gid= #设置组的GID号
name= #指定组的名称
state= #指定组的状态,默认为创建,设置值为absent为删除 system= #设置值为yes,表示创建为系统组
举例如下: ① 创建组
[root@server ~]# ansible web -m group -a \’name=sanguo gid=12222\’
192.168.37.122 | SUCCESS => {
\”changed\”: true,
\”gid\”: 12222,
\”name\”: \”sanguo\”,
\”state\”: \”present\”,
\”system\”: false
}
192.168.37.133 | SUCCESS => {
\”changed\”: true,
\”gid\”: 12222,
\”name\”: \”sanguo\”,
\”state\”: \”present\”,
\”system\”: false
}
创建过后,我们来查看一下:
[root@server ~]# ansible web -m shell -a \’cat /etc/group | grep 12222\’
192.168.37.122 | SUCCESS | rc=0 >>
sanguo:x:12222:
192.168.37.133 | SUCCESS | rc=0 >>
sanguo:x:12222:
可以看出,我们的组已经创建成功了。 ② 删除组
[root@server ~]# ansible web -m group -a \’name=sanguo state=absent\’
192.168.37.122 | SUCCESS => {
\”changed\”: true,
\”name\”: \”sanguo\”,
\”state\”: \”absent\”
}
192.168.37.133 | SUCCESS => {
\”changed\”: true,
\”name\”: \”sanguo\”,
\”state\”: \”absent\”
}
照例查看一下:
[root@server ~]# ansible web -m shell -a \’cat /etc/group | grep 12222\’
192.168.37.122 | FAILED | rc=1 >>
192.168.37.133 | FAILED | rc=1 >>
已经没有这个组的相关信息了。
12、script 模块
该模块用于将本机的脚本在被管理端的机器上运行。 该模块直接指定脚本的路径即可,我们通过例子来看一看到底如何使用的: 首先,我们写一个脚本,并给其加上执行权限:
[root@server ~]# vim /tmp/df.sh
#!/bin/bash
date >> /tmp/disk_total.log
df -lh >> /tmp/disk_total.log
[root@server ~]# chmod +x /tmp/df.sh
然后,我们直接运行命令来实现在被管理端执行该脚本:
[root@server ~]# ansible web -m script -a \’/tmp/df.sh\’
192.168.37.122 | SUCCESS => {
\”changed\”: true,
\”rc\”: 0,
\”stderr\”: \”Shared connection to 192.168.37.122 closed.\\r\\n\”,
\”stdout\”: \”\”,
\”stdout_lines\”: []
}
192.168.37.133 | SUCCESS => {
\”changed\”: true,
\”rc\”: 0,
\”stderr\”: \”Shared connection to 192.168.37.133 closed.\\r\\n\”,
\”stdout\”: \”\”,
\”stdout_lines\”: []
}
照例查看一下文件内容:
[root@server ~]# ansible web -m shell -a \’cat /tmp/disk_total.log\’
192.168.37.122 | SUCCESS | rc=0 >>
Tue Dec 5 15:58:21 CST 2017
Filesystem Size Used Avail Use% Mounted on
/dev/sda2 47G 4.4G 43G 10% /
devtmpfs 978M 0 978M 0% /dev
tmpfs 993M 84K 993M 1% /dev/shm
tmpfs 993M 9.1M 984M 1% /run
tmpfs 993M 0 993M 0% /sys/fs/cgroup
/dev/sda3 47G 33M 47G 1% /app
/dev/sda1 950M 153M 798M 17% /boot
tmpfs 199M 16K 199M 1% /run/user/42
tmpfs 199M 0 199M 0% /run/user/0
192.168.37.133 | SUCCESS | rc=0 >>
Tue Dec 5 15:58:21 CST 2017
Filesystem Size Used Avail Use% Mounted on
/dev/sda2 46G 4.1G 40G 10% /
devtmpfs 898M 0 898M 0% /dev
tmpfs 912M 84K 912M 1% /dev/shm
tmpfs 912M 9.0M 903M 1% /run
tmpfs 912M 0 912M 0% /sys/fs/cgroup
/dev/sda3 3.7G 15M 3.4G 1% /app
/dev/sda1 1.9G 141M 1.6G 9% /boot
tmpfs 183M 16K 183M 1% /run/user/42
tmpfs 183M 0 183M 0% /run/user/0
可以看出已经执行成功了。
13、setup 模块
该模块主要用于收集信息,是通过调用facts组件来实现的。
facts组件是Ansible用于采集被管机器设备信息的一个功能,我们可以使用setup模块查机器的所有facts信息,可以使用filter来查看指定信息。整个facts信息被包装在一个JSON格式的数据结构中,ansible_facts是最上层的值。
facts就是变量,内建变量 。每个主机的各种信息,cpu颗数、内存大小等。会存在facts中的某个变量中。调用后返回很多对应主机的信息,在后面的操作中可以根据不同的信息来做不同的操作。如redhat系列用yum安装,而debian系列用apt来安装软件。
① 查看信息
我们可以直接用命令获取到变量的值,具体我们来看看例子:
[root@server ~]# ansible web -m setup -a \’filter=\”*mem*\”\’ #查看内存
192.168.37.122 | SUCCESS => {
\”ansible_facts\”: {
\”ansible_memfree_mb\”: 1116,
\”ansible_memory_mb\”: {
\”nocache\”: {
\”free\”: 1397,
\”used\”: 587
},
\”real\”: {
\”free\”: 1116,
\”total\”: 1984,
\”used\”: 868
},
\”swap\”: {
\”cached\”: 0,
\”free\”: 3813,
\”total\”: 3813,
\”used\”: 0
}
},
\”ansible_memtotal_mb\”: 1984
},
\”changed\”: false
}
192.168.37.133 | SUCCESS => {
\”ansible_facts\”: {
\”ansible_memfree_mb\”: 1203,
\”ansible_memory_mb\”: {
\”nocache\”: {
\”free\”: 1470,
\”used\”: 353
},
\”real\”: {
\”free\”: 1203,
\”total\”: 1823,
\”used\”: 620
},
\”swap\”: {
\”cached\”: 0,
\”free\”: 3813,
\”total\”: 3813,
\”used\”: 0
}
},
\”ansible_memtotal_mb\”: 1823
},
\”changed\”: false
}
我们可以通过命令查看一下内存的大小以确认一下是否一致:
[root@server ~]# ansible web -m shell -a \’free -m\’
192.168.37.122 | SUCCESS | rc=0 >>
total used free shared buff/cache available
Mem: 1984 404 1122 9 457 1346
Swap: 3813 0 3813
192.168.37.133 | SUCCESS | rc=0 >>
total used free shared buff/cache available
Mem: 1823 292 1207 9 323 1351
Swap: 3813 0 3813
可以看出信息是一致的。
② 保存信息
我们的setup模块还有一个很好用的功能就是可以保存我们所筛选的信息至我们的主机上,同时,文件名为我们被管制的主机的IP,这样方便我们知道是哪台机器出的问题。
我们可以看一看例子:
[root@server tmp]# ansible web -m setup -a \’filter=\”*mem*\”\’ –tree /tmp/facts
192.168.37.122 | SUCCESS => {
\”ansible_facts\”: {
\”ansible_memfree_mb\”: 1115,
\”ansible_memory_mb\”: {
\”nocache\”: {
\”free\”: 1396,
\”used\”: 588
},
\”real\”: {
\”free\”: 1115,
\”total\”: 1984,
\”used\”: 869
},
\”swap\”: {
\”cached\”: 0,
\”free\”: 3813,
\”total\”: 3813,
\”used\”: 0
}
},
\”ansible_memtotal_mb\”: 1984
},
\”changed\”: false
}
192.168.37.133 | SUCCESS => {
\”ansible_facts\”: {
\”ansible_memfree_mb\”: 1199,
\”ansible_memory_mb\”: {
\”nocache\”: {
\”free\”: 1467,
\”used\”: 356
},
\”real\”: {
\”free\”: 1199,
\”total\”: 1823,
\”used\”: 624
},
\”swap\”: {
\”cached\”: 0,
\”free\”: 3813,
\”total\”: 3813,
\”used\”: 0
}
},
\”ansible_memtotal_mb\”: 1823
},
\”changed\”: false
}
然后我们可以去查看一下:
[root@server ~]# cd /tmp/facts/
[root@server facts]# ls
192.168.37.122 192.168.37.133
[root@server facts]# cat 192.168.37.122
{\”ansible_facts\”: {\”ansible_memfree_mb\”: 1115, \”ansible_memory_mb\”: {\”nocache\”: {\”free\”: 1396, \”used\”: 588}, \”real\”: {\”free\”: 1115, \”total\”: 1984, \”used\”: 869}, \”swap\”: {\”cached\”: 0, \”free\”: 3813, \”total\”: 3813, \”used\”: 0}}, \”ansible_memtotal_mb\”: 1984}, \”changed\”: false}
14、get_url模块
get_url模块
用途: 用于将文件或软件从http、https或ftp下载到本地节点上
常用参数:
dest: 指定将文件下载的绝对路径—必须
url: 文件的下载地址(网址)—必须
url_username: 用于http基本认证的用户名
url_password: 用于http基本认证的密码
validate_certs: 如果否,SSL证书将不会验证。这只应在使用自签名证书的个人控制站点上使用
owner: 指定属主
group: 指定属组
mode: 指定权限
ansible -i /etc/ansible/hosts zabbix -m get_url -a \”url=ftp://10.3.131.50/soft/wechat.py dest=/tmp\”
15、stat模块
用途:检查文件或文件系统的状态
注意:
对于Windows目标,请改用win_stat模块
选项:
path:文件/对象的完整路径(必须)
案例:
name: install_apcu | Check if apcu local file is already configured.
stat: path={{ php_apcu_file_path }}
connection: local
register: php_apcu_file_result
常用的返回值判断:
exists: 判断是否存在
isuid: 调用用户的ID与所有者ID是否匹配
16、unarchive模块
用途:从本地机器上复制存档后,将其解包。
说明:
该unarchive模块将解压缩一个存档。
默认情况下,它将在解包之前将源文件从本地系统复制到目标。
设置remote_src=yes为解包目标上已经存在的档案。
对于Windows目标,请改用win_unzip模块。
常用选项:
dest:远程绝对路径,档案应该被解压缩
exec:列出需要排除的目录和文件
src:指定源
creates:一个文件名,当它已经存在时,这个步骤将不会被运行。
ansible -i /etc/ansible/hosts web -m unarchive -a \’src=/root/easy-springmvc-maven.zip dest=/tmp\’
– name: Extract foo.tgz into /var/lib/foo
unarchive:
src: foo.tgz
dest: /var/lib/foo
– name: Unarchive a file that is already on the remote machine
unarchive:
src: /tmp/foo.zip
dest: /usr/local/bin
remote_src: yes
– name: Unarchive a file that needs to be downloaded (added in 2.0)
unarchive:
src: https://example.com/example.zip
dest: /usr/local/bin
remote_src: yes
六、Ansible playbook 简介
playbook 是 ansible 用于配置,部署,和管理被控节点的剧本。 通过 playbook 的详细描述,执行其中的一系列 tasks ,可以让远端主机达到预期的状态。playbook 就像 Ansible 控制器给被控节点列出的的一系列 to-do-list ,而被控节点必须要完成。 也可以这么理解,playbook 字面意思,即剧本,现实中由演员按照剧本表演,在Ansible中,这次由计算机进行表演,由计算机安装,部署应用,提供对外服务,以及组织计算机处理各种各样的事情。
七、Ansible playbook使用场景
执行一些简单的任务,使用ad-hoc命令可以方便的解决问题,但是有时一个设施过于复杂,需要大量的操作时候,执行的ad-hoc命令是不适合的,这时最好使用playbook。 就像执行shell命令与写shell脚本一样, 也可以理解为批处理任务,不过playbook有自己的语法格式。 使用playbook你可以方便的重用这些代码,可以移植到不同的机器上面,像函数一样,最大化的利用代码。在你使用Ansible的过程中,你也会发现,你所处理的大部分操作都是编写playbook。可以把常见的应用都编写成playbook,之后管理服务器会变得十分简单。
八、Ansible playbook格式
1、格式简介
playbook由YMAL语言编写。YAML( /ˈjæməl/ )参考了其他多种语言,包括:XML、C语言、Python、Perl以及电子邮件格式RFC2822,Clark Evans在2001年5月在首次发表了这种语言,另外Ingy döt Net与OrenBen-Kiki也是这语言的共同设计者。 YMAL格式是类似于JSON的文件格式,便于人理解和阅读,同时便于书写。首先学习了解一下YMAL的格式,对我们后面书写playbook很有帮助。
以下为playbook常用到的YMAL格式:
1、文件的第一行应该以 “—” (三个连字符)开始,表明YMAL文件的开始。
2、在同一行中,#之后的内容表示注释,类似于shell,python和ruby。
3、YMAL中的列表元素以”-”开头然后紧跟着一个空格,后面为元素内容。
4、同一个列表中的元素应该保持相同的缩进。否则会被当做错误处理。
5、play中hosts,variables,roles,tasks等对象的表示方法都是键值中间以\”:“分隔表示,”:\”后面还要增加一个空格。
下面是一个举例:
—
#安装与运行mysql服务
– hosts: node1
remote_user: root
tasks:
– name: install mysql-server package
yum: name=mysql-server state=present
– name: starting mysqld service
service: name=mysql state=started
我们的文件名称应该以.yml结尾,像我们上面的例子就是mysql.yml。其中,有三个部分组成:
host部分:使用 hosts 指示使用哪个主机或主机组来运行下面的 tasks ,每个 playbook 都必须指定 hosts ,hosts也可以使用通配符格式。主机或主机组在 inventory 清单中指定,可以使用系统默认的/etc/ansible/hosts,也可以自己编辑,在运行的时候加上-i选项,指定清单的位置即可。在运行清单文件的时候,–list-hosts选项会显示那些主机将会参与执行 task 的过程中。 remote_user:指定远端主机中的哪个用户来登录远端系统,在远端系统执行 task 的用户,可以任意指定,也可以使用 sudo,但是用户必须要有执行相应 task 的权限。 tasks:指定远端主机将要执行的一系列动作。tasks 的核心为 ansible 的模块,前面已经提到模块的用法。tasks 包含 name 和要执行的模块,name 是可选的,只是为了便于用户阅读,不过还是建议加上去,模块是必须的,同时也要给予模块相应的参数。
使用ansible-playbook运行playbook文件,得到如下输出信息,输出内容为JSON格式。并且由不同颜色组成,便于识别。一般而言 | 绿色代表执行成功,系统保持原样 | 黄色代表系统代表系统状态发生改变 | 红色代表执行失败,显示错误输出 执行有三个步骤:1、收集facts 2、执行tasks 3、报告结果
2、核心元素
Playbook的核心元素:
Hosts:主机组; Tasks:任务列表; Variables:变量,设置方式有四种; Templates:包含了模板语法的文本文件; Handlers:由特定条件触发的任务;
3、基本组件
Playbooks配置文件的基础组件:
Hosts:运行指定任务的目标主机
remote_user:在远程主机上执行任务的用户;
sudo_user:
tasks:任务列表
模块,模块参数:
格式: (1) action: module arguments (2) module: arguments 注意:shell和command模块后面直接跟命令,而非key=value类的参数列表;
handlers:任务,在特定条件下触发;接收到其它任务的通知时被触发;
(1) 某任务的状态在运行后为changed时,可通过“notify”通知给相应的handlers;
(2) 任务可以通过“tags“打标签,而后可在ansible-playbook命令上使用-t指定进行调用;
举例
① 定义playbook
[root@server ~]# cd /etc/ansible
[root@server ansible]# vim nginx.yml
—
– hosts: web
remote_user: root
tasks:
– name: install nginx
yum: name=nginx state=present
– name: copy nginx.conf
copy: src=/tmp/nginx.conf dest=/etc/nginx/nginx.conf backup=yes
notify: reload #当nginx.conf发生改变时,通知给相应的handlers
tags: reloadnginx #打标签
– name: start nginx service
service: name=nginx state=started
tags: startnginx #打标签
handlers: #注意,前面没有-,是两个空格
– name: reload
service: name=nginx state=restarted #为了在进程中能看出来
运行前三部曲
检查错误
ansible-playbook nginx.yml –syntax-check
列出所有任务
ansible-playbook nginx.yml –list-task
列出在那些机器执行
ansible-playbook nginx.yml –list-hosts
运行
ansible-playbook nginx.yml
② 测试运行结果 写完了以后,我们就可以运行了:
[root@server ansible]# ansible-playbook nginx.yml
现在我们可以看看两台机器的端口是否开启:
[root@server ansible]# ansible web -m shell -a \’ss -nutlp |grep nginx\’
192.168.37.122 | SUCCESS | rc=0 >>
tcp LISTEN 0 128 *:80 *:* users:((\”nginx\”,pid=8304,fd=6),(\”nginx\”,pid=8303,fd=6))
192.168.37.133 | SUCCESS | rc=0 >>
tcp LISTEN 0 128 *:80 *:* users:((\”nginx\”,pid=9671,fd=6),(\”nginx\”,pid=9670,fd=6))
③ 测试标签 我们在里面已经打上了一个标签,所以可以直接引用标签。但是我们需要先把服务关闭,再来运行剧本并引用标签:
[root@server ansible]# ansible web -m shell -a \’systemctl stop nginx\’
[root@server ansible]# ansible-playbook nginx.yml -t startnginx
④ 测试notify 我们还做了一个notify,来测试一下: 首先,它的触发条件是配置文件被改变,所以我们去把配置文件中的端口改一下:
[root@server ansible]# vim /tmp/nginx.conf
listen 8080;
然后我们重新加载一下这个剧本: 发现我们执行的就是reload段以及我们定义的notify部分。 我们来看一看我们的端口号:
[root@server ansible]# ansible web -m shell -a \’ss -ntlp | grep nginx\’
192.168.37.122 | SUCCESS | rc=0 >>
LISTEN 0 128 *:8080 *:* users:((\”nginx\”,pid=2097,fd=6),(\”nginx\”,pid=2096,fd=6))
192.168.37.133 | SUCCESS | rc=0 >>
LISTEN 0 128 *:8080 *:* users:((\”nginx\”,pid=3061,fd=6),(\”nginx\”,pid=3060,fd=6))
可以看出,我们的nginx端口已经变成了8080。
4、variables 部分
上文中,我们说到了variables是变量,有四种定义方 法,现在我们就来说说这四种定义方法:
① facts :可直接调用
上一篇中,我们有说到setup这个模块,这个模块就是通过调用facts组件来实现的。我们这里的variables也可以直接调用facts组件。 具体的facters我们可以使用setup模块来获取,然后直接放入我们的剧本中调用即可。
ansible_all_ipv4_addresses:仅显示ipv4的信息 —> [u\’192.168.95.143\’]
ansible_eth0[\’ipv4\’][\’address\’]:仅显示ipv4的信息 —> eth0 的ip地址
ansible_devices:仅显示磁盘设备信息
ansible_distribution:显示是什么系统,例:centos,suse等
ansible_distribution_version:仅显示系统版本
ansible_machine:显示系统类型,例:32位,还是64位
ansible_eth0:仅显示eth0的信息
ansible_hostname:仅显示主机名
ansible_kernel:仅显示内核版本
ansible_lvm:显示lvm相关信息
ansible_memtotal_mb:显示系统总内存
ansible_memfree_mb:显示可用系统内存
ansible_memory_mb:详细显示内存情况
ansible_swaptotal_mb:显示总的swap内存
ansible_swapfree_mb:显示swap内存的可用内存
ansible_mounts:显示系统磁盘挂载情况
ansible_processor:显示cpu个数(具体显示每个cpu的型号)
ansible_processor_vcpus:显示cpu个数(只显示总的个数)
ansible_python_version:显示python版本
例如:批量修改主机 host 文件
—
– hosts: web
vars:
IP: \”{{ ansible_eth0[\’ipv4\’][\’address\’] }}\”
tasks:
– name: 将原有的hosts文件备份
shell: mv /etc/hosts /etc/hosts_bak
– name: 将ansible端的hosts复制到各自机器上
copy: src=/root/hosts dest=/etc/ owner=root group=root mode=0644
– name: 在新的hosts文件后面追加各自机器内网ip和hostname
lineinfile: dest=/etc/hosts line=\”{{ IP }} {{ ansible_hostname }} \”
② 用户自定义变量
我们也可以直接使用用户自定义变量,想要自定义变量有以下两种方式:
通过命令行传入
ansible-playbook命令的命令行中的-e VARS, –extra-vars=VARS,这样就可以直接把自定义的变量传入。
在playbook中定义变量
我们也可以直接在playbook中定义我们的变量:
vars:
- var1: value1
- var2: value2
举例
① 定义剧本 我们就使用全局替换把我们刚刚编辑的文件修改一下:
[root@server ansible]# vim nginx.yml
这样一来,我们的剧本就定义完成了。 ② 拷贝配置文件 我们想要在被监管的机器上安装什么服务的话,就直接在我们的server端上把该服务的配置文件拷贝到我们的/tmp/目录下。这样我们的剧本才能正常运行。 我们就以keepalived服务为例:
[root@server ansible]# cp /etc/keepalived/keepalived.conf /tmp/keepalived.conf
③ 运行剧本,变量由命令行传入
[root@server ansible]# ansible-playbook nginx.yml -e rpmname=keepalived
④ 修改剧本,直接定义变量 同样的,我们可以直接在剧本中把变量定义好,这样就不需要在通过命令行传入了。以后想要安装不同的服务,直接在剧本里把变量修改一下即可。
[root@server ansible]# vim nginx.yml
⑤ 运行定义过变量的剧本 我们刚刚已经把变量定义在剧本里面了。现在我们来运行一下试试看:
[root@server ansible]# ansible-playbook nginx.yml
发现这样也是可以的~
③ 通过roles传递变量
具体的,我们下文中说到 roles 的时候再详细说明。
④ Host Inventory
我们也可以直接在主机清单中定义。 定义的方法如下:
向不同的主机传递不同的变量:
IP/HOSTNAME varaiable=value var2=value2
向组中的主机传递相同的变量:
[groupname:vars]
variable=value
Ansible Inventory 内置参数
使用内置变量把用户名密码写在Inventory中,也就是/etc/ansible/hosts文件里,缺点就是暴露了账号密码,不安全。如果有多个主机需要使用同样的变量,可以用组变量的形式,书写格式如下:
[web]
192.168.100.10
192.168.100.11
192.168.100.12
[web:vars] #给名为webservers的组定义一个变量,:vars是固定格式
ansible_ssh_port=22
ansible_ssh_user=\’root\’
ansible_ssh_pass=\’1234.com\’
5、模板 templates
模板是一个文本文件,嵌套有脚本(使用模板编程语言编写)。 Jinja2:Jinja2是python的一种模板语言,以Django的模板语言为原本。 模板支持:
字符串:使用单引号或双引号;
数字:整数,浮点数;
列表:[item1, item2, …]
元组:(item1, item2, …)
字典:{key1:value1, key2:value2, …}
布尔型:true/false
算术运算:
+, -, *, /, //, %, **
比较操作:
==, !=, >, >=, <, <=
逻辑运算:
and, or, not
通常来说,模板都是通过引用变量来运用的。
举例
① 定义模板 我们直接把之前定义的/tmp/nginx.conf改个名,然后编辑一下,就可以定义成我们的模板文件了:
[root@server ansible]# cd /tmp
[root@server tmp]# mv nginx.conf nginx.conf.j2
[root@server tmp]# vim nginx.conf.j2
worker_processes {{ ansible_processor_vcpus }};
listen {{ nginxport }};
② 修改剧本 我们现在需要去修改剧本来定义变量:
[root@server ansible]# vim nginx.yml
需要修改的部分如图所示。
copy模块 也需要修改为 template模块
③ 运行剧本 上面的准备工作完成后,我们就可以去运行剧本了:
[root@server ansible]# ansible-playbook nginx.yml -t reloadnginx
PLAY [web] *********************************************************************
TASK [setup] *******************************************************************
ok: [192.168.37.122]
ok: [192.168.37.133]
TASK [copy nginx.conf] *********************************************************
ok: [192.168.37.122]
ok: [192.168.37.133]
PLAY RECAP *********************************************************************
192.168.37.122 : ok=2 changed=0 unreachable=0 failed=0
192.168.37.133 : ok=2 changed=0 unreachable=0 failed=0
6、条件测试
when语句:在task中使用,jinja2的语法格式。 举例如下:
tasks:
– name: install conf file to centos7
template: src=files/nginx.conf.c7.j2
when: ansible_distribution_major_version == \”7\”
– name: install conf file to centos6
template: src=files/nginx.conf.c6.j2
when: ansible_distribution_major_version == \”6\”
循环:迭代,需要重复执行的任务; 对迭代项的引用,固定变量名为\”item\”,而后,要在task中使用with_items给定要迭代的元素列表; 举例如下:
tasks:
– name: unstall web packages
yum: name={{ item }} state=absent
with_items:
– httpd
– php
– php-mysql
跳过错误:
tasks:
– name: unstall web packages
yum: name=httpd state=absent
ignore_errors: yes
7、字典
ansible playbook 还支持字典功能。举例如下:
– name: install some packages
yum: name={{ item }} state=present
with_items:
– nginx
– memcached
– php-fpm
– name: add some groups
group: name={{ item }} state=present
with_items:
– group11
– group12
– group13
– name: add some users
user: name={{ item.name }} group={{ item.group }} state=present
with_items:
– { name: \’user11\’, group: \’group11\’ }
– { name: \’user12\’, group: \’group12\’ }
– { name: \’user13\’, group: \’group13\’ }
8、角色订制:roles
① 简介
对于以上所有的方式有个弊端就是无法实现复用假设在同时部署Web、db、ha 时或不同服务器组合不同的应用就需要写多个yml文件。很难实现灵活的调用。 roles 用于层次性、结构化地组织playbook。roles 能够根据层次型结构自动装载变量文件、tasks以及handlers等。要使用roles只需要在playbook中使用include指令即可。简单来讲,roles就是通过分别将变量(vars)、文件(file)、任务(tasks)、模块(modules)及处理器(handlers)放置于单独的目录中,并可以便捷地include它们的一种机制。角色一般用于基于主机构建服务的场景中,但也可以是用于构建守护进程等场景中。
② 角色集合
角色集合:roles/ mysql/ httpd/ nginx/ files/:存储由copy或script等模块调用的文件; tasks/:此目录中至少应该有一个名为main.yml的文件,用于定义各task;其它的文件需要由main.yml进行“包含”调用; handlers/:此目录中至少应该有一个名为main.yml的文件,用于定义各handler;其它的文件需要由main.yml进行“包含”调用; vars/:此目录中至少应该有一个名为main.yml的文件,用于定义各variable;其它的文件需要由main.yml进行“包含”调用; templates/:存储由template模块调用的模板文本; meta/:此目录中至少应该有一个名为main.yml的文件,定义当前角色的特殊设定及其依赖关系;其它的文件需要由main.yml进行“包含”调用; default/:此目录中至少应该有一个名为main.yml的文件,用于设定默认变量;
③ 角色定制实例
1. 在roles目录下生成对应的目录结构
[root@server ansible]# cd roles/
[root@server roles]# ls
[root@server roles]# mkdir -pv ./{nginx,mysql,httpd}/{files,templates,vars,tasks,handlers,meta,default}
[root@server roles]# tree
.
├── httpd
│ ├── default
│ ├── files
│ ├── handlers
│ ├── meta
│ ├── tasks
│ ├── templates
│ └── vars
├── mysql
│ ├── default
│ ├── files
│ ├── handlers
│ ├── meta
│ ├── tasks
│ ├── templates
│ └── vars
└── nginx
├── default
├── files
├── handlers
├── meta
├── tasks
├── templates
└── vars
24 directories, 0 files
2. 定义配置文件 我们需要修改的配置文件为/tasks/main.yml,下面,我们就来修改一下:
[root@server roles]# vim nginx/tasks/main.yml
– name: cp rpm for nginx
copy: src=nginx-1.10.2-1.el7.ngx.x86_64.rpm dest=/tmp/nginx-1.10.2-1.el7.ngx.x86_64.rpm
– name: install
yum: name=/tmp/nginx-1.10.2-1.el7.ngx.x86_64.rpm state=latest
– name: conf
template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf
tags: nginxconf
notify: new conf to reload
– name: start service
service: name=nginx state=started enabled=true
3. 放置我们所需要的文件到指定目录 因为我们定义的角色已经有了新的组成方式,所以我们需要把文件都放到指定的位置,这样,才能让配置文件找到这些并进行加载。 rpm包放在files目录下,模板放在templates目录下:
[root@server nginx]# cp /tmp/nginx-1.10.2-1.el7.ngx.x86_64.rpm ./files/
[root@server nginx]# cp /tmp/nginx.conf.j2 ./templates/
[root@server nginx]# tree
.
├── default
├── files
│ └── nginx-1.10.2-1.el7.ngx.x86_64.rpm
├── handlers
├── meta
├── tasks
│ └── main.yml
├── templates
│ └── nginx.conf.j2
└── vars
7 directories, 3 files
4. 修改变量文件 我们在模板中定义的变量,也要去配置文件中加上:
[root@server nginx]# vim vars/main.yml
nginxprot: 9999
5. 定义handlers文件 我们在配置文件中定义了notify,所以我么也需要定义handlers,我们来修改配置文件:
[root@server nginx]# vim handlers/main.yml
– name: new conf to reload
service: name=nginx state=restarted
6. 定义剧本文件 接下来,我们就来定义剧本文件,由于大部分设置我们都单独配置在了roles里面,所以,接下来剧本就只需要写一点点内容即可:
[root@server ansible]# vim roles/roles.yml
– hosts: web
remote_user: root
roles:
– nginx
完成后的目录结构
# tree ./
./
├── httpd
│ ├── default
│ ├── files
│ ├── handlers
│ ├── meta
│ ├── tasks
│ ├── templates
│ └── vars
├── mysql
│ ├── default
│ ├── files
│ ├── handlers
│ ├── meta
│ ├── tasks
│ ├── templates
│ └── vars
├── nginx
│ ├── default
│ ├── files
│ │ └── nginx-1.10.2-1.el7.ngx.x86_64.rpm
│ ├── handlers
│ │ └── main.yml
│ ├── meta
│ ├── tasks
│ │ └── main.yml
│ ├── templates
│ │ └── nginx.conf.j2
│ └── vars
│ └── main.yml
└── roles.yml
7. 启动服务 剧本定义完成以后,我们就可以来启动服务了:
[root@server ansible]# ansible-playbook roles.yml
PLAY [web] *********************************************************************
TASK [setup] *******************************************************************
ok: [192.168.37.122]
ok: [192.168.37.133]
TASK [nginx : cp] **************************************************************
ok: [192.168.37.122]
ok: [192.168.37.133]
TASK [nginx : install] *********************************************************
changed: [192.168.37.122]
changed: [192.168.37.133]
TASK [nginx : conf] ************************************************************
changed: [192.168.37.122]
changed: [192.168.37.133]
TASK [nginx : start service] ***************************************************
changed: [192.168.37.122]
changed: [192.168.37.133]
RUNNING HANDLER [nginx : new conf to reload] ***********************************
changed: [192.168.37.122]
changed: [192.168.37.133]
PLAY RECAP *********************************************************************
192.168.37.122 : ok=6 changed=4 unreachable=0 failed=0
192.168.37.133 : ok=6 changed=4 unreachable=0 failed=0
启动过后照例查看端口号:
[root@server ansible]# ansible web -m shell -a \”ss -ntulp |grep 9999\”
192.168.37.122 | SUCCESS | rc=0 >>
tcp LISTEN 0 128 *:9999 *:* users:((\”nginx\”,pid=7831,fd=6),(\”nginx\”,pid=7830,fd=6),(\”nginx\”,pid=7829,fd=6))
192.168.37.133 | SUCCESS | rc=0 >>
tcp LISTEN 0 128 *:9999 *:* users:((\”nginx\”,pid=9654,fd=6),(\”nginx\”,pid=9653,fd=6),(\”nginx\”,pid=9652,fd=6))
可以看出我们的剧本已经执行成功。
九、Ansible使用jinja2管理配置文件以及jinja2语法简介
1、Jinja2介绍
Jinja2是基于python的模板引擎,功能比较类似于PHP的smarty,J2ee的Freemarker和velocity。它能完全支持unicode,并具有集成的沙箱执行环境,应用广泛。jinja2使用BSD授权
Jinja2的语法是由variables(变量)和statement(语句)组成,如下;
1、variables:可以输出数据
my_variables
{{ some_dudes_name | capitalize }}
2、statements: 可以用来创建条件和循环等
if语句:
{% if my_conditional %}
…
{% endif %}
for 语句:
{% for item in all_items %}
`item`
……
{% endfor %}
从上面第二个variables的例子中可以看出,jinja2支持使用带过滤器的Unix型管道操作符,有很多的内置过滤器可供使用。我们可以仅仅用一堆简单if和for就可以建立几乎任何的常规配置文件,不过如果你有意更进一步,jinja2 documentation (http://jinja.pocoo.org/docs/dev/)包含了很多有趣的东西可供了解。我们可以看到ansible允许在模板中使用诸如绘制时间此类的一些额外的模板变量
第一个例子:引用变量
# tree
.
├── site.yml
├── templates
│ └── order.j2
└── vars
└── main.yml
2 directories, 3 files
总调度yml文件:
# cat site.yml
—
– hosts: 192.168.19.154
user: root
vars:
– PROJECT: \”JAVA\”
SWITCH: \”ON\”
DBPORT: \”8080\”
tasks:
– name: create{{ PROJECT }}directory
file: path=/data/{{ PROJECT }} state=directory
– name: template transfor java
template: src=order.j2 dest=/data/{{ PROJECT }}/order.conf
注意:这里 – role: template 和 – template 是一样的!
其他yml文件,如下:
# cat templates/order.j2
project: {{ PROJECT }}
switch: {{ SWITCH }}
dbport: {{ DBPORT }}
测试:
# ansible-playbook templates.yml –syntax-check
playbook: templates.yml
执行:
PLAY [192.168.19.154] **********************************************************
TASK [Gathering Facts] *********************************************************
ok: [192.168.19.154]
TASK [createJAVAdirectory] *****************************************************
changed: [192.168.19.154]
TASK [template transfor java] **************************************************
changed: [192.168.19.154]
PLAY RECAP *********************************************************************
192.168.19.154 : ok=3 changed=2 unreachable=0 failed=0
#cat /data/JAVA/order.conf
project: JAVA
switch: ON
dbport: 8080
第二个例子:for 语句
为远程主机生成服务器列表,加入该列表从192.168.13.201 web01.test.com 到192.168.13.211 web11.test.com 结束,如果手动添加就很不科学了,这里需要使用jinja2语法的for循环通过模板批量生成对应的配置文件,如下:
ansible目录结构:
#cd /etc/ansible/roles/test_hosts
.
├── meta
│ └── main.yml
├── tasks
│ ├── file1.yml
│ └── main.yml
├── templates
│ └── test1.j2
└── vars
└── main.yml
各个目录下yml文件内容:
# cat tasks/file1.yml
– name: ansible jinja2 template for hosts config
template: src=test1.j2 dest=/etc/httpd/conf/httpd.conf.test
# cat tasks/main.yml
– include: file1.yml
# cat templates/test1.j2
{% for id in range(201,212) %}
192.168.13.{{ id }} web{{ \”%02d\” |format(id-200) }}.test.com
{% endfor %}
解释:
{{ id }} 提取for循环中对应的变量id值
\”%02d\” 调用的是python内置的字符串格式化输出(%d格式化整数)因为是01,02这种格式,所以是保留2位,故用02
然后将结果通过管道符 “|” 传递给format 函数做二次处理。
执行结果:
#cat httpd.conf.test
192.168.13.201 web01.test.com
192.168.13.202 web02.test.com
192.168.13.203 web03.test.com
192.168.13.204 web04.test.com
192.168.13.205 web05.test.com
192.168.13.206 web06.test.com
192.168.13.207 web07.test.com
192.168.13.208 web08.test.com
192.168.13.209 web09.test.com
192.168.13.210 web10.test.com
192.168.13.211 web11.test.com
第三个例子:if语句
说明:如果定义端口号,就绑定定义的端口号,如果不定义端口号,就绑定默认端口号
ansible目录结果
#cd /etc/ansible/roles/mysql_cnf
#tree
.
├── meta
│ └── main.yml
├── tasks
│ └── main.yml
├── templates
│ └── test3.j2
└── vars
主要的yml文件是templates目录下面的test3.j2
# cat templates/test3.j2
{% if PORT %}
bind_address=10.0.90.27:{{ PORT }}
{% else %}
bind_address=10.0.90.27:3306
{% endif %}
playbook主文件
# cat jinj2_test.yml
—
– hosts: 10.0.90.27
user: root
gather_facts: false
vars:
PORT: 3136
tasks:
– name: copy file to client
template: src=/etc/ansible/roles/mysql_cnf/templates/test3.j2 dest=/root/my.cnf
执行:
# ansible-playbook jinj2_test.yml
PLAY [10.0.90.27] **************************************************************
TASK [copy file to client] *****************************************************
changed: [10.0.90.27]
PLAY RECAP *********************************************************************
10.0.90.27 : ok=1 changed=1 unreachable=0 failed=0
查看
# cat my.cnf
bind_address=10.0.90.27:3136
如果将vars变量去掉,执行结果:
# cat jinj2_test.yml
—
– hosts: 10.0.90.27
user: root
gather_facts: false
vars:
PORT: false
tasks:
– name: copy file to client
template: src=/etc/ansible/roles/mysql_cnf/templates/test3.j2 dest=/root/my.cnf
查看:
# cat my.cnf
bind_address=10.0.90.27:3306
3、Jinja default()设定
精通程序编码的朋友皆知,default()默认值的设定有助于程序的健壮性和简洁性。所幸Jinja也支持该功能,上面的例子中生成Mysql配置文件中的端口定义,如果指定则PORT=3136,否则PORT=3306,我们将该案例改造为使用default()试试
编辑/etc/ansible/roles/mysql_cnf/templates/test3.j2内容如下,这种方法更简介。
bind_address=10.0.90.27:{{ PORT | default(3306) }}
2、ansible使用jinja2生成apache多主机配置
1、创建目录,创建好之后如下:
#cd /etc/ansible/roles/apache_conf
# tree ./
./
├── meta
│ └── main.yml
├── tasks
│ ├── file.yml
│ └── main.yml
├── templates
│ └── apache.config.j2
└── vars
└── main.yml
4 directories, 5 files
2、创建tasks调度文件,如下:
#cat file.yml
– name: ansible jinja2 template for apache config
template: src=apache.config.j2 dest=/etc/httpd/conf/httpd.conf.template
#cat main.yml
– include: file.yml
3、创建apache的jinja2模板文件,如下:
#cat apache.config.j2
NameVirtualHost *:80
{% for vhost in apache_vhost %}
<VirtualHost *:80>
ServerName {{ vhost.servername }}
DocumentRoot {{ vhost.documentroot }}
{% if vhost.serveradmin is defined %}
ServerAdmin {{ vhost.serveradmin }}
{% endif %}
<Directory \”{{ vhost.documentroot }}\”>
AllowOverride All
Options -Indexes FollowSymLinks
Order allow,deny
Allow from all
</Directory>
</VirtualHost>
{% endfor %}
4、创建变量,如下:
#cat vars/main.yml
apache_vhost:
– {servername: \”apache.test1.com\”, documentroot: \”/data/test1/\”}
– {servername: \”apache.test2.com\”, documentroot: \”/data/test2/\”}
5、创建总调度yml文件,如下:
#cat /etc/ansible/apache_test.yml
—
– hosts: 10.0.90.27
user: root
gather_facts: no
roles:
– { role: apache_conf }
6、测试:
#ansible-playbook apache_test.yml –syntax-check
playbook: apache_test.yml
7、执行测试
#ansible-playbook apache_test.yml
PLAY [10.0.90.27] **************************************************************
TASK [apache_conf : include] ***************************************************
included: /etc/ansible/roles/apache_conf/tasks/file.yml for 10.0.90.27
TASK [apache_conf : ansible jinja2 template for apache config] *****************
changed: [10.0.90.27]
PLAY RECAP *********************************************************************
10.0.90.27 : ok=2 changed=1 unreachable=0 failed=0
8、到客户端查看
#cat httpd.conf.template
NameVirtualHost *:80
<VirtualHost *:80>
ServerName apache.test1.com
DocumentRoot /data/test1/
<Directory \”/data/test1/\”>
AllowOverride All
Options -Indexes FollowSymLinks
Order allow,deny
Allow from all
</Directory>
</VirtualHost>
<VirtualHost *:80>
ServerName apache.test2.com
DocumentRoot /data/test2/
<Directory \”/data/test2/\”>
AllowOverride All
Options -Indexes FollowSymLinks
Order allow,deny
Allow from all
</Directory>
</VirtualHost>
3、ansible使用jiaja2生成nginx一个模板多种不同配置
说明:为2台Nginx Proxy,1台Nginx Web通过一套模板生成对应的配置
1、ansible目录结构:
# cd roles/nginx_conf/
#tree
.
├── files
├── meta
│ └── main.yml
├── tasks
│ ├── file.yml
│ └── main.yml
├── templates
│ └── nginx.conf.j2
└── vars
└── main.yml
2、tasks目录下文件内容:
#cat tasks/file.yml
– name: nginx.j2 template transfer example
template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf.template
#cat tasks/main.yml
– include: file.yml
3、nginx模板文件
#cat templates/nginx.conf.j2
{% if nginx_use_proxy %}
{% for proxy in nginx_proxies %}
upstream {{ proxy.name }}
#server 127.0.0.1:{{ proxy.port }};
server {{ ansible_eth0.ipv4.address }}:{{ proxy.port }};
}
{% endfor %}
{% endif%}
server {
listen 80;
servername {{ nginx_server_name }};
access_log off;
error_log /etc/nginx/nginx_error.log;
rewrite ^ https://$server_name$request_uri? permanent;
}
server {
listen 443 ssl;
server_name {{ nginx_server_name }};
ssl_certificate /etc/nginx/ssl/{{ nginx_ssl_cert_name }};
ssl_certificate_key /etc/nginx/ssl/{{ nginx_ssl_cert_key }};
root {{ nginx_web_root }};
index index.html index.html;
{% if nginx_use_auth %}
auth_basic \”Restricted\”;
auth_basic_user_file /etc/nginx/{{ project_name }}.htpasswd;
{% endif %}
{% if nginx_use_proxy %}
{% for proxy in nginx_proxies %}
location {{ proxy.location }} {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Proto http;
proxy_set_header X-Url-Scheme $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-NginX-Proxy true;
proxy_redirect off;
proxy_pass http://{{ proxy.name }};
break;
}
{% endfor %}
{% endif %}
{% if nginx_server_static %}
location / {
try_files $url $url/ =404;
}
{% endif %}
}
4、ansible变量文件
cat vars/main.yml
nginx_server_name: www.testnginx.com
nginx_web_root: /data/html/
nginx_proxies:
– name: suspicious
location: /
port: 1234
– name: suspicious-api
location: /api
port: 4567
5、ansible主playbook文件
#cat nginx_test.yml
##The first roles
– name: Nginx Proxy Server\’s Config Dynamic Create
hosts: \”10.0.90.25:10.0.90.26\”
remote_user: root
vars:
nginx_use_proxy: true
nginx_ssl_cert_name: ifa.crt
nginx_ssl_cert_key: ifa.key
nginx_use_auth: true
project_name: suspicious
nginx_server_static: true
gather_facts: true
roles:
– role: nginx_conf
##The second roles
– name: Nginx WebServer\’s Config Dynamic Create
hosts: 10.0.90.27
remote_user: root
vars:
nginx_use_proxy: false
nginx_ssl_cert_name: ifa.crt
nginx_ssl_cert_key: ifa.crt
nginx_use_auth: false
project_name: suspicious
nginx_server_static: false
gather_facts: false
roles:
– role: nginx_conf
6、测试并执行:
#ansible-playbook nginx_test.yml –syntax-check
playbook: nginx_test.yml
执行:
# ansible-playbook nginx_test.yml
PLAY [Nginx Proxy Server\’s Config Dynamic Create] ******************************
TASK [setup] *******************************************************************
ok: [10.0.90.25]
ok: [10.0.90.26]
TASK [nginx_conf : include] ****************************************************
included: /etc/ansible/roles/nginx_conf/tasks/file.yml for 10.0.90.25, 10.0.90.26
TASK [nginx_conf : nginx.j2 template transfer example] *************************
changed: [10.0.90.26]
changed: [10.0.90.25]
PLAY [Nginx WebServer\’s Config Dynamic Create] *********************************
TASK [nginx_conf : include] ****************************************************
included: /etc/ansible/roles/nginx_conf/tasks/file.yml for 10.0.90.27
TASK [nginx_conf : nginx.j2 template transfer example] *************************
changed: [10.0.90.27]
PLAY RECAP *********************************************************************
10.0.90.25 : ok=3 changed=1 unreachable=0 failed=0
10.0.90.26 : ok=3 changed=1 unreachable=0 failed=0
10.0.90.27 : ok=2 changed=1 unreachable=0 failed=0
7、查看检测执行结果
到Nginx Proxy 服务器查看配置文件
#cat nginx.conf.template
upstream suspicious
#server 127.0.0.1:1234;
server 10.0.90.26:1234;
}
upstream suspicious-api
#server 127.0.0.1:4567;
server 10.0.90.26:4567;
}
server {
listen 80;
servername www.testnginx.com;
access_log off;
error_log /etc/nginx/nginx_error.log;
rewrite ^ https://$server_name$request_uri? permanent;
}
server {
listen 443 ssl;
server_name www.testnginx.com;
ssl_certificate /etc/nginx/ssl/ifa.crt;
ssl_certificate_key /etc/nginx/ssl/ifa.key;
root /data/html/;
index index.html index.html;
auth_basic \”Restricted\”;
auth_basic_user_file /etc/nginx/suspicious.htpasswd;
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Proto http;
proxy_set_header X-Url-Scheme $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-NginX-Proxy true;
proxy_redirect off;
proxy_pass http://suspicious;
break;
}
location /api {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Proto http;
proxy_set_header X-Url-Scheme $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-NginX-Proxy true;
proxy_redirect off;
proxy_pass http://suspicious-api;
break;
}
location / {
try_files $url $url/ =404;
}
}
到Nginx Web 服务器上查看配置文件
#cat nginx.conf.template
server {
listen 80;
servername www.testnginx.com;
access_log off;
error_log /etc/nginx/nginx_error.log;
rewrite ^ https://$server_name$request_uri? permanent;
}
server {
listen 443 ssl;
server_name www.testnginx.com;
ssl_certificate /etc/nginx/ssl/ifa.crt;
ssl_certificate_key /etc/nginx/ssl/ifa.crt;
root /data/html/;
index index.html index.html;
}
到这里,就结束了。用同样的模板通过简单的if和变量设置就可以完成不同类型主机的Nginx conf配置,所以一方面在了解Ansible强大的模板功能的同时,也需要看到模板质量的重要性。
#以上关于Ansible 实战详解的相关内容来源网络仅供参考,相关信息请以官方公告为准!
原创文章,作者:CSDN,如若转载,请注明出处:https://www.sudun.com/ask/92718.html