ansible 详解

文章目录

  • 一、ansible 简介
    • 1.1 ansible 是什么?
    • 1.2 ansible 特点
    • 1.3 ansible 架构图
  • 二、ansible 任务执行
    • 2.1 ansible 任务执行模式
    • 2.2 ansible 执行流程
    • 2.3 ansible 命令执行过程
  • 三、ansible 配置详解
    • 3.1 ansible 安装方式
      • 3.1.1 使用 pip(python的包管理模块)安装
      • 3.1.2 使用 yum 安装
    • 3.2 ansible 程序结构
    • 3.3 ansible配置文件
    • 3.4 ansuble主机清单
  • 四、ansible 常用命令
    • 4.1 ansible 命令集
    • 4.2 ansible-doc 命令
    • 4.3 ansible 命令详解
  • 五、ansible 常用模块
    • 5.1 ping 模块
    • 5.2 command 模块
    • 5.3 shell 模块
    • 5.4 copy 模块
    • 5.5 file 模块
    • 5.6 fetch 模块
    • 5.7 cron 模块
    • 5.8 yum 模块
    • 5.9 apt 模块
    • 5.10 service 模块
    • 5.11 unarchive 模块
    • 5.12 lineinfile 模块
    • 5.13 script 模块
    • 5.14 setup 模块
    • 5.15 user 模块
    • 5.16 mount 模块
    • 5.17 wait_for模块
  • 六、playbook
    • 6.1 playbook核心元素
    • 6.2 playbook基本语法
    • tags: 添加标签
    • 6.3 handlers
    • 6.4 register 和when
    • 6.5 循环
    • 6.6 模板templates
      • 6.6.1 template 的使用
      • 6.6.2 template示例
    • 6.7 roles
      • 6.7.1 Roles介绍
      • 6.7.2 Roles目录结构
      • 6.7.3 Roles示例

一、ansible 简介

1.1 ansible 是什么?

  ansible是新出现的自动化运维工具,基于Python开发,集合了众多运维工具(puppet、chef、func、fabric)的优点,实现了批量系统配置、批量程序部署、批量运行命令等功能。

  ansible是基于 paramiko 开发的,并且基于模块化工作,本身没有批量部署的能力。真正具有批量部署的是ansible所运行的模块,ansible只是提供一种框架。ansible不需要在远程主机上安装client/agents,因为它们是基于ssh来和远程主机通讯的。ansible目前已经已经被红帽官方收购,是自动化运维工具中大家认可度最高的,并且上手容易,学习简单。是每位运维工程师必须掌握的技能之一。

1.2 ansible 特点

  1. 部署简单,只需在主控端部署Ansible环境,被控端无需做任何操作;
  2. 默认使用SSH协议对设备进行管理;
  3. 有大量常规运维操作模块,可实现日常绝大部分操作;
  4. 配置简单、功能强大、扩展性强;
  5. 支持API及自定义模块,可通过Python轻松扩展;
  6. 通过Playbooks来定制强大的配置、状态管理;
  7. 轻量级,无需在客户端安装agent,更新时,只需在操作机上进行一次更新即可;
  8. 提供一个功能强大、操作性强的Web管理界面和REST API接口——AWX平台。
  9. 幂等性:一个任务执行1遍和执行n遍效果一样,不因重复执行带来意外情况

1.3 ansible 架构图

ansible 详解_第1张图片

主要模块

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

二、ansible 任务执行

2.1 ansible 任务执行模式

Ansible 系统由控制主机对被管节点的操作方式可分为两类,即adhocplaybook

  • ad-hoc模式(点对点模式)
     使用单个模块,支持批量执行单条命令。ad-hoc 命令是一种可以快速输入的命令,而且不需要保存起来的命令。就相当于bash中的一句话shell。
  • playbook模式(剧本模式)
     是Ansible 主要管理方式 ,也是Ansible功能强大的关键所在。playbook通过多个task集合完成一类功能,如Web服务的安装部署、数据库服务器的批量备份等。可以简单地把playbook理解为通过组合多条ad-hoc操作的配置文件。

2.2 ansible 执行流程

ansible 详解_第2张图片

简单理解就是Ansible在运行时, 首先读取ansible.cfg中的配置, 根据规则获取Inventory中的管理主机列表, 并行的在这些主机中执行配置的任务, 最后等待执行返回的结果。

2.3 ansible 命令执行过程

  1. 加载自己的配置文件,默认/etc/ansible/ansible.cfg;
  2. 查找对应的主机配置文件,找到要执行的主机或者组;
  3. 加载自己对应的模块文件,如 command;
  4. 通过ansible将模块或命令生成对应的临时py文件(python脚本), 并将该文件传输至远程服务器;
  5. 对应执行用户的家目录的.ansible/tmp/XXX/XXX.PY文件;
  6. 给文件 +x 执行权限;
  7. 执行并返回结果;
  8. 删除临时py文件,sleep 0退出;

三、ansible 配置详解

3.1 ansible 安装方式

ansible安装常用两种方式,yum安装和pip程序安装

3.1.1 使用 pip(python的包管理模块)安装

需要安装一个python-pip包,安装完成以后,则直接使用pip命令来安装我们的ansible包

[root@localhost ~]$ yum install python-pip
[root@localhost ~]$ pip install ansible

3.1.2 使用 yum 安装

需要先安装一个epel-release包,然后再安装 ansible 即可。

[root@localhost ~]$ yum -y install epel-release
[root@localhost ~]$ yum -y install ansible

3.2 ansible 程序结构

安装目录如下(yum安装):

  • 配置文件目录:/etc/ansible/
  • 执行文件目录:/usr/bin/
  • Lib库依赖目录:/usr/lib/pythonX.X/site-packages/ansible/
  • Help文档目录:/usr/share/doc/ansible-X.X.X/
  • Man文档目录:/usr/share/man/man1/

3.3 ansible配置文件

ansible 的配置文件为/etc/ansible/ansible.cfg,下面是常见参数

inventory = /etc/ansible/hosts		  #这个参数表示资源清单inventory文件的位置
library = /usr/share/ansible		 #指向存放Ansible模块的目录,支持多个目录方式,只要用冒号(:)隔开就可以
forks = 5		                      #并发连接数,默认为5
sudo_user = root		              #设置默认执行命令的用户
remote_port = 22		              #指定连接被管节点的管理端口,默认为22端口,建议修改,能够更加安全
ask_pass = True                #是否需要密码
host_key_checking = False		     #设置是否检查SSH主机的密钥,值为True/False。关闭后第一次连接不会提示配置实例
timeout = 60		                #设置SSH连接的超时时间,单位为秒
log_path = /var/log/ansible.log		#指定一个存储ansible日志的文件(默认不记录日志)

3.4 ansuble主机清单

在配置文件中,我们提到了资源清单,这个清单就是我们的主机清单,里面保存的是一些 ansible 需要连接管理的主机列表。在/etc/ansible/hosts文件内

直接指明主机地址或主机名:

[root@localhost ~]$ vim /etc/ansible/hosts 
## green.example.com#
# blue.example.com#
# 192.168.100.1
# 192.168.100.10

定义一个主机组[组名]把地址或主机名加进去

[root@localhost ~]$ vim /etc/ansible/hosts 
[mysql_test]
192.168.253.159 ansible_user=root ansible_port=22 ansible_ssh_pass=root
192.168.253.160 ansible_user=root ansible_port=22 ansible_ssh_pass=root
192.168.253.153 ansible_user=root ansible_port=22 ansible_ssh_pass=root

