admin管理员组

文章数量:1531443

自动化运维工具之ansible

  • Ansible简述
    • Ansible的特性
    • Ansible架构
    • 利用ansible实现管理的方式
    • Ansible主要操作对象
    • 注意事项
  • Ansible安装
    • rpm包安装
    • 编译安装
    • Git方式
    • pip安装: pip是安装Python包的管理器,类似yum
    • 确认安装
  • Ansible配置文件
  • Ansible命令
  • Ansible常用模块详解
    • 主机连通性测试
    • command 模块
    • shell 模块
    • copy 模块
    • script模块
    • file 模块
    • fetch 模块
    • hostname模块
    • cron模块
    • yum模块
    • service模块
    • user模块
    • group模块
    • setup模块
  • YAML语法简介
  • Ansible playbook基础
  • Playbook变量、handlers使用
  • Playbook模板templates
  • Template中for和if
    • for
    • if
  • Playbook when
  • Playbook字典with_ items
    • 迭代:with_items
    • 迭代嵌套子变量
  • Ansible Roles
    • Roles目录编排

Ansible简述

Ansible是一款自动化运维工具,基于Python开发,集合了众多运维工具(puppet、cfengine、chef、func、fabric)优点,实现了批量系统配置、批量程序部署、批量运行命令等功能。ansible是基于模块工作,本身没有批量部署的能力。真正具有批量部署的是ansible所运行的模块,ansible只是提供一种框架。主要包括:
(1)连接插件connection plugins:负责和被监控端实现通信;
(2)host inventory : 指定操作的主机,是一个配置文件里面定义监控的主机;
(3)各种模块核心模块、command模块、自定义模块;
(4)借助于插件完成记录日志邮件等功能;
(5)playbook:剧本执行多个任务时,非必须可以让节点一次运行多个任务

Ansible的特性

  1. 模块化:调用特定的模块,完成特定任务
  2. 有Paramiko , PyYAML , Jinja2 (模板语言)三个关键模块
  3. 支持自定义模块
  4. 基于Python语言实现
  5. 部署简单,基于python和SSH(默认已安装) , agentless
  6. 安全,基于OpenSSH
  7. 支持playbook编排任务
  8. 幂等性:一个任务执行1遍和执行n遍效果一 样,不因重复执行带来意外情况
  9. 无需代理不依赖PKI (无需ssI )
  10. 可使用任何编程语言写模块
  11. YAML格式,编排任务,支持丰富的数据结构
  12. 较强大的多层解决方案

Ansible架构

Ansible:Ansible核心程序。
HostInventory:记录由Ansible管理的主机信息,包括端口、密码、ip等。
Playbooks:“剧本”YAML格式文件,多个任务定义在一个文件中,定义主机需要调用哪些模块来完成的功能。
Core Modules:核心模块,主要操作是通过调用核心模块来完成管理任务。
CustomModules:自定义模块,完成核心模块无法完成的功能,支持多种语言。
PLUGINS :模块功能的补充,如连接类型插件、循环插件、变量插件、过滤插
件等,该功能不常用
ConnectionPlugins:连接插件,Ansible和Host通信使用

利用ansible实现管理的方式

  1. Ad-Hoc即ansible命令, 主要用于临时命令使用场景
  2. Ansible-playbook主要用于长期规划好的,大型项目的场景,需要有前提的规划。

Ansible主要操作对象

  1. HOSTS主机
  2. NETWORKING网络设备

注意事项

  1. 执行ansible的主机-般称为主控端,中控, master或堡垒机
  2. 主控端Python版本需要2.6或以上
  3. 被控端Python版本小于2.4需要安装python-simplejson
  4. 被控端如开启SELinux需 要安装libselinux-python
  5. 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/repo/epel-7.repo
--2020-05-20 21:45:57--  http://mirrors.aliyun/repo/epel-7.repo
正在解析主机 mirrors.aliyun (mirrors.aliyun)... 183.201.230.97, 183.201.230.100, 183.201.230.94, ...
正在连接 mirrors.aliyun (mirrors.aliyun)|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/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\" -m ping

ansible命令执行过程

  1. 加载自己的配置文件默认/etc/ansible/ansible.cfg
  2. 加载自己对应的模块文件,如command
  3. 通过ansible将模块或命令生成对应的临时py文件,并将该文件传输至远程服务器的对应执行用户$HOME/.ansible/tmp/ansible-tmp-数字/XXX.PY文件
  4. 给文件+x执行
  5. 执行并返回结果
  6. 删除临时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"
		 root: "/var/www/nginx/web2/"
	  - web3:
  		 listen: 8080
		 server_name: "web3.yanyujie"
 		 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
		root /var/www/nginx/web2/
}
server {
		listen 8080
		server_name web3.yanyujie
		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的步骤

  1. 创建以roles命名的目录
  2. 在roles目录中分别创建以各角色名称命名的目录,如webservers等
  3. 在每个角色命名的目录中分别创建files、handlers、 meta、 tasks、
    templates和vars目录;用不到的目录可以创建为空目录,也可以不创建
  4. 在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/en/docs/
#   * Official Russian Documentation: http://nginx/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/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

本文标签: 工具ansible