自动化运维工具之ansible
Ansible简述
Ansible是一款自动化运维工具,基于Python开发,集合了众多运维工具(puppet、cfengine、chef、func、fabric)优点,实现了批量系统配置、批量程序部署、批量运行命令等功能。ansible是基于模块工作,本身没有批量部署的能力。真正具有批量部署的是ansible所运行的模块,ansible只是提供一种框架。主要包括:
(1)连接插件connection plugins:负责和被监控端实现通信;
(2)host inventory : 指定操作的主机,是一个配置文件里面定义监控的主机;
(3)各种模块核心模块、command模块、自定义模块;
(4)借助于插件完成记录日志邮件等功能;
(5)playbook:剧本执行多个任务时,非必须可以让节点一次运行多个任务
Ansible的特性
- 模块化:调用特定的模块,完成特定任务
- 有Paramiko , PyYAML , Jinja2 (模板语言)三个关键模块
- 支持自定义模块
- 基于Python语言实现
- 部署简单,基于python和SSH(默认已安装) , agentless
- 安全,基于OpenSSH
- 支持playbook编排任务
- 幂等性:一个任务执行1遍和执行n遍效果一 样,不因重复执行带来意外情况
- 无需代理不依赖PKI (无需ssI )
- 可使用任何编程语言写模块
- YAML格式,编排任务,支持丰富的数据结构
- 较强大的多层解决方案
Ansible架构
Ansible:Ansible核心程序。
HostInventory:记录由Ansible管理的主机信息,包括端口、密码、ip等。
Playbooks:“剧本”YAML格式文件,多个任务定义在一个文件中,定义主机需要调用哪些模块来完成的功能。
Core Modules:核心模块,主要操作是通过调用核心模块来完成管理任务。
CustomModules:自定义模块,完成核心模块无法完成的功能,支持多种语言。
PLUGINS :模块功能的补充,如连接类型插件、循环插件、变量插件、过滤插
件等,该功能不常用
ConnectionPlugins:连接插件,Ansible和Host通信使用
利用ansible实现管理的方式
- Ad-Hoc即ansible命令, 主要用于临时命令使用场景
- Ansible-playbook主要用于长期规划好的,大型项目的场景,需要有前提的规划。
Ansible主要操作对象
- HOSTS主机
- NETWORKING网络设备
注意事项
- 执行ansible的主机-般称为主控端,中控, master或堡垒机
- 主控端Python版本需要2.6或以上
- 被控端Python版本小于2.4需要安装python-simplejson
- 被控端如开启SELinux需 要安装libselinux-python
- windows不能做为主控端
Ansible安装
rpm包安装
//获取EPEL源
[root@ansible ~]# cd /etc/yum.repos.d/
[root@ansible yum.repos.d]#mkdir bak && mv C* bak/
[root@ansible yum.repos.d]#wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo
--2020-05-20 21:45:57-- http://mirrors.aliyun.com/repo/epel-7.repo
正在解析主机 mirrors.aliyun.com (mirrors.aliyun.com)... 183.201.230.97, 183.201.230.100, 183.201.230.94, ...
正在连接 mirrors.aliyun.com (mirrors.aliyun.com)|183.201.230.97|:80... 已连接。
已发出 HTTP 请求,正在等待回应... 200 OK
长度:664 [application/octet-stream]
正在保存至: “/etc/yum.repos.d/epel.repo”
100%[============================================================================================>] 664 --.-K/s 用时 0s
2020-05-20 21:45:58 (269 MB/s) - 已保存 “/etc/yum.repos.d/epel.repo” [664/664])
[root@ansible ~]# yum install -y ansible
.............
编译安装
yum -y install python-jinja2 PyYAML python-paramiko python-babel python-crypto
tar xf ansible-1.5.4.tar.gz
cd ansible-1.5.4
python setup.py build
python setup.py install
mkdir /etc/ansible
cp -r examples/* /etc/ansible
Git方式
gitclone git://github.com/ansible/ansible.git --recursive
cd ./ansible
source ./hacking/env-setup
pip安装: pip是安装Python包的管理器,类似yum
yum install python-pip python-devel
yum install gcc glibc-devel zibl-devel rpm-bulid openssl-devel
pip install --upgrade pip
pip install ansible --upgrade
确认安装
[root@ansible ~]# ansible --version
ansible 2.9.9
config file = /etc/ansible/ansible.cfg
configured module search path = [u'/root/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
ansible python module location = /usr/lib/python2.7/site-packages/ansible
executable location = /usr/bin/ansible
python version = 2.7.5 (default, Aug 7 2019, 00:51:29) [GCC 4.8.5 20150623 (Red Hat 4.8.5-39)]
Ansible配置文件
配置文件
配置文件 | 作用 |
---|---|
/etc/ansible/ansible.cfg | 主配置文件,配置ansible工作特性 |
/etc/ansible/hosts | 主机清单 |
/etc/ansible/roles/ | 存放角色的目录 |
配置文件/etc/ansible/ansible.cfg
Ansible配置文件/etc/ansible/ansible.cfg (一般保持默认)
[defaults]
#inventory = /etc/ansible/hosts #主机列表配置文件
#library = /usr/share/my_ modules/ #库文件存放目录
#remote_tmp = $HOME/.ansible/tmp #临时py命令文件存放在远程主机目录
#local_tmp = $HOME/.ansible/tmp #本机的临时命令执行目录
#forks = 5 #默认并发数
#sudo_user = root #默认sudo用户
#ask_sudo_pass = True #每次执行ansible命令是否询问ssh密码
#ask_pass = True
#remote_port = 22
#host_key_checking = False #检查对应服务器的host_key ,建议取消注释
#log_path=/var/log/ansible.log #日志文件
定义主机清单即要被控制的主机
//vim /etc/ansible/hosts在最后添加
[webservers]
10.0.0.137
ansible配置公私钥
上面我们已经提到过 ansible 是基于 ssh 协议实现的,所以其配置公私钥的方式与 ssh 协议的方式相同,具体操作步骤如下:
//生成私钥
[root@ansible ~]# ssh-keygen -t rsa
Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa):
Created directory '/root/.ssh'.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /root/.ssh/id_rsa.
Your public key has been saved in /root/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:xHXbYgRfPN6lB+zQR7h45tlSjNT+HC+rixbAuFcLVxQ root@ansible
The key's randomart image is:
+---[RSA 2048]----+
| ooE=.+.|
| . . +o+O +|
| oo .=*.@.|
| ..+ o...O.*|
| .S= . + *+|
| . . o = =|
| . . + |
| .. . |
| .. oo |
+----[SHA256]-----+
//向主机分发私钥
[root@ansible ~]# ssh-copy-id 10.0.0.137
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/root/.ssh/id_rsa.pub"
The authenticity of host '10.0.0.137 (10.0.0.137)' can't be established.
ECDSA key fingerprint is SHA256:HdwXx3rYMt0dZtBvrXEM5D+imcJqc/1vfn6Cnj7SddQ.
ECDSA key fingerprint is MD5:dd:7e:55:12:9e:61:a7:04:35:ab:cf:21:77:d1:4b:f5.
Are you sure you want to continue connecting (yes/no)? yes //确认连接
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
root@10.0.0.137's password: //输入连接的密码
Number of key(s) added: 1
Now try logging into the machine, with: "ssh '10.0.0.137'"
and check to make sure that only the key(s) you wanted were added.
Ansible命令
ansible:主程序,临时命令执行工具
Usage:ansible <host-pattern>[-m module_name] [-a args]
-m:指定要使用的模块,不指定默认是command
-v:查看详细信息,同时支持-vvv,-vvvv可查看更详细信息
-a:模块的参数
--version:显示版本
--list-hosts:显示主机列表,可简写--list
-k, --ask-pass:提示输入ssh连接密码,默认Key验证
-K, --ask-become-pass:提示输入sudo时的口令
-C, --check:检查,并不执行
-T, --timeout=TIMEOUT:执行命令的超时时间,默认10s
-u, --user= REMOTE_USER:执行远程执行的用户
-b, --become:代替旧版的sudo切换
ansible的Host-pattern
匹配主机的列表
All:表示所有Inventory中的所有主机
ansible all -m ping
*:通配符
ansible "*" -m ping
ansible 192.168.1.* -m ping
ansible "*srvs" -m ping
或关系
ansible "websrvs:appsrvs" -m ping
ansible "192.168.1.10:192.168.1.20" -m ping
逻辑与
ansible "websrvs:&dbsrvs" -m ping
在websrvs组并且在dbsrvs组中的主机
逻辑非
ansible 'websrvs:!dbsrvs' -m ping
在websrvs组,但不在dbsrvs组中的主机
注意:此处为单引号
综合逻辑
ansible 'websrvs:dbsrvs:&appsrvs:!ftpsrvs' -m ping
正则表达式
ansible "websrvs:&dbsrvs" -m ping
ansible "~(web|db).*\.magedu\.com" -m ping
ansible命令执行过程
- 加载自己的配置文件默认/etc/ansible/ansible.cfg
- 加载自己对应的模块文件,如command
- 通过ansible将模块或命令生成对应的临时py文件,并将该文件传输至远程服务器的对应执行用户$HOME/.ansible/tmp/ansible-tmp-数字/XXX.PY文件
- 给文件+x执行
- 执行并返回结果
- 删除临时py文件, sleep 0退出
执行状态:
绿色:执行成功并且不需要做改变的操作
黄色:执行成功并且对目标主机做变更
红色:执行失败
ansible-doc:查看配置文档,模块功能查看工具
Usage: ansible-doc [options] [module...]
-a:显示所有模块的文档
-s:显示指定模块的playbook片段
-l:列出可用的模块
ansible-galaxy:下载和上传优秀代码或Roles模块的官网平台
usage: ansible-galaxy [-h] [--version] [-v] TYPE ...
list:列出所有已经安装的galaxy
install:安装galaxy,角色包
remove:删除galaxy角色包
ansible-playbook:定制自动化任务,编排剧本工具
usage: ansible-playbook [-h] [--version] [-v] [-k]
-t:运行指定的tags
-e:定义变量
-C:检查playbook语法
ansible-pull:远程执行命令的工具,拉取配置而非推送配置
ansible-vault:文件加密工具
encrypt 加密yml文件
decrypt 解密yml文件
view 查看yml加密文件
edit 编辑加密文件
rekey 重新修改加密口令
create 创建新文件
ansible-console基于Console界面与用户交互的执行工具
Ansible常用模块详解
主机连通性测试
我们使用ansible all -m ping命令来进行主机连通性测试,效果如下:
[root@ansible ansible]# ansible all -m ping
10.0.0.137 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"ping": "pong"
}
command 模块
这个模块可以直接在远程主机上执行命令,并将结果返回本主机。
[root@ansible ansible]# ansible all -m command -a 'ss -ntl'
10.0.0.137 | CHANGED | rc=0 >>
State Recv-Q Send-Q Local Address:Port Peer Address:Port
LISTEN 0 128 *:80 *:*
LISTEN 0 128 *:22 *:*
LISTEN 0 128 127.0.0.1:631 *:*
LISTEN 0 100 127.0.0.1:25 *:*
LISTEN 0 128 127.0.0.1:6010 *:*
LISTEN 0 128 :::22 :::*
LISTEN 0 128 ::1:631 :::*
LISTEN 0 100 ::1:25 :::*
LISTEN 0 128 ::1:6010 :::*
命令模块接受命令名称,后面是空格分隔的列表参数。给定的命令将在所有选定的节点上执行。它不会通过shell进行处理,比如$HOME和操作如"<",">","|",";","&" 工作(需要使用(shell)模块实现这些功能)。注意,该命令不支持| 管道命令。
该模块下常用的几个命令:
chdir # 在执行命令之前,先切换到该目录
executable # 切换shell来执行命令,需要使用命令的绝对路径
free_form # 要执行的Linux指令,一般使用Ansible的-a参数代替。
creates # 一个文件名,当这个文件存在,则该命令不执行,可以
用来做判断
removes # 一个文件名,这个文件不存在,则该命令不执行
shell 模块
shell模块可以在远程主机上调用shell解释器运行命令,支持shell的各种功能,例如管道等。
[root@ansible ansible]# ansible all -m shell -a 'cat /etc/passwd |grep "root"'
10.0.0.137 | CHANGED | rc=0 >>
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
只要是我们的shell命令,都可以通过这个模块在远程主机上运行。
copy 模块
这个模块用于将文件复制到远程主机,同时支持给定内容生成文件和修改权限等。
其相关选项如下:
src #被复制到远程主机的本地文件。可以是绝对路径,也可以是相对路径。如果路径是一个目录,则会递归复制,用法类似于"rsync"
content #用于替换"src",可以直接指定文件的值
dest #必选项,将源文件复制到的远程主机的绝对路径
backup #当文件内容发生改变后,在覆盖之前把源文件备份,备份文件包含时间信息
directory_mode #递归设定目录的权限,默认为系统默认权限
force #当目标主机包含该文件,但内容不同时,设为"yes",表示强制覆盖;设为"no",表示目标主机的目标位置不存在该文件才复制。默认为"yes"
others #所有的 file 模块中的选项可以在这里使用
举例:
1、复制文件
[root@ansible ~]# ansible all -m copy -a 'src=12345 dest=/root'
10.0.0.137 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"checksum": "e9b2de1c4e921b09ad8a8f17b0236a379fe07ee4",
"dest": "/root/12345",
"gid": 0,
"group": "root",
"md5sum": "4d701311bad1fe03103044e744812f21",
"mode": "0644",
"owner": "root",
"size": 10,
"src": "/root/.ansible/tmp/ansible-tmp-1590162116.92-13109-195905256318648/source",
"state": "file",
"uid": 0
}
2、给定内容生成文件,并制定权限
[root@ansible ~]# ansible all -m copy -a 'content="Hello world\n" dest=/data/name mode=666'
10.0.0.137 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"checksum": "33ab5639bfd8e7b95eb1d8d0b87781d4ffea4d5d",
"dest": "/data/name",
"gid": 0,
"group": "root",
"md5sum": "f0ef7081e1539ac00ef5b761b4fb01b3",
"mode": "0666",
"owner": "root",
"size": 12,
"src": "/root/.ansible/tmp/ansible-tmp-1590165401.66-13836-73245737274512/source",
"state": "file",
"uid": 0
}
我们现在可以去查看一下我们生成的文件及其权限:
[root@ansible ~]# ansible all -m shell -a 'ls -l /data/'
10.0.0.137 | CHANGED | rc=0 >>
总用量 8
-rw-r--r-- 1 root root 0 5月 20 15:24 file1
-rw-r--r-- 1 root root 0 5月 20 15:24 file2
-rw-r--r-- 1 root root 0 5月 20 15:24 file3
-rw-r--r-- 1 root root 81 5月 20 15:53 for1.conf
-rw-rw-rw- 1 root root 12 5月 20 00:36 name
可以看出我们的name文件已经生成,并且权限为666
3、关于覆盖
我们把文件的内容修改一下,然后选择覆盖备份:
[root@ansible ~]# ansible all -m copy -a 'content="Hello yanyujie\n" dest=/data/name mode=666 backup=yes'
10.0.0.137 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"backup_file": "/data/name.26212.2020-05-23@00:40:11~",
"changed": true,
"checksum": "56992803795a3a502f5448700e95385a9907f2eb",
"dest": "/data/name",
"gid": 0,
"group": "root",
"md5sum": "858e667f63d8b6040ab71574d80cdef4",
"mode": "0666",
"owner": "root",
"size": 15,
"src": "/root/.ansible/tmp/ansible-tmp-1590165610.35-13943-170133111730692/source",
"state": "file",
"uid": 0
}
现在我们可以去查看一下:
[root@ansible ~]# ansible all -m shell -a 'ls -l /data/'
10.0.0.137 | CHANGED | rc=0 >>
总用量 12
-rw-r--r-- 1 root root 0 5月 20 15:24 file1
-rw-r--r-- 1 root root 0 5月 20 15:24 file2
-rw-r--r-- 1 root root 0 5月 20 15:24 file3
-rw-r--r-- 1 root root 81 5月 20 15:53 for1.conf
-rw-rw-rw- 1 root root 15 5月 23 00:40 name
-rw-rw-rw- 1 root root 10 5月 23 00:39 name.26212.2020-05-23@00:40:11~
可以看出,我们的源文件已经被备份
script模块
该模块用于将本机的脚本在被管理端的机器上运行。
该模块直接指定脚本的路径即可,我们通过例子来看一看到底如何使用的:
首先,我们写一个脚本,并给其加上执行权限:
[root@ansible ~]# vim test.sh
#!/bin/bash
date >> /tmp/disk_total.log
df -lh >> /tmp/disk_total.log
[root@ansible ~]# chmod +x test.sh
然后,我们直接运行命令来实现在被管理端执行该脚本:
[root@ansible ~]# ansible all -m script -a 'test.sh'
10.0.0.137 | CHANGED => {
"changed": true,
"rc": 0,
"stderr": "Shared connection to 10.0.0.137 closed.\r\n",
"stderr_lines": [
"Shared connection to 10.0.0.137 closed."
],
"stdout": "",
"stdout_lines": []
}
照例查看一下文件内容:
[root@ansible ~]# ansible all -m shell -a 'cat /tmp/disk_total.log'
10.0.0.137 | CHANGED | rc=0 >>
2020年 05月 20日 星期三 00:32:43 CST
文件系统 容量 已用 可用 已用% 挂载点
/dev/mapper/centos-root 38G 3.4G 35G 9% /
devtmpfs 978M 0 978M 0% /dev
tmpfs 993M 144K 993M 1% /dev/shm
tmpfs 993M 8.9M 985M 1% /run
tmpfs 993M 0 993M 0% /sys/fs/cgroup
/dev/sr0 4.2G 4.2G 0 100% /var/www/html/centos/6
/dev/sda1 497M 140M 357M 29% /boot
tmpfs 199M 16K 199M 1% /run/user/0
/dev/sr1 4.1G 4.1G 0 100% /mnt
可以看出已经执行成功了。
file 模块
该模块主要用于设置文件的属性,比如创建文件、创建链接文件、删除文件等。
下面是一些常见的命令:
force #需要在两种情况下强制创建软链接,一种是源文件不存在,但之后会建立的情况下;另一种是目标软链接已存在,需要先取消之前的软链,然后创建新的软链,有两个选项:yes|no
group #定义文件/目录的属组。后面可以加上mode:定义文件/目录的权限
owner #定义文件/目录的属主。后面必须跟上path:定义文件/目录的路径
recurse #递归设置文件的属性,只对目录有效,后面跟上src:被链接的源文件路径,只应用于state=link的情况
dest #被链接到的路径,只应用于state=link的情况
state #状态,有以下选项:
directory:如果目录不存在,就创建目录
file:即使文件不存在,也不会被创建
link:创建软链接
hard:创建硬链接
touch:如果文件不存在,则会创建一个新的文件,如果文件或目录已存在,则更新其最后修改时间
absent:删除目录、文件或者取消链接文件
用法举例如下:
1、创建目录
[root@ansible ~]# ansible all -m file -a 'path=/data/app state=directory'
10.0.0.137 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"gid": 0,
"group": "root",
"mode": "0755",
"owner": "root",
"path": "/data/app",
"size": 6,
"state": "directory",
"uid": 0
}
我们可以查看一下:
[root@ansible ~]# ansible all -m shell -a 'ls -l /data'
10.0.0.137 | CHANGED | rc=0 >>
总用量 12
drwxr-xr-x 2 root root 6 5月 20 00:45 app
-rw-r--r-- 1 root root 0 5月 20 15:24 file1
-rw-r--r-- 1 root root 0 5月 20 15:24 file2
-rw-r--r-- 1 root root 0 5月 20 15:24 file3
-rw-r--r-- 1 root root 81 5月 20 15:53 for1.conf
-rw-rw-rw- 1 root root 15 5月 20 00:40 name
-rw-rw-rw- 1 root root 10 5月 20 00:39 name.26212.2020-05-23@00:40:11~
可以看出,我们的目录已经创建完成。
2、创建链接文件
[root@ansible ~]# ansible all -m file -a 'path=/data/file1.ln src=/data/file1 state=link'
10.0.0.137 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"dest": "/data/file1.ln",
"gid": 0,
"group": "root",
"mode": "0777",
"owner": "root",
"size": 11,
"src": "/data/file1",
"state": "link",
"uid": 0
}
我们可以去查看一下:
[root@ansible ~]# ansible all -m shell -a 'ls -l /data'
10.0.0.137 | CHANGED | rc=0 >>
总用量 12
drwxr-xr-x 2 root root 6 5月 23 00:45 app
-rw-r--r-- 1 root root 0 5月 20 15:24 file1
lrwxrwxrwx 1 root root 11 5月 23 00:51 file1.ln -> /data/file1
-rw-r--r-- 1 root root 0 5月 20 15:24 file2
-rw-r--r-- 1 root root 0 5月 20 15:24 file3
-rw-r--r-- 1 root root 81 5月 20 15:53 for1.conf
-rw-rw-rw- 1 root root 15 5月 23 00:40 name
-rw-rw-rw- 1 root root 10 5月 23 00:39 name.26212.2020-05-23@00:40:11~
我们的链接文件已经创建成功。
3、删除文件
[root@ansible ~]# ansible all -m file -a 'path=/data/file1 state=absent'
10.0.0.137 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"path": "/data/file1",
"state": "absent"
}
我们可以查看一下:
[root@ansible ~]# ansible all -m shell -a 'ls /data/file1'
10.0.0.137 | FAILED | rc=2 >>
ls: 无法访问/data/file1: 没有那个文件或目录non-zero return code
发现已经没有这个文件了。
fetch 模块
该模块用于从远程某主机获取(复制)文件到本地。
有两个选项:
dest:用来存放文件的目录
src:在远程拉取的文件,并且必须是一个file,不能是目录
具体举例如下:
[root@ansible ~]# ansible all -m fetch -a 'src=/data/name dest=/data'
10.0.0.137 | CHANGED => {
"changed": true,
"checksum": "56992803795a3a502f5448700e95385a9907f2eb",
"dest": "/data/10.0.0.137/data/name",
"md5sum": "858e667f63d8b6040ab71574d80cdef4",
"remote_checksum": "56992803795a3a502f5448700e95385a9907f2eb",
"remote_md5sum": null
}
我们可以在本机上查看一下文件是否复制成功。要注意,文件保存的路径是我们设置的接收目录下的被管制主机ip目录下:
[root@ansible ~]# cat /data/10.0.0.137/data/name
Hello yanyujie
hostname模块
管理主机名
[root@ansible ~]# ansible all -m hostname -a 'name=node1'
10.0.0.137 | CHANGED => {
"ansible_facts": {
"ansible_domain": "",
"ansible_fqdn": "node1",
"ansible_hostname": "node1",
"ansible_nodename": "node1",
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"name": "node1"
}
查看主机名验证是否修改成功
[root@ansible ~]# ansible all -m shell -a 'hostname'
10.0.0.137 | CHANGED | rc=0 >>
node1
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 # 以哪个用户的身份执行
disabled #true禁用一条计划任务
举例如下:
1、添加计划任务
[root@ansible ~]# ansible all -m cron -a "name=warning minute=* weekday=1,2,3,4,5 job='/usr/bin/wall warning'"
10.0.0.137 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"envs": [],
"jobs": [
"warning"
]
}
我们可以去查看一下:
[root@ansible ~]# ansible all -m shell -a 'crontab -l'
10.0.0.137 | CHANGED | rc=0 >>
#Ansible: warning
* * * * 1,2,3,4,5 /usr/bin/wall warning
可以看出,我们的计划任务已经设置成功了。
2、删除计划任务
如果我们的计划任务添加错误,想要删除的话,则执行以下操作:
首先我们查看一下现有的计划任务:
[root@ansible ~]# ansible all -m shell -a 'crontab -l'
10.0.0.137 | CHANGED | rc=0 >>
#Ansible: warning
* * * * 1,2,3,4,5 /usr/bin/wall warning
然后执行删除操作:
[root@ansible ~]# ansible all -m cron -a 'name=warning state=absent'
10.0.0.137 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"envs": [],
"jobs": []
}
删除完成后,我们再查看一下现有的计划任务确认一下:
root@ansible ~]# ansible all -m shell -a 'crontab -l'
10.0.0.137 | CHANGED | rc=0 >>
我们的删除操作已经成功。
yum模块
用于软件的安装
其选项如下
name= #所安装的包的名称
state= #present安装,latest安装最新的,absent卸载软件。
下面我们就来安装一个包试试看:
[root@ansible ~]# ansible all -m yum -a 'name=httpd'
10.0.0.137 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"msg": "",
"rc": 0,
"results": [
"httpd-2.4.6-40.el7.centos.x86_64 providing httpd is already installed"
]
}
安装成功。
service模块
该模块用于服务程序的管理。
其主要选项如下:
enabled #设置开机启动
name= #服务名称
state= #有四种状态,分别为:
started 启动服务
stopped 停止服务
restarted 重启服务
reloaded 重载配置
1、开启服务并设置自启动
[root@ansible ~]# ansible all -m service -a 'name=httpd enabled=yes state=started'
10.0.0.137 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"enabled": true,
"name": "httpd",
"state": "started",
................
}
}
我们可以去查看一下端口是否打开:
[root@ansible ~]# ansible all -m shell -a 'ss -ntl|grep 80'
10.0.0.137 | CHANGED | rc=0 >>
LISTEN 0 128 *:80 *:*
LISTEN 0 128 :::8088 :::*
关闭服务
[root@ansible ~]# ansible all -m service -a 'name=httpd state=stopped'
10.0.0.137 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"name": "httpd",
"state": "stopped",
...
}
}
一样的,我们来查看一下端口:
[root@ansible ~]# ansible all -m shell -a 'ss -ntl|grep 80'
10.0.0.137 | FAILED | rc=1 >>
non-zero return code
可以看出,我们已经没有80端口了,说明我们的httpd服务已经关闭了。
user模块
该模块主要是用来管理用户账号。
其选项如下:
comment # 用户的描述信息
createhome # 是否创建家目录
force # 在使用state=absent时, 行为与userdel –force一致.
group # 指定基本组
groups # 指定附加组,如果指定为(groups=)表示删除所有组
home # 指定用户家目录
move_home # 如果设置为home=时, 试图将用户主目录移动到指定的目录
name # 指定用户名
non_unique # 该选项允许改变非唯一的用户ID值
password # 指定用户密码
remove # 在使用state=absent时, 行为是与userdel –remove一致
shell # 指定默认shell
state # 设置帐号状态,不指定为创建,指定值为absent表示删除
system # 当创建一个用户,设置这个用户是系统用户。这个设置不能更改现有用户
uid # 指定用户的uid
1、添加一个用户并指定其 uid
[root@ansible ~]# ansible all -m user -a 'name=yyj uid=6666'
10.0.0.137 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"append": false,
"changed": true,
"comment": "yyj",
"group": 1000,
"home": "/home/yyj",
"move_home": false,
"name": "yyj",
"shell": "/bin/bash",
"state": "present",
"uid": 6666
}
添加完成,我们可以去查看一下:
[root@ansible ~]# ansible all -m shell -a 'cat /etc/passwd |grep yyj'
10.0.0.137 | CHANGED | rc=0 >>
yyj:x:6666:1000:yyj:/home/yyj:/bin/bash
2、删除用户
[root@ansible ~]# ansible all -m user -a 'name=yyj state=absent'
10.0.0.137 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"force": false,
"name": "yyj",
"remove": false,
"state": "absent"
}
一样的,删除之后,我们去看一下:
[root@ansible ~]# ansible all -m shell -a 'cat /etc/passwd |grep yyj'
10.0.0.137 | FAILED | rc=1 >>
non-zero return code
发现已经没有这个用户了。
group模块
该模块主要用于添加或删除组。
常用的选项如下:
gid= #设置组的GID号
name= #指定组的名称
state= #指定组的状态,默认为创建,设置值为absent为删除
system= #设置值为yes,表示创建为系统组
1、创建组
[root@ansible ~]# ansible all -m group -a 'name=yyj gid=6666'
10.0.0.137 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"gid": 6666,
"name": "yyj",
"state": "present",
"system": false
}
创建过后,我们来查看一下:
[root@ansible ~]# ansible all -m shell -a 'cat /etc/group | grep 6666'
10.0.0.137 | CHANGED | rc=0 >>
yyj:x:6666:
可以看出,我们的组已经创建成功了
2、删除组
[root@ansible ~]# ansible all -m group -a 'name=yyj state=absent'
10.0.0.137 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"name": "yyj",
"state": "absent"
}
验证一下
[root@ansible ~]# ansible all -m shell -a 'cat /etc/group | grep 6666'
10.0.0.137 | FAILED | rc=1 >>
non-zero return code
发现组已经被删除
setup模块
该模块主要用于收集信息,是通过调用facts组件来实现的。
facts组件是Ansible用于采集被管机器设备信息的一个功能,我们可以使用setup模块查机器的所有facts信息,可以使用filter来查看指定信息。整个facts信息被包装在一个JSON格式的数据结构中,ansible_facts是最上层的值。
facts就是变量,内建变量 。每个主机的各种信息,cpu颗数、内存大小等。会存在facts中的某个变量中。调用后返回很多对应主机的信息,在后面的操作中可以根据不同的信息来做不同的操作。如redhat系列用yum安装,而debian系列用apt来安装软件。
常用选项:
filter= #过滤想要的结果,支持通配符
--tree /path 和filter合起来用将过滤的信息保存在某个文件去
[root@ansible ~]# ansible all -m setup -a 'filter="*vcpus*"'
10.0.0.137 | SUCCESS => {
"ansible_facts": {
"ansible_processor_vcpus": 2,
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false
}
YAML语法简介
- 大小写敏感
- 使用缩进表示层级关系
- 缩进时不允许使用Tab键,只允许使用空格。
- 缩进的空格数目不重要,只要相同层级的元素左侧对齐即可
- #表示注释,从这个字符一直到行尾,都会被解析器忽略
- YAML 还有一个小的怪癖. 所有的 YAML 文件(无论和 Ansible 有没有关系)开始行都应该是
---
. 这是 YAML 格式的一部分, 表明一个文件的开始。 - 列表中的所有成员都开始于相同的缩进级别, 并且使用一个 "- " 作为开头(一个横杠和一个空格)
- 一个字典是由一个简单的 键: 值 的形式组成(这个冒号后面必须是一个空格)
- Ansible 使用 “{{ var }}” 来引用变量
Ansible playbook基础
Ansible-playbook (剧本)执行过程:
- 将已有编排好的任务集写入Ansible-Playbook
- 通过ansible-playbook命令分拆任务集至逐条ansible命令,按预定规则逐条执行
playbook.yml 常包含下面几个关键字:
- hosts:执行的远程主机列表,为主机的IP,或者主机组名,或者关键字all
- remote_user: 以哪个用户身份执行。
- vars: 内置变量或自定义变量在playbook中调用
- tasks: 任务集
- Templates:模板,可替换模板文件中的变量并实现一些简单逻辑的文件
- 每一个task必须有一个名称name,这样在运行playbook时,从其输出的任务执行信息中可以很好的辨别出是属于哪一个task的
- tags标签指定某条任务执行,用于选择运行playbook中的部分代码。ansible具有幂等性,因此会自动跳过没有变化的部分,即便如此,有些代码为测试其确实没有发生变化的时间依然会非常地长。此时,如果确信其没有变化,就可以通过tags跳过此些代码片断
- handers:是playbook的event ,默认不会执行,在action里触发才会执行。多次触发只执行一次。Handlers和notity结合使用,由特定条件触发的操作,满足条件方才执行,否则不执行
如果命令或脚本的退出码不为零,可以使用如下方式替代
tasks:
- name: run this command and ignore the result
shell: /usr/bin/somecommand || /bin/true
或者使用ignore_errors来忽略错误信息:
tasks:
- name: run this command and ignore the result
shell: /usr/ bin/somecommand
ignore_errors: True
一个简单的示例:
---
- hosts: webservers
remote_user: root
tasks:
- name: install pakeges
yum: name=httpd
tags: install
- name: create user
user: name=yanyujie uid=666 system=yes
- name: start service
service: name=httpd state=started
Playbook变量、handlers使用
变量
变量名:仅能由字母、数字和下划线组成,且只能以字母开头
变量来源:
- ansible setup facts远程主机的所有变量都可直接调用
- 在/etc/ansible/hosts中定义
普通变量:主机组中主机单独定义,优先级高于公共变量
公共(组)变量:针对主机组中所有主机定义统一变量 - 通过命令行指定变量,优先级最高
ansible-playbook -e varname=value - 在playbook中定义
vars:
- var1: value1
- var2: value2
- 在role中定义
变量的优先级
命令行定义>playbook中定义>/etc/ansible/hosts中定义
变量调用
通过{{ variable_name }} 调用变量,且变量名前后必须有空格,有时用"{{ variable_name }}”才生效
Handlers
是task列表,这些task与前述的task并没有本质上的不同,用于当关注的资源发生变化时,才会采取一定的操作
Notify此action可用于在每个play的最后被触发,这样可避免多次有改变发生
时每次都执行指定的操作,仅在所有的变化发生完成后一次性地执行指定操作。在notify中列出的操作称为handler ,也即notify中调用handler中定义的操作
一个notify可以跟多个handlers
例子:
---
- hosts: webservers
remote_user: root
vars:
- http_port: 8088
tasks:
- name: install pakeges
yum: name=httpd
tags: install
- name: copy config file
copy: src=httpd.conf dest=/etc/httpd/conf/httpd.conf
notify: restart service
- name: start service
service: name=httpd state=started
handlers:
- name: restart service
service: name=httpd state=restarted
Playbook模板templates
- 文本文件 ,嵌套有脚本(使用模板编程语言编写)
- Jinja2语言,使用字面量,有下面形式
字符串:使用单引号或双引号
数字:整数,浮点数
列表: [item1, item2, …]
元组: (item1, item2, …)
字典: {key1:value1, key2:value2…}
布尔型: true/false - 算术运算: +.-.*,/,//, %,**
- 比较操作: ==,!=,>, >=,<, <=
- 逻辑运算: and, or, not
- 流表达式: For If When
templates功能:根据模块文件动态生成对应的配置文件
templates文件必须存放于templates目录下,且命名为j2结尾
yaml/yml文件需和templates目录平级,目录结构如下:
./
├── temnginx.yml
└── templates
└── nginx.conf.j2
例子:
复制/etc/nginx/nginx.conf到templates目录并命名为nginx.conf.j2,修改nginx.conf.j2 下面行为
worker_processes {{ ansible_processor_vcpus }};
---
- hosts: webservers
remote_user: root
tasks:
- name: install pakeges
yum: name=nginx
- name: copy template file
template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf
notify: restart service
- name: start service
service: name=nginx state=started
handlers:
- name: restart service
service: name=nginx state=restarted
效果:启动nginx服务,每个服务器会根据自己的CPU数来决定多少个进程
Template中for和if
for
格式:
{% for M in N %}
{% endfor %}
例子:
//剧本文件
[root@ansible ansible]# cat testfor.yml
---
- hosts: all
remote_user: root
vars:
ports:
- 81
- 82
- 83
tasks:
- name: copy file
template: src=for1.conf.j2 dest=/data/for1.conf
//模板文件
[root@ansible ansible]# cat templates/for1.conf.j2
{% for port in ports %}
server {
listen {{ port }}
}
{% endfor %}
//运行剧本
[root@ansible ansible]# ansible-playbook testfor.yml
PLAY [all] ***************************************************************************************************************************
TASK [Gathering Facts] ***************************************************************************************************************
ok: [10.0.0.137]
TASK [copy file] *********************************************************************************************************************
ok: [10.0.0.137]
PLAY RECAP ***************************************************************************************************************************
10.0.0.137 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
//查看生成的文件
[root@ansible ansible]# ansible all -m shell -a 'cat /data/for1.conf'
10.0.0.137 | CHANGED | rc=0 >>
server {
listen 81
}
server {
listen 82
}
server {
listen 83
}
if
格式:
{% if M is defined %}
{% endif %}
例子:
// 剧本文件temnginx.yml
---
- hosts: webservers
remote_user: root
vars:
nginx_vhosts:
- web1:
listen: 8080
root: "/var/www/nginx/web1/"
- web2:
listen: 8080
server_name: "web2.yanyujie.com"
root: "/var/www/nginx/web2/"
- web3:
listen: 8080
server_name: "web3.yanyujie.com"
root: "/var/www/nginx/web3/"
tasks:
- name: template config to
template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf
//模板文件templates/nginx.conf.j2
{% for vhost in nginx_vhosts %}
server {
listen {{ vhost.listen }}
{% if vhost.server_name is defined %}
server_name {{ vhost.server_name }}
{% endif %}
root {{ vhost.root }}
}
{% endfor %}
//运行生成的结果
server {
listen 8080
root /var/www/nginx/web1/
}
server {
listen 8080
server_name web2.yanyujie.com
root /var/www/nginx/web2/
}
server {
listen 8080
server_name web3.yanyujie.com
root /var/www/nginx/web3/
}
Playbook when
- 条件测试:如果需要根据变量、facts或此前任务的执行结果来做为某task执行与否的前提时要用到条件测试,通过when语句实现,在task中使用, jinja2的语法格式
- when语句
- 在task后添加when子句即可使用条件测试; when语句支持Jinja2表达式语法
- 示例:
tasks:
- name: "shutdown RedHat flavored systems '
command: /sbin/shutdown -h now
when: ansible_OS_family == " RedHat'
例子:
---
- hosts: webservers
remote_user: root
vars:
- http_port: 8088
tasks:
- name: install pakeges
yum: name=httpd
tags: install
- name: copy template file
template: src=httpd.conf.j2 dest=/etc/httpd/conf/httpd.conf
when: ansible_distribution_major_version == '7'
notify: restart service
- name: start service
service: name=httpd state=started
handlers:
- name: restart service
service: name=httpd state=restarted
Playbook字典with_ items
迭代:with_items
迭代:当有需要重复性执行的任务时,可以使用迭代机制
- 对迭代项的引用,固定变量名为”item"
- 要在task中使用with_items给定要迭代的元素列表
- 列表格式:
字符串
字典
例子:
---
- hosts: webservers
remote_user: root
tasks:
- name: create some users
user: name={{ item }} shell=/sbin/nologin system=yes
with_items:
- test1
- test2
- test3
效果:test1、test2、test3都会创出
迭代嵌套子变量
分别创建g1,g2,g3三个组,创建user1,user2,user3,分别加入g1,g2,g3组里面
---
- hosts: webservers
remote_user: root
tasks:
- name: create some groups
group: name={{ item }}
with_items:
- g1
- g2
- g3
- name: create some users
user: name={{ item.user }} groups={{ item.group }}
with_items:
- { user: 'user1',group: 'g1' }
- { user: 'user2',group: 'g2' }
- { user: 'user3',group: 'g3' }
Ansible Roles
roles
ansilbe自1.2版本引入的新特性,用于层次性、结构化地组织playbook。 roles
能够根据层次型结构自动装载变量文件、tasks以及handlers等。 要使用roles只需要在playbook中使用include指令即可。简单来讲, roles就是通过分别将变量、文件、任务、模板及处理器放置于单独的目录中,并可以便捷地include它们的一种机制。角色一般用于基于主机构建服务的场景中,但也可以是用于构建守护进程等场景中
复杂场景:建议使用roles ,代码复用度高
- 变更指定主机或主机组
- 如命名不规范维护和传承成本大
- 某些功能需多个Playbook ,通过Includes即可实现
Roles目录编排
roles目录结构
每个角色,以特定的层级目录结构进行组织
roles目录结构:
./
├──playbook.yml
└──roles/
└──project/
├──tasks/
├──files/
├──vars/ 不常用
├──default/ 不常用
├──templates/
├──handlers/
├──meta/ 不常用
各目录作用
/roles/project/ :项目名称,有以下子目录
- files/ : 存放由copy或script模块等调用的文件
- templates/ : template模块查找所需要模板文件的目录
- tasks/ :定义task,role的基本元素,至少应该包含一个名为main.yml的文件;其它的文件需要在此文件中通过include进行包含
- handlers/ :至少应该包含一个名为main.yml的文件 ;其它的文件需要在此文件中通过include进行包含
- vars/ :定义变量,至少应该包含一个名为main.yml的文件;其它的文件需要在此文件中通过include进行包含
- meta/ :定义当前角色的特殊设定及其依赖关系,至少应该包含一个名为main.yml的文件,其它文件需在此文件中通过include进行包含
- default/ :设定默认变量时使用此目录中的main.ymI文件
创建role的步骤
- 创建以roles命名的目录
- 在roles目录中分别创建以各角色名称命名的目录,如webservers等
- 在每个角色命名的目录中分别创建files、handlers、 meta、 tasks、
templates和vars目录;用不到的目录可以创建为空目录,也可以不创建 - 在playbook文件中,调用各角色
可以跨角色调用
例如:
---
- hosts: webservers
remote_user: root
roles:
- role: nginx
- role: roles/mysql/tasks/copyfile.yml
可以取标签
例如:
---
- hosts: webservers
remote_user: root
roles:
- { role: nginx, tags:['app','nginx'] }
- { role: mysql, tags:['app','mysql'] }
ansible-playbook -t 指定标签 role_nginx.yml
例子
//roles目录解构
/root/ansible/
├── roles
│ ├── httpd
│ ├── memcache
│ ├── mysql
│ └── nginx
│ ├── files
│ │ └── vhosts.conf
│ ├── handlers
│ │ └── main.yml
│ ├── tasks
│ │ ├── copyfile.yml
│ │ ├── group.yml
│ │ ├── main.yml
│ │ ├── start.yml
│ │ ├── templ.yml
│ │ ├── user.yml
│ │ └── yum.yml
│ ├── templates
│ │ └── nginx.conf.j2
│ └── vars
│ └── main.yml
└── roles_nginx.yml
//tasks目录中文件内容
[root@ansible ansible]# cat roles/nginx/tasks/copyfile.yml
- name: copy file
copy: src=vhosts.conf dest=/etc/nginx/conf.d/ owner=app
[root@ansible ansible]# cat roles/nginx/tasks/group.yml
- name: create group
group: name=app gid=888
[root@ansible ansible]# cat roles/nginx/tasks/user.yml
- name: create user
user: name=app system=yes uid=888 group=nginx shell=/sbin/nologin
[root@ansible ansible]# cat roles/nginx/tasks/main.yml
- include: group.yml
- include: user.yml
- include: yum.yml
- include: templ.yml
- include: copyfile.yml
- include: start.yml
[root@ansible ansible]# cat roles/nginx/tasks/start.yml
- name: start nginx
service: name=nginx state=started enabled=yes
notify: restart nginx
[root@ansible ansible]# cat roles/nginx/tasks/templ.yml
- name: copy conf
template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf
[root@ansible ansible]# cat roles/nginx/tasks/yum.yml
- name: install packeges
yum: name=nginx
//handlers目录中文件内容
[root@ansible ansible]# cat roles/nginx/handlers/main.yml
- name: restart nginx
service: name=nginx state=restarted
//vars目录中文件内容
[root@ansible ansible]# cat roles/nginx/vars/main.yml
username: app
groupname: app
//files目录中文件内容
[root@ansible ansible]# cat roles/nginx/files/vhosts.conf
[root@ansible ansible]#
//templates目录中文件内容
[root@ansible ansible]# cat roles/nginx/templates/nginx.conf.j2
# For more information on configuration, see:
# * Official English Documentation: http://nginx.org/en/docs/
# * Official Russian Documentation: http://nginx.org/ru/docs/
user {{ username }}; //变量
worker_processes {{ ansible_processor_vcpus+2 }}; //变量
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;
worker_rlimit_nofile 655350;
# Load dynamic modules. See /usr/share/doc/nginx/README.dynamic.
include /usr/share/nginx/modules/*.conf;
events {
worker_connections 1024;
}
http {
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
include /etc/nginx/mime.types;
default_type application/octet-stream;
# Load modular configuration files from the /etc/nginx/conf.d directory.
# See http://nginx.org/en/docs/ngx_core_module.html#include
# for more information.
include /etc/nginx/conf.d/*.conf;
server {
listen 80;
server_name localhost;
# Load configuration files for the default server block.
include /etc/nginx/default.d/*.conf;
location / {
root html;
index index.html index.htm;
}
error_page 404 /404.html;
location = /40x.html {
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
}
# Settings for a TLS enabled server.
#
# server {
# listen 443 ssl http2 default_server;
# listen [::]:443 ssl http2 default_server;
# server_name _;
# root /usr/share/nginx/html;
#
# ssl_certificate "/etc/pki/nginx/server.crt";
# ssl_certificate_key "/etc/pki/nginx/private/server.key";
# ssl_session_cache shared:SSL:1m;
# ssl_session_timeout 10m;
# ssl_ciphers HIGH:!aNULL:!MD5;
# ssl_prefer_server_ciphers on;
#
# # Load configuration files for the default server block.
# include /etc/nginx/default.d/*.conf;
#
# location / {
# }
#
# error_page 404 /404.html;
# location = /40x.html {
# }
#
# error_page 500 502 503 504 /50x.html;
# location = /50x.html {
# }
# }
}
//调用
[root@ansible ansible]# cat roles_nginx.yml
---
- hosts: webservers
remote_user: root
roles:
- role: nginx
//运行结果
[root@ansible ansible]# ansible-playbook roles_nginx.yml
PLAY [webservers] ********************************************************************************************************************
TASK [Gathering Facts] ***************************************************************************************************************
ok: [10.0.0.137]
TASK [nginx : create group] **********************************************************************************************************
changed: [10.0.0.137]
TASK [nginx : create user] ***********************************************************************************************************
changed: [10.0.0.137]
TASK [nginx : install packeges] ******************************************************************************************************
ok: [10.0.0.137]
TASK [nginx : copy conf] *************************************************************************************************************
changed: [10.0.0.137]
TASK [nginx : copy file] *************************************************************************************************************
changed: [10.0.0.137]
TASK [nginx : start nginx] ***********************************************************************************************************
changed: [10.0.0.137]
RUNNING HANDLER [nginx : restart nginx] **********************************************************************************************
changed: [10.0.0.137]
PLAY RECAP ***************************************************************************************************************************
10.0.0.137 : ok=8 changed=6 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
//验证结果
[root@ansible ansible]# ansible all -m shell -a 'ss -ntlp|grep 80'
10.0.0.137 | CHANGED | rc=0 >>
LISTEN 0 128 *:80 *:* users:(("nginx",pid=35689,fd=6),("nginx",pid=35688,fd=6),("nginx",pid=35687,fd=6),("nginx",pid=35686,fd=6),("nginx",pid=35685,fd=6))
[root@ansible ansible]# ansible all -m shell -a 'ps -aux|grep app'
10.0.0.137 | CHANGED | rc=0 >>
root 1975 0.0 0.7 745824 14272 ? Sl 5月22 0:00 /usr/bin/gnome-software --gapplication-service
root 2004 0.0 0.7 451704 14920 ? Sl 5月22 0:00 abrt-applet
root 2034 0.0 0.7 1084900 14580 ? SNl 5月22 0:00 /usr/libexec/tracker-miner-apps
app 35686 0.0 0.1 121188 3512 ? S 04:49 0:00 nginx: worker process
app 35687 0.0 0.1 121188 3512 ? S 04:49 0:00 nginx: worker process
app 35688 0.0 0.1 121188 3512 ? S 04:49 0:00 nginx: worker process
app 35689 0.0 0.1 121188 3512 ? S 04:49 0:00 nginx: worker process
root 35954 0.0 0.0 113116 1220 pts/2 S+ 05:00 0:00 /bin/sh -c ps -aux|grep app
root 35956 0.0 0.0 112664 948 pts/2 S+ 05:00 0:00 grep app
[root@ansible ansible]# ansible all -m shell -a 'ls -l /etc/nginx/conf.d'
10.0.0.137 | CHANGED | rc=0 >>
总用量 0
-rw-r--r-- 1 app root 0 5月 23 04:49 vhosts.conf