还可以使用密钥对配置免密登录
服务端生成密钥对

[root@localhost ~]$ ssh-keygen    #一路回车

然后把公钥传到被控端

[root@localhost ~]$ ssh-copy-id [email protected]

vars变量 :定义主机的内置参数
定义属于整个组的变量

[root@localhost ~]$ vim /etc/ansible/hosts 
[test]
host1
host2

[test:vars]
ntp_server=ntp.atlanta.example.com
proxy=proxy.atlanta.example.com

嵌套定义vars

#编写主机组
[group1]
group1.linux.com
 
[group2]
group2.example.com
 
[group:children]
group1
group2
 
#嵌套变量定义
[group:vars]   ##用var进行标识
user=studen    ##以字典方式定义

子组分类变量:children
可以把一个组作为另一个组的子成员,以及分配变量给整个组使用

[root@localhost ~]$ vim /etc/ansible/hosts 
[nginx]
192.168.1.31
[apache]
192.168.1.32
[webservers:children] #子组分类变量
apache
nginx

[webservers:vars]  #webservers组的内置变量
ansible_ssh_user='root'
ansible_ssh_pass='redhat'
ansible_ssh_port='22'

Inventory(主机清单) 参数的说明

ansible_ssh_host
      将要连接的远程主机名.与你想要设定的主机的别名不同的话,可通过此变量设置.

ansible_ssh_port
      ssh端口号.如果不是默认的端口号,通过此变量设置.

ansible_ssh_user
      默认的 ssh 用户名

ansible_ssh_pass
      ssh 密码(这种方式并不安全,我们强烈建议使用 --ask-pass 或 SSH 密钥)

ansible_sudo_pass
      sudo 密码(这种方式并不安全,我们强烈建议使用 --ask-sudo-pass)

ansible_sudo_exe (new in version 1.8)
      sudo 命令路径(适用于1.8及以上版本)

ansible_connection
      与主机的连接类型.比如:local, ssh 或者 paramiko. Ansible 1.2 以前默认使用 paramiko.1.2 以后默认使用 'smart','smart' 方式会根据是否支持 ControlPersist, 来判断'ssh' 方式是否可行.

ansible_ssh_private_key_file
      ssh 使用的私钥文件.适用于有多个密钥,而你不想使用 SSH 代理的情况.

ansible_shell_type
      目标系统的shell类型.默认情况下,命令的执行使用 'sh' 语法,可设置为 'csh''fish'.

ansible_python_interpreter
      目标主机的 python 路径.适用于的情况: 系统中有多个 Python, 或者命令路径不是"/usr/bin/python",比如  \*BSD, 或者 /usr/bin/python
      不是 2.X 版本的 Python.我们不使用 "/usr/bin/env" 机制,因为这要求远程用户的路径设置正确,且要求 "python" 可执行程序名不可为 python以外的名字(实际有可能名为python26).

四、ansible 常用命令

4.1 ansible 命令集

/usr/bin/ansible   Ansibe AD-Hoc 临时命令执行工具,常用于临时命令的执行
/usr/bin/ansible-doc    Ansible 模块功能查看工具
/usr/bin/ansible-galaxy   下载/上传优秀代码或Roles模块 的官网平台,基于网络的
/usr/bin/ansible-playbook  Ansible 定制自动化的任务集编排工具
/usr/bin/ansible-pull   Ansible远程执行命令的工具,拉取配置而非推送配置(使用较少,海量机器时使用,对运维的架构能力要求较高)
/usr/bin/ansible-vault   Ansible 文件加密工具
/usr/bin/ansible-console  Ansible基于Linux Consoble界面可与用户交互的命令执行工具
/etc/ansible/roles 角色存放处

其中,我们比较常用的是/usr/bin/ansible/usr/bin/ansible-playbook

4.2 ansible-doc 命令

ansible-doc 命令常用于获取模块信息及其使用帮助

[root@localhost ~]$ ansible-doc
Usage: ansible-doc [options] [module...]

Options:
  -h, --help            show this help message and exit  # 显示命令参数API文档
  -l, --list            List available modules  #列出可用的模块
  -M MODULE_PATH, --module-path=MODULE_PATH  #指定模块的路径
                        specify path(s) to module library (default=None)
  -s, --snippet         Show playbook snippet for specified module(s)  #显示playbook制定模块的用法
  -v, --verbose         verbose mode (-vvv for more, -vvvv to enable  # 显示ansible-doc的版本号查看模块列表:
                        connection debugging)
  --version             show program's version number and exit

4.3 ansible 命令详解

命令的具体格式如下:

ansible <host-pattern> [-f forks] [-m module_name] [-a args]
ansible  匹配主机模式   -m  模块  -a  '需要执行的内容'

< host-pattern>   匹配主机的列表
	- ALL   表示列表中的所有主机
    ansible all -m  ping   #匹配所有主机
	- *   支持通配符
    ansible "*" -m ping  #匹配所有主机
    ansible 192.168.1.* -m ping  #匹配IP地址以192.168.1开头的主机
    ansible “*srvs” -m ping  # 匹配分组名 以 srvs结尾的主机
    ansible websrvs  -m ping #匹配分组名为websrvs
    

常用选项:
	-a MODULE_ARGS #模块的参数,如果执行默认COMMAND的模块,即是命令参数,如: “date”,“pwd”等等
	-m MODULE_NAME #执行模块的名字,默认使用 command 模块,所以如果是只执行单一命令可以不用 -m参数
	-k,--ask-pass #ask for SSH password。登录密码,提示输入SSH密码而不是假设基于密钥的验证
	--ask-su-pass #ask for su password。su切换密码
	-K,--ask-sudo-pass #ask for sudo password。提示密码使用sudo,sudo表示提权操作
	--ask-vault-pass #ask for vault password。假设我们设定了加密的密码,则用该选项进行访问
	-B SECONDS #后台运行超时时间
	-C   #模拟运行环境并进行预运行,可以进行查错测试
	-c CONNECTION #连接类型使用
	-f FORKS #并行任务数,默认为5
	-i INVENTORY #指定主机清单的路径,默认为/etc/ansible/hosts
	--list-hosts #查看有哪些主机组
	-o #压缩输出,尝试将所有结果在一行输出,一般针对收集工具使用
	-S #用 su 命令
	-R SU_USER #指定 su 的用户,默认为 root 用户
	-s #用 sudo 命令
	-U SUDO_USER #指定 sudo 到哪个用户,默认为 root 用户
	-T TIMEOUT #指定 ssh 默认超时时间,默认为10s,也可在配置文件中修改
	-u REMOTE_USER #远程用户,默认为 root 用户
	-v #查看详细信息,同时支持-vvv,-vvvv可查看更详细信息

五、ansible 常用模块

模块名 说明
ping 检查指定节点机器是否还能连通,用法很简单,不涉及参数,主机如果在线,则回复pong
command 和 shell 用于在各被管理节点运行指定的命令. shell和command的区别:shell模块可以特殊字符,而command是不支持
copy 在远程主机执行复制操作文件。
file 主要用于远程主机上的文件操作。
fetch 它用于从远程机器获取文件,并将其本地存储在由主机名组织的文件树中。
cron 该模块适用于管理cron计划任务的。
yum RedHat和CentOS的软件包安装和管理工具。
apt Ubuntu/Debian的软件包安装和管理工具。
service 或 systemd 用于管理远程主机的服务。
user 模块 与 group user模块是请求的是useradd, userdel, usermod三个指令,goup模块请求的是groupadd, groupdel, groupmod 三个指令。
script 在远程主机上执行主控端的脚本,相当于scp+shell组合。
setup 该模块主要用于收集信息
lineinfile 远程主机上的文件编辑模块
unarchive 用于解压文件。
hostname 修改远程主机名的模块。批量修改主机名时最好加变量,防止所有主机名一致,ansible all -m hostname -a “name=webserver1”
mount 挂载文件系统。
wait_for 等待一个事情发生,然后继续。它可以等待某个端口被占用,然后再做下面的事情,也可以在一定时间超时后做另外的事。

5.1 ping 模块

ping模块用来检查目标主机是否在线

 [root@localhost ~]$ ansible test -m ping
 192.168.37.122 | SUCCESS => {
    "changed": false, 
    "ping": "pong"
}
192.168.37.133 | SUCCESS => {
    "changed": false, 
    "ping": "pong"
}

5.2 command 模块

可以直接在远程主机上执行命令,并将结果返回本主机。不支持特殊字符

[root@localhost ~]$ ansible test -m command -a 'ss -ntl'

常用的选项:
	chdir:     # 在执行命令之前,先切换到该目录
	executable:   # 切换shell来执行命令,需要使用命令的绝对路径
	free_form:   # 要执行的Linux指令,一般使用Ansible的-a参数代替。
	creates:     # 一个文件名,当这个文件存在,则该命令不执行,可以用来做判断
	removes:      # 一个文件名,这个文件不存在,则该命令不执行
	

#先切换到/data/ 目录,再执行“ls”命令
[root@localhost ~]$ ansible test -m command -a 'chdir=/data/ ls'

#如果/data/aaa.jpg存在,则不执行“ls”命令
[root@localhost ~]$ ansible test -m command -a 'creates=/data/aaa.jpg ls'

#如果/data/aaa.jpg存在,则执行“cat /data/a”命令
[root@localhost ~]$ ansible test -m command -a 'removes=/data/aaa.jpg cat /data/a'


注意,该命令不支持| 管道命令。

5.3 shell 模块

shell模块可以在远程主机上调用shell解释器运行命令,支持shell的各种功能

[root@localhost ~]$ ansible test -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


5.4 copy 模块

用于将文件复制到远程主机,同时支持给定内容生成文件和修改权限等。远程主机目录不存在,则会自动创建

[root@localhost ~]$ ansible test -m copy -a 'src=~/hello dest=/data/hello' 

常用选项:
	src:     # 源文件绝对路径或相对路径
	dest:     #必选项,将源文件复制到的远程主机的绝对路径
	content:   #用于替换"src",可以直接指定文件的值
	backup:    #当文件内容发生改变后,在覆盖之前把源文件备份,备份文件包含时间信息
	directory_mode:    #递归设定目录的权限,默认为系统默认权限
	force:      #当目标主机包含该文件,但内容不同时,设为"yes",表示强制覆盖;为"no",表示目标主机的目标位置不存在该文件才复制。默认为"yes"
	others:    #所有的 file 模块中的选项可以在这里使用
	mode:         #设置文件权限
	owner:        #属主
	group:        #属组
	
	

#给定内容生成文件,并制定权限
[root@localhost ~]$ ansible test -m copy -a 'content="I am keer\n" dest=/data/name mode=666'



#查看一下我们生成的文件及其权限
[root@localhost ~]$ ansible test -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

#把文件的内容修改一下,然后选择覆盖备份
[root@localhost ~]$ ansible test -m copy -a 'content="I am keerya\n" backup=yes dest=/data/name mode=666'



#可以查看一下name文件的内容
[root@localhost ~]$ ansible test -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.5 file 模块

该模块主要用于设置文件的属性,比如创建文件、创建链接文件、删除文件等。

[root@localhost ~]$ ansible test -m file -a 'path=/data/app state=directory'

常用选项:
	path:  #必选项,定义文件/目录的路径
	force:  #需要在两种情况下强制创建软链接,一种是源文件不存在,但之后会建立的情况下;另一种是目标软链接已存在,需要先取消之前的软链,然后创建新的软链,有两个选项:yes|no
	group:  #定义文件/目录的属组。后面可以加上mode:定义文件/目录的权限
	owner:  #定义文件/目录的属主。后面必须跟上path:定义文件/目录的路径
	recurse:  #递归设置文件的属性,只对目录有效,后面跟上src:被链接的源文件路径,只应用于state=link的情况
	dest:  #被链接到的路径,只应用于state=link的情况
	state:  #状态,有以下选项:
		directory:如果目录不存在,就创建目录
		file:即使文件不存在,也不会被创建
		link:创建软链接
		hard:创建硬链接
		touch:如果文件不存在,则会创建一个新的文件,如果文件或目录已存在,则更新其最后修改时间
		absent:删除目录、文件或者取消链接文件
		
		
		

#创建新目录
[root@localhost ~] ansible all -m file -a 'name=/data state=directory'

#创建新文件
[root@localhost ~]$ ansible all -m file -a 'name=/data/f3 state=touch' 

#删除文件
[root@localhost ~]$ ansible all -m file -a 'name=/data/f3 state=absent'

#删除目录下的所有文件(建议使用shell好用)
[root@localhost ~]$ ansible all -m shell -a 'rm -rf /data/*'

#创建目录
[root@localhost ~]$ ansible all -m file -a 'name=/data/dir1 state=directory'

#删除目录
[root@localhost ~]$ ansible all -m file -a 'name=/data/dir1 state=absent'

#创建软连接
[root@localhost ~]$ ansible all -m file -a 'src=/etc/fstab dest=/data/fstab.link state=link'
[root@localhost ~]$ ansible all -m file -a 'dest=/data/fstab.link state=absent'

#创建文件指定所有者,权限
[root@localhost ~]$ ansible all -m file -a 'path=/root/a.sh owner=liych mode=755'
[root@localhost ~]$ ansible all -m file -a 'src=/data/testfile dest=/data/testfile-link state=link'

5.6 fetch 模块

该模块用于从远程某主机获取(复制)文件到本地。

[root@localhost ~]$ ansible web -m fetch -a 'src=/data/hello dest=/data'

常用选项:
	dest:  # 本地存储拉取文件的目录。
	src:  # 远程主机上的源文件,不支持目录。在未来的版本可能会支持目录递归拉取。
	validate_checksum:        # 获取文件后验证源和目标校验和是否匹配
	
	
#远程主机拉取文件
[root@localhost ~]$ ansible test -m fetch -a 'src=/data/hello dest=/data'  

[root@localhost ~]$ ls /data/

5.7 cron 模块

该模块适用于管理cron计划任务的。其使用的语法跟我们的crontab文件中的语法一致

[root@localhost ~]$ ansible web -m cron -a 'name="ntp update every 5 min" minute=*/5 job="/sbin/ntpdate 172.17.0.1 &> /dev/null"'

常用选项:
	name:     #定时任务描述
	job:      #指明运行的命令是什么,可以写shell命令
	cron_file:      # 自定义cron_file的文件名,使用相对路径则在/etc/cron.d中。
	user:           # 以哪个用户的身份执行

	minute:         # 分(0-59, *, */N),不写时,默认为*
	hour:          # 时(0-23, *, */N),不写时,默认为*
	day:           # 日(1-31, *, */N),不写时,默认为*
	month:          # 月(1-12, *, */N),不写时,默认为*
	weekday:        # 周(0-6 for Sunday-Saturday, *),不写时,默认为*

	special_time #特殊的时间范围,参数: reboot(重启时),annually(每年),monthly(每月),weekly(每周),daily(每天),hourly(每小时)
	state #指定状态
		present表示添加定时任务,也是默认设置
		absent表示删除定时任务



#创建计划任务:每周1,3,5,每分钟打印warning,任务名称:test 
[root@localhost ~]$ ansible all -m cron -a 'minute=* weekday=1,3,5 job="/usr/bin/wall  warning" name=test'

#注释禁用cronname=test的计划任务:也可以用yes/no
[root@localhost ~]$ ansible all -m cron -a 'disabled=true job="/usr/bin/wall  warning" name=test'

#给cronname=test的计划任务去掉注释:也可以用yes/no
[root@localhost ~]$ ansible all -m cron -a 'disabled=false job="/usr/bin/wall  warning" name=test'

#删除计划任务:
[root@localhost ~]$ ansible all -m cron -a 'job="/usr/bin/wall warning" name=test state=absent'

#查看计划任务:
[root@localhost ~]$ ansible all -m shell -a 'crontab -l'

#增加定时任务
[root@localhost ~]$ vim add_cron.yaml
---
- hosts: sktest
  remote_user: root
  gather_facts: False
  tasks:
   - name: copy file
     copy: src=/etc/ansible/test.sh dest=/home/ mode=755
   - name: add cron #每2小时执行一次
     cron: name='test' hour=*/2 job='bash /home/test.sh'
   - name: zhushi cron #取消注释 disabled=false
     cron: name='test' hour=*/2 job='bash /home/test.sh' disabled=true


5.8 yum 模块

RedHat和CentOS的软件包安装和管理工具。

[root@localhost ~]$ ansible web -m yum -a 'name=htop state=present'

常用选项:
	name=           #所安装的包的名称
	state=          #present--->安装, latest--->安装最新的, absent---> 卸载软件。
	update_cache       #强制更新yum的缓存
	conf_file          #指定远程yum安装时所依赖的配置文件(安装本地已有的包)。
	disable_pgp_check  #是否禁止GPG checking,只用于presentor latest。
	disablerepo         #临时禁止使用yum库。 只用于安装或更新时。
	enablerepo        #临时使用的yum库。只用于安装或更新时。
	
	
	

#yum安装vsftpd包:(默认state=installd)
#列出和ansible相关的包。
[root@localhost ~]$ ansible all -m yum -a "list=ansible" 
[root@localhost ~]$ ansible all -m yum -a 'name=nginx'

#安装多个包用逗号隔开:
[root@localhost ~]$ ansible all -m yum -a 'name=nginx,vsftpd'

#显示所有已安装的包:
[root@localhost ~]$ ansible all -m yum -a 'name=vsftpd  list=installd'

#卸载vsftpd包:
[root@localhost ~]$ ansible all -m yum -a 'name=nvsftpd  state=removed'

#安装从互联网下载的包:
[root@localhost ~]$ ansible all -m yum -a 'name=https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm state=present'

#安装本地的包,且排除某些包不安装。
[root@localhost ~]$ ansible all -m yum -a "name=/tmp/*.rpm exclude=*unix* state=present"

#更新缓存:
[root@localhost ~]$ ansible all -m yum -a 'update_cache=yes'

#更新缓存同时安装dstat包
[root@localhost ~]$ ansible all -m yum -a 'name=dstat update_cache=yes'


yum_repository模块管理远程主机上的yum仓库

参数
	name:相当于.repo文件定义中括号的[仓库ID]
	baseurl:相当于.repo文件中baseurl
	description:相当于.repo文件中的name
	file:相当于.repo文件的名称,不使用时默认以name加.repo命令
	enabled=yes|no:相当于.repo文件中enabled
	gpgcheck=yes|no:相当于.repo文件中gpgcheck
	gpgcakey:前提是gpgcheck=yes,相当于.repo文件中gpgkey,验证gpg公钥
	state=present|absent:默认present,absent表示删除

示例

创建阿里云epel源

[root@localhost ~]$ ansible all -m yum_repository -a 'name=aliepel baseurl=https://mirrors.aliyun.com/epel/7/x86_64/ enabled=yes gpgcheck=yes gpgcakey=https://mirrors.aliyun.com/epel/RPM-GPG-KEY-EPEL-7 state=present file=AlicloudEpel'

删除阿里云epel源

[root@localhost ~]$ ansible all -m yum_repository -a 'file=AlicloudEpel name=aliepel state=absent'

5.9 apt 模块

Apt是Ubuntu/Debian的包管理工具。

[root@localhost ~]$ ansible web-nodes -m apt -a 'name=foo update_cache=yes'

常用选项:
	deb:                #用于安装远程机器上的.deb后缀的软件包(optional)
	install_recommends:    #这个参数可以控制远程电脑上是否只是下载软件包,还是下载后安装,默认参数为true,设置为false的时候只下载软件包,不安装
	update_cache: #当这个参数为yes的时候等于apt-get update(optional)
	name:          #apt要下载的软件包名字,支持name=git=1.6 这种制定版本的模式
	state:         #状态(present,absent,latest),表示是安装还是卸载. 其中present、installed、latest 表示安装, absent 、removed表示卸载删除; present默认状态, laster表示安装最新版本.
	
	
	

#在安装foo软件包前更新然后安装foo
[root@localhost ~]$ ansible web-nodes -m apt -a 'name=foo update_cache=yes'
 
#移除foo软件包
[root@localhost ~]$ ansible web-nodes -m apt -a 'name=foo state=absent'
 
#安装foo软件包
[root@localhost ~]$ ansible web-nodes -m apt -a 'name=foo state=present'
 
#安装foo 1.0软件包
[root@localhost ~]$ ansible web-nodes -m apt -a 'name=foo=1.00 state=present'
 
#安装nginx最新的名字为squeeze-backport发布包,并且安装前执行更新
[root@localhost ~]$ ansible web-nodes -m apt -a 'name=nginx state=latest default_release=squeeze-backports update_cache=yes'
 
#只下载openjdk-6-jdk最新的软件包,不安装
[root@localhost ~]$ ansible web-nodes -m apt -a 'name=openjdk-6-jdk state=latest install_recommends=no'
 
#安装所有软件包到最新版本
[root@localhost ~]$ ansible web-nodes -m apt -a 'upgrade=dist'
 
#更新apt-get的list
[root@localhost ~]$ ansible web-nodes -m apt -a 'update_cache=yes'
 
#3600秒后停止update_cache
[root@localhost ~]$ ansible web-nodes -m apt -a 'update_cache=yes cache_valid_time=3600'
 
#安装远程节点上的/tmp/mypackage.deb软件包
[root@localhost ~]$ ansible web-nodes -m apt -a 'deb=/tmp/mypackage.deb'

5.10 service 模块

该模块用于服务程序的管理。

[root@localhost ~]$ ansible web -m service -a 'name=nginx state=started enabled=true' 

常用选项:

	enabled=[yes|no] #是否开机启动 默认no
	name:           #必选项,服务名称
	pattern:        #定义一个模式,如果通过status指令来查看服务的状态时,没有响应,就会通过ps指令在进程中根据该模式进行查找,如果匹配到,则认为该服务依然在运行
	sleep:          #如果执行了restarted,在则stop和start之间沉睡几秒钟
	state:          #对当前服务执行启动,停止、重启、重新加载等操作    
					 #(started,stopped,restarted,reloaded)

#停止httpd服务:
[root@localhost ~]$ ansible all -m service -a ‘name=httpd state=stopped’

#开启httpd服务:
[root@localhost ~]$ ansible all -m service -a ‘name=httpd state=started’

#重新加载httod服务:
[root@localhost ~]$ ansible all -m service -a ‘name=httpd state=reloaded’

#重启httpd服务:
[root@localhost ~]$ ansible all -m service -a ‘name=httpd state=restarted’

#开启ftp服务,同时设置开机自动启动:
[root@localhost ~]$ ansible all -m service -a ‘name=vsftpd state=started enabled=yes’

#重启ftp服务:
[root@localhost ~]$ ansible all -m service -a ‘name=vsftpd state=restarted’

5.11 unarchive 模块

将ansible主机上的压缩包在本地解压缩后传到远程主机上,或者将远程主机上的某个压缩包解压缩到指定路径下

[root@localhost ~]$ ansible pms -m unarchive -a 'src=/srv/tomcat8/apache-tomcat-8.0.29.tar.gz dest=/usr/local copy=no mode=0755'

常用选项:
	creates:一个文件名,当它已经存在时,这个步骤将不会被运行。
	copy:默认为yes,拷贝的文件从ansible主机复制到远程主机,no在远程主机上寻找src源文件解压
	src:tar源路径,可以是ansible主机上的路径,也可以是远程主机上的路径,如果是远程主机上的路径,则需设置copy=no
	dest:远程主机上的目标绝对路径
	mode:设置解压缩后的文件权限
	exec:列出需要排除的目录和文件
	remote_src:设置remote_src=yes为解包目标上已经存在的档案。对于Windows目标,改用win_unzip模块。
	owner:解压后文件或目录的属主
	group:解压后的目录或文件的属组
	
	
#解压ansible管理机上的压缩文件到远程主机并设置权限
[root@localhost ~]$ ansible all -m unarchive -a "src=/tmp/install/zabbix-3.0.4.tar.gz dest=/tmp/ mode=755 copy=yes"

#在远程主机上解压文件并设置权限
[root@localhost ~]$ ansible all -m unarchive -a 'src=/srv/tomcat8/apache-tomcat-8.0.29.tar.gz dest=/usr/local copy=no mode=755'


---
- hosts: test
  remote_user: root
  gather_facts: False
  tasks:
   - name: tar tomcat
     unarchive: src=/srv/tomcat8/apache-tomcat-8.0.29.tar.gz dest=/usr/local copy=yes
     notify:
       - restart tomcat

  handlers: 
    - name: restart tomcat 
      shell: service tomcat restart



5.12 lineinfile 模块

用于对远程受控节点的文件编辑模块

[root@localhost ~]$ ansible web-nodes -m lineinfile -a 'path=/data/test regexp="123" line="wangshibo" backrefs=no'

常用选项:
	path: 指定要修改的配置文件, 包括:
			 regexp:匹配要修改的内容,可以使用政策
			 line:要增加或者修改的内容
	state: 状态, 包括:
			 absent:表示删除,当匹配到时进行删除
			 present:表示增加,当匹配到时进行修改,当没有匹配到时在最后增加一行,默认为此项
	backrefs: 该参数值包括:
			 no:表示如果没有匹配到,则增加line;如果匹配成功,则替换line;
			 yes:表示如果没有匹配到,则不变line;如果匹配成功,则替换line;
	backup: 该参数值包括:
			 no:表示如果没有匹配到,则增加line;如果匹配成功,则替换line;不备份原文件
			 yes:表示如果没有匹配到,则增加line;如果匹配成功,则替换line;备份原文件
	insertafter(匹配的是此行): 在匹配到的行之后添加一行.  (经测试, 发现是匹配到的行的最后一行的后面添加一行)
	insertbefore(匹配的是此行): 在匹配到的行之前添加一行.  (经测试, 发现是匹配到的行的最后一行的前面添加一行)
	
	
	
#将远程受控节点的/data/test文件中的"123"字段修改为"wangshibo"
[root@localhost ~] ansible web-nodes -m lineinfile -a 'path=/data/test regexp="123" line="wangshibo" backrefs=no'
 
# 将line开头的行替换为test test
[root@localhost ~]$ ansible test -m lineinfile -a "path=/testdir/test regexp='^line' line='test test'"
 
#匹配到的行后增加一行
[root@localhost ~]$ ansible test -m lineinfile -a 'dest=/data/test insertafter="wangshibo" line="huihui"'
 
#匹配到的行前增加一行 
[root@localhost ~]$ ansible test -m lineinfile -a 'dest=/data/test insertbefore="root" line="huihui"'
 
#删除匹配到的行:
[root@localhost ~]$ ansible test -m lineinfile -a 'path=/data/test regexp="123" state=absent'


5.13 script 模块

该模块用于将本机的脚本在被管理端的机器上运行。

[root@localhost ~]$ vim /tmp/df.sh
#!/bin/bash

date >> /tmp/disk_total.log
df -lh >> /tmp/disk_total.log 
[root@localhost ~] chmod +x /tmp/df.sh 

#执行脚本
[root@localhost ~]$ ansible web -m script -a '/tmp/df.sh'

5.14 setup 模块

该模块主要用于收集信息,是通过调用facts组件来实现的。
查看信息
  可以直接用命令获取到变量的值

[root@localhost ~]$ ansible web -m setup -a 'filter="*mem*"'	#查看内存
[root@localhost ~]$ cd /tmp/facts/

保存信息
setup模块还有一个很好用的功能就是可以保存我们所筛选的信息至我们的主机上,同时,文件名为我们被管制的主机的IP

[root@localhost ~]$ ansible web -m setup -a 'filter="*mem*"' --tree /tmp/facts

5.15 user 模块

该模块主要是用来管理用户账号。

[root@localhost ~]$ ansible web -m user -a 'name=keer uid=11111'

常用选项:
	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
	
	
	

#使用bash shell添加用户haha,将组"管理员"和"开发人员"附加到用户组
[root@localhost ~]$ ansible web-nodes -m user -a "name=haha shell=/bin/bash groups=admins,developers append=yes"

#删除用户anhui
[root@localhost ~]$ ansible test -m user -a 'name=anhui remove=yes state=absent' 


#修改用户密码
---
- hosts: demo
  remote_user: root
  tasks:
  - name: change user passwd
    user: name={{ item.user }} password={{ item.password | password_hash('sha512') }}  update_password=always
    with_items:
        - { user: 'root', password: 'root' }

5.16 mount 模块

在远程受控节点上挂载文件系统。

[root@localhost ~]$ ansible test -m mount -a "path=/mnt/data src=/dev/sd0 fstype=ext4 ots=ro state=present"

常用选项:
	present: 开机挂载,仅将挂载配置写入/etc/fstab(不常用)
	mounted: 挂载设备,并将配置写入/etc/fstab
	unmounted: 卸载设备,不会清除/etc/fstab写入的配置
	absent: 卸载设备,会清理/etc/fstab写入的配置


#将受控节点的/dev/sd0设备挂载到/mnt/data目录上, 文件格式为ext4, 只读属性
[root@localhost ~]$ ansible web-nodes -m mount -a "path=/mnt/data src=/dev/sd0 fstype=ext4 ots=ro state=present"
 
#仅将挂载的配置写入/etc/fstab,并不会执行挂载操作
[root@localhost ~]$ ansible test -m mount -a "src=172.16.60.220:/data path=/data fstype=nfs opts=defaults state=present"
 
#临时挂载设备,并将挂载信息写入/etc/fstab
[root@localhost ~]$ ansible test -m mount -a "src=172.16.60.220:/data path=/data fstype=nfs opts=defaults state=mounted"
 
#临时卸载,不会清理/etc/fstab
[root@localhost ~]$ ansible test -m mount -a "src=172.16.60.220:/data path=/data fstype=nfs opts=defaults state=unmounted"
 
#卸载,不仅临时卸载,同时会清理/etc/fstab
[root@localhost ~]$ ansible test -m mount -a "src=172.16.60.220:/data path=/data fstype=nfs opts=defaults state=absent"

5.17 wait_for模块

当你利用service 启动tomcat,或数据库后,他们真的启来了么?这个你是否想确认下?
wait_for模块就是干这个的。

选项

  • connect_timeout
    连接的超时时间,默认是5秒。
  • delay
    开始轮询之前等待的秒数,默认是0。
  • exclude_hosts
    与state=drained一起使用。用于指定,在寻找活跃的TCP链接的时候,要忽略的主机或IP列表。
  • host
    要等待的 可解析的主机名 或 IP地址。
    path
    在继续之前,文件系统上必须存在的文件的路径。
  • port
    要轮询的端口。
  • search_regex
    用于匹配文件或socket链接中的一个字符串。
  • state
    可以是present、started、stopped、absent、drained。
    当检查端口的时候,started会确保端口打开;stopped会确保端口关闭;drained会检查活跃的链接。
    当检查文件或搜索字符串的时候,present和started会确保文件或字符串存在。absent会确保文件不存在或被移除。
    (Choices: present, started, stopped, absent, drained)[Default: started]
  • timeout
    等待的超时时间。默认是300秒。

例子

wait_for: port:8000 delay=10
等待8000端口打开,每10秒检查一次。超时时间是300秒。

wait_for: host=0.0.0.0 port=8000 delay=10 state=drained
等待所有本地IP上的8000端口,关闭活跃连接。每10秒检查一次,超时时间是300秒。

wait_for: host=0.0.0.0 port=8000 state=drained exclude_hosts=10.2.1.2,10.2.1.3
等待所有本地IP上的8000端口,关闭活跃的连接。忽略来自10.2.1.2和10.2.1.3上的连接。超时时间是300秒。

wait_for: path=/tmp/foo
一直等到/tmp/foo这个文件存在。

wait_for: path=/tmp/foo search_regex=completed
一直等到字符串completed出现在文件/tmp/foo中。

wait_for: path=/var/lock/file.lock state=absent
一直等到lock文件被删除。

wait_for: path=/proc/3466/status state=absent
一直等到进程结束,并且pid被销毁。

local_action: wait_for port=22 host="{{ ansible_ssh_host | default(inventory_hostname) }}" search_regex=OpenSSH delay=10
等待22端口被打开,并且包含字符串OpenSSH。并且不确保inventory_hostname是可解析的。每10秒检查一次,超时时间是300秒。

六、playbook

  Playbooks是Ansible的配置,部署和编排语言。他们可以描述您希望在远程机器做哪些事。使用易读的YAML格式组织Playbook。

  playbook是由一个或多个play组成的列表,play的主要功能在于将事先归并为一组的主机装扮成事先通过ansible中的task定义好的角色。从根本上来讲,所谓的task无非是调用ansible的一个module。将多个play组织在一个playbook中,即可以让它们联合起来按事先编排的机制完成某一任务

6.1 playbook核心元素

  • Hosts 执行的远程主机列表
  • Tasks 任务集
  • Varniables 内置变量或自定义变量在playbook中调用
  • Templates 模板,即使用模板语法的文件,比如配置文件等
  • Handlers 和notity结合使用,由特定条件触发的操作,满足条件方才执行,否则不执行
  • tags 标签,指定某条任务执行,用于选择运行playbook中的部分代码。
  • remote_user:在远程主机以哪个用户身份执行;

6.2 playbook基本语法

playbook使用yaml语法格式,后缀可以是yaml,也可以是yml。

[root@localhost ~]$ vim test.yaml
---      #表示文档开始
- hosts: test       # "- "表示一个块序列的节点,注意:横杠后面有空格,可以写主机名,主机组名,多个使用逗号隔开
  remote_user: root      #指定在进行远程操作时使用root用户进行操作
  tasks:       #使用tasks关键字指明要进行操作的任务列表,之后的行都属于tasks键值对中的值。
  - name: Ping  #每个任务都以"- "开头,每个任务都有自己的名字,任务名使用name关键字进行指定
    ping:         #ansible模块
  - name: make directory test  #第二个任务使用file模块,使用file模块时,指定了path参数与state参数的值。
    file:     #ansible模块
       path: /data/test   #模块的参数
       state: directory
	   
	   
	   
	   
---                             #标记文件的开始
- hosts: webservers             #指定该playbook在哪个服务器上执行
  vars:                         #表示下面是定义的变量,
    http_port: 80               #变量的形式,key: value,这里http_port是变量名,80是值
    max_clients: 200
  remote_user: root             #指定远程的用户名,这里缩进和vars保持了一致,说明变量的代码块已经结束。
  tasks:                        #下面构成playbook的tasks,每个task都有 - name: 开始,name指定该任务的名称。
  - name: ensure apache is at the latest version  #指定该任务的名称。
    yum: pkg=httpd state=latest                   #yum说明要是用的模板名称,后面指定对应的参数,这两行结合起来就相当于一个shell命令。

  - name: write the apache config file            #每个task之间可以使用空行来做区分。
    template: src=/srv/httpd.j2 dest=/etc/httpd.conf

#需要说明的是缩进的意义和python中缩进的意义是一样,是来区分代码块的。

检测语法

[root@localhost ~]$ ansible-playbook  --syntax-check  /path/to/playbook.yaml

测试运行

[root@localhost ~]$ ansible-playbook -C /path/to/playbook.yaml

运行

[root@localhost ~]$ ansible-playbook  /path/to/playbook.yaml

示例:Playbook 创建用户

[root@localhost ~]$ vim sysuser.yml
---
- hosts: all
  remote_user: root

  tasks:
    - name: create mysql user
      user: name=mysql system=yes uid=36
    - name: create a group
      group: name=httpd system=yes

Playbook示例 安装nginx服务

[root@localhost ~]$ vim nginx.yml
- hosts: all
  remote_user: root

  tasks:
    - name: add group nginx
      user: name=nginx state=present
    - name: add user nginx
      user: name=nginx state=present group=nginx
    - name: Install Nginx
      yum: name=nginx state=present
    - name: Start Nginx
      service: name=nginx state=started enabled=yes

tags: 添加标签

可以指定某一个任务添加一个标签,添加标签以后,想执行某个动作可以做出挑选来执行
多个动作可以使用同一个标签

示例:httpd.yml

- hosts: websrvs
  remote_user: root
  
  tasks:
    - name: Install httpd
      yum: name=httpd state=present
      tags: install 
    - name: Install configure file
      copy: src=files/httpd.conf dest=/etc/httpd/conf/
      tags: conf
    - name: start httpd service
      tags: service
      service: name=httpd state=started enabled=yes

ansible-playbook -t install,conf httpd.yml   指定执行install,conf 两个标签

6.3 handlers

handlers和notify结合使用触发条件
Handlers 实际上就是一个触发器是task列表,这些task与前述的task并没有本质上的不同,用于当关注的资源发生变化时,才会采取一定的操作

Notify此action可用于在每个play的最后被触发,
这样可避免多次有改变发生时每次都执行指定的操作,仅在所有的变化发生完成后一次性地执行指定操作。
在notify中列出的操作称为handler,也即notify中调用handler中定义的操作

在系统中,我们修改了服务器的配置文件,这时候就需要重启操作服务,就可以使用到handlers。配合 notify使用

---
- hosts: control-node
  remote_user: root
  vars:
    - pkg: httpd
    - name: template configuration file
      template: src=template.j2 dest=/etc/foo.conf  #修改了配置文件然后依次启动memcached和apache服务。
        notify:                               #使用notify来声明引用handlers。
         - restart memcached
         - restart apache
    
  handlers:                               #下面定义了两个handlers
    - name: restart memcached
      service:  name=memcached state=restarted
    - name: restart apache
      service: name=apache state=restarted

在使用handlers的过程中,有以下几点需要注意:

  1. handlers只有在其所在的任务被执行时,都会被运行;
  2. handlers只会在Play的末尾运行一次;如果想在一个Playbook的中间运行handlers,则需要使用meta模块来实现,例如:- meta: flush_handlers。
  3. 如果一个Play在运行到调用handlers的语句之前失败了,那么这个handlers将不会被执行。我们可以使用mega模块的–force-handlers选项来强制执行handlers,即使在handlers所在Play中途运行失败也能执行。

6.4 register 和when

register 用于注册一个变量,保存命令的结果(shell或command模块),这个变量可以在后面的task、when语句或模板文件中使用

- shell: /bin/pwd
  register: pwd_result
debug:
    #msg: "{{ pwd_result }}"   # 输出全部信息
    #msg: "{{ pwd_result.cmd }}"   # 引用方式一
    msg: "{{ pwd_result['stdout_lines'] }}"  # 引用方式二

when 相当于shell脚本里的if 判断,when语句就是用来实现这个功能的,它是一个jinja2的语法,但是不需要双大括号,用法很简单

- name: echo date  #执行了一个 date 命令,register 关键字将 date 命令的输出存储到 date_output 变量名
  command: date 
  register: date_output 

 - name: echo date_output   #用 when 对关键字对分析后的进行判断,如果匹配,则执行这个 task,不匹配就不执行
   command: echo "30"
   when: date_output.stdout.split(' ')[2] == "30"

这里第 1 个 task 是执行了一个 date 命令,register 关键字将 date 命令的输出存储到 date_output 变量名。第 2 个 task 对输出进行分析,并使用 when 对关键字对分析后的进行判断,如果匹配,则执行这个 task,不匹配就不执行。这里要重点说下的,因为 register 获取到的输出内容都是字符串,而 ansible 又是 python 写的,你可以使用 python 字符串的方法对其做处理,比如本文中使用的 split,还可以使用 find 方法。

示例:

tasks:
  - name: "shutdown RedHat flavored systems"
    shell: /sbin/shutdown -h now
    when: ansible_os_family == "RedHat"  #当系统属于红帽系列,执行shell模块

6.5 循环

标准循环关键字:”with_items
对迭代项的引用,固定变量名为"item”,使用with_item属性给定要迭代的元素

[root@localhost ~]$ cat xh.yml 
---
- hosts: all
  gather_facts: no
  tasks:
    - name: dispaly list
      debug: msg="{{item}}"
      with_items:
        - one
        - two
        - three
        - four
 
[root@localhost ~]$ ansible-playbook -i hosts xh.yml 
 
PLAY [all] *************************************************************************************************************
TASK [dispaly xunhuan] *************************************************************************************************
ok: [192.168.52.129] => (item=one) => {
    "changed": false, 
    "item": "one", 
    "msg": "one"
}
ok: [192.168.52.129] => (item=two) => {
    "changed": false, 
    "item": "two", 
    "msg": "two"
}
ok: [192.168.52.129] => (item=three) => {
    "changed": false, 
    "item": "three", 
    "msg": "three"
}
ok: [192.168.52.129] => (item=four) => {
    "changed": false, 
    "item": "four", 
    "msg": "four"
}

安装一堆软件包。

---
    - hosts: localhost
      tasks: 
        - yum: name="{{item}}" state=installed
          with_items: 
            - pkg1
            - pkg2
            - pkg3

它会一个一个迭代到特殊变量"{{item}}"处。

loop等价于with_list,从名字上可以知道它是遍历数组(列表)的,所以在loop指令中,每个元素都以列表的方式去定义。列表有多少个元素,就循环执行file模块多少次,每轮循环中,都会将本次迭代的列表元素保存在控制变量 item中。

安装多个软件

tasks:
  - name: "Install Packages"
    yum: name={{ item }}  state=latest
    loop:
      - httpd
      - mysql-server
      - php

6.6 模板templates

Jinja2语言,使用字面量,有下面形式
字符串:使用单引号或双引号
数字:整数,浮点数
列表:[item1, item2, …]
元组:(item1, item2, …)
字典:{key1:value1, key2:value2, …}
布尔型:true/false
算术运算:+, -, *, /, //, %, **
比较操作:==, !=, >, >=, <, <=
逻辑运算:and,or,not
流表达式:For,If,When

6.6.1 template 的使用

templates是ansible的一个模块,其功能是根据模板文件动态生成配置文件,templates文件必须存放于templates目录下,且命名为".j2"结尾,yaml/yml文件需要和templates目录平级,这样我们在yml文件中调用模板的时候,就不需要写模板文件的路径,否则需要描述模板文件的路径,因为template模块会自动去找templates目录下的模板文件

./
├── temnginx.yml
└── templates
└── nginx.conf.j2

6.6.2 template示例

示例:利用template 同步nginx配置文件
准备templates/nginx.conf.j2文件

vim temnginx.yml
- hosts: websrvs
  remote_user: root
  
  tasks:
    - name: template config to remote hosts
      template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf

ansible-playbook temnginx.yml

for循环使用

{% for vhost in nginx_vhosts %}
server {
listen {{ vhost.listen }}
}
{% endfor %}

if单分支选择使用

{% if vhost.server_name is defined %}
    server_name {{ vhost.server_name }}
{% endif %}

if多分支选择使用

{%if vhost.port is undefined %}
    http_port=80
{%elif vhost.port == 81%}
    http_port=81
{%else%}
    http_port = 83
{%endif%}

单行注释

{#% for i in list %#}

6.7 roles

6.7.1 Roles介绍

ansible自1.2版本引入的新特性,用于层次性、结构化地组织playbook。roles能够根据层次型结构自动装载变量文件、tasks以及handlers等。要使用roles只需要在playbook中使用include指令引入即可。简单来讲,roles就是通过分别将变量、文件、任务、模板及处理器放置于单独的目录中,并可以便捷的include它们的一种机制。角色一般用于基于主机构建服务的场景中,但也可以是用于构建守护进程等场景中。主要使用场景代码复用度较高的情况下。

6.7.2 Roles目录结构

ansible 详解_第3张图片

各目录含义解释

roles:          <--所有的角色必须放在roles目录下,这个目录可以自定义位置,默认的位置在/etc/ansible/roles
  project:      <---具体的角色项目名称,比如nginx、tomcat、php
    files:     <--用来存放由copy模块或script模块调用的文件。
    templates: <--用来存放jinjia2模板,template模块会自动在此目录中寻找jinjia2模板文件。
    tasks:     <--此目录应当包含一个main.yml文件,用于定义此角色的任务列表,此文件可以使用include包含其它的位于此目录的task文件。
      main.yml
    handlers:  <--此目录应当包含一个main.yml文件,用于定义此角色中触发条件时执行的动作。
      main.yml
    vars:      <--此目录应当包含一个main.yml文件,用于定义此角色用到的变量。
      main.yml
    defaults:  <--此目录应当包含一个main.yml文件,用于为当前角色设定默认变量。
      main.yml
    meta:      <--此目录应当包含一个main.yml文件,用于定义此角色的特殊设定及其依赖关系。
      main.yml




roles/example_role/files/             所有文件,都将可存放在这里
roles/example_role/templates/         所有模板都存放在这里
roles/example_role/tasks/main.yml:   主函数,包括在其中的所有任务将被执行
roles/example_role/handlers/main.yml:所有包括其中的 handlers 将被执行
roles/example_role/vars/main.yml:    所有包括在其中的变量将在roles中生效
roles/example_role/meta/main.yml:    roles所有依赖将被正常登入

6.7.3 Roles示例

通过ansible roles安装配置httpd服务,此处的roles使用默认的路径/etc/ansible/roles

#在ansible目录下面,建立roles目录
#修改配置文件,使系统能够读取roles目录
[root@ansible ~]$ cat /etc/ansible/ansible.cfg | grep roles
# additional paths to search for roles in, colon separated
#roles_path    = /etc/ansible/roles  #roles默认路径
# by default, variables from roles will be visible in the global variable

创建role的步骤
(1) 创建以roles命名的目录
(2) 在roles目录中分别创建以各角色名称命名的目录,如webservers等
(3) 在每个角色命名的目录中分别创建files、handlers、meta、tasks、templates和vars目录;
用不到的目录可以创建为空目录,也可以不创建
(4) 在playbook文件中,调用各角色

实验: 创建httpd角色
1> 创建roles目录
   mkdir roles/{httpd,mysql,redis}/tasks -pv
   mkdir  roles/httpd/{handlers,files}
查看目录结构
tree roles/
    roles/
    ├── httpd
    │   ├── files
    │   ├── handlers
    │   └── tasks
    ├── mysql
    │   └── tasks
    └── redis
        └── tasks
2> 创建目标文件
   cd roles/httpd/tasks/
   touch install.yml config.yml service.yml
3> vim install.yml
   - name: install httpd package
     yum: name=httpd
     
   vim config.yml
   - name: config file  
     copy: src=httpd.conf dest=/etc/httpd/conf/ backup=yes 
   
   vim service.yml
   - name: start service 
     service: name=httpd state=started enabled=yes
     
4> 创建main.yml主控文件,调用以上单独的yml文件,
   main.yml定义了谁先执行谁后执行的顺序
   vim main.yml
   - include: install.yml
   - include: config.yml
   - include: service.yml
   
5> 准备httpd.conf文件,放到httpd单独的文件目录下
   cp /app/ansible/flies/httpd.conf ../files/
   
6> 创建一个网页
   vim flies/index.html
   

welcome to weixiaodong home <\h1> 7> 创建网页的yml文件 vim tasks/index.yml - name: index.html copy: src=index.html dest=/var/www/html 8> 将网页的yml文件写进mian.yml文件中 vim mian.yml - include: install.yml - include: config.yml - include: index.yml - include: service.yml 9> 在handlers目录下创建handler文件mian.yml vim handlers/main.yml - name: restart service httpd service: name=httpd state=restarted 10> 创建文件调用httpd角色 cd /app/ansidle/roles vim role_httpd.yml --- # httpd role - hosts: appsrvs remote_user: root roles: #调用角色 - role: httpd 11> 查看目录结构 tree . httpd ├── files │ ├── httpd.conf │ └── index.html ├── handlers │ └── main.yml └── tasks ├── config.yml ├── index.yml ├── install.yml ├── main.yml └── service.yml 12> ansible-playbook role_httpd.yml

1)创建目录

[root@ansible ~]$ cd /etc/ansible/roles/
# 创建需要用到的目录
[root@ansible roles]$ mkdir -p httpd/{handlers,tasks,templates,vars}
[root@ansible roles]$ cd httpd/
[root@ansible httpd]$ tree .
.
├── handlers
├── tasks
├── templates
└── vars

4 directories, 0 file

2)变量文件准备vars/main.yml

[root@ansible httpd]$ vim vars/main.yml
PORT: 8088        #指定httpd监听的端口
USERNAME: www     #指定httpd运行用户
GROUPNAME: www    #指定httpd运行组

3)配置文件模板准备templates/httpd.conf.j2

# copy一个本地的配置文件放在templates/下并已j2为后缀
[root@ansible httpd]$ cp /etc/httpd/conf/httpd.conf templates/httpd.conf.j2

# 进行一些修改,调用上面定义的变量
[root@ansible httpd]$ vim templates/httpd.conf.j2
Listen {{ PORT }} 
User {{ USERNAME }}
Group {{ GROUPNAME }}

4)任务剧本编写,创建用户、创建组、安装软件、配置、启动等

# 创建组的task
[root@ansible httpd]$ vim tasks/group.yml
- name: Create a Startup Group
  group: name=www gid=60 system=yes

# 创建用户的task
[root@ansible httpd]$ vim tasks/user.yml
- name: Create Startup Users
  user: name=www uid=60 system=yes shell=/sbin/nologin

# 安装软件的task
[root@ansible httpd]$ vim tasks/install.yml
- name: Install Package Httpd
  yum: name=httpd state=installed

# 配置软件的task
[root@ansible httpd]$ vim tasks/config.yml
- name: Copy Httpd Template File
  template: src=httpd.conf.j2 dest=/etc/httpd/conf/httpd.conf
  notify: Restart Httpd

# 启动软件的task
[root@ansible httpd]$ vim tasks/start.yml
- name: Start Httpd Service
  service: name=httpd state=started enabled=yes

# 编写main.yml,将上面的这些task引入进来
[root@ansible httpd]$ vim tasks/main.yml
- include: group.yml
- include: user.yml
- include: install.yml
- include: config.yml
- include: start.ym

5)编写重启httpd的handlers,handlers/main.yml

[root@ansible httpd]$ vim handlers/main.yml
# 这里的名字需要和task中的notify保持一致
- name: Restart Httpd
  service: name=httpd state=restarted

6)编写主的httpd_roles.yml文件调用httpd角色

[root@ansible httpd]$ cd ..
[root@ansible roles]$ vim httpd_roles.yml
---
- hosts: all
  remote_user: root
  roles:
    - role: httpd        #指定角色名称

7)整体的一个目录结构查看

[root@ansible roles]$ tree .
.
├── httpd
│   ├── handlers
│   │   └── main.yml
│   ├── tasks
│   │   ├── config.yml
│   │   ├── group.yml
│   │   ├── install.yml
│   │   ├── main.yml
│   │   ├── start.yml
│   │   └── user.yml
│   ├── templates
│   │   └── httpd.conf.j2
│   └── vars
│       └── main.yml
└── httpd_roles.yml

5 directories, 10 files

8)测试playbook语法是否正确

[root@ansible roles]$ ansible-playbook -C httpd_roles.ym

9)上面的测试没有问题,正式执行playbook

[root@ansible roles]$ ansible-playbook httpd_roles.ym

你可能感兴趣的:(Linux,linux,服务器,运维,经验分享,程序人生)