【前言】
上次说了ansible的任务模式之一:ad-hoc模式,然而这种模式只适合一些简单任务,但是当一个设施过于复杂,需要大量操作的时候,执行ad-hoc命令显然是费时费力的,这时就要使用ansible的另一种任务模式了—-playbook。
【playbook介绍】
playbook是ansible用于配置、部署和管理被控节点的剧本。
通过palybook的详细描述,执行其中的一系列tasks,可以让远端主机达到预期的状态。playbook就像ansible控制器给被控节点列出的一系列to-do-list,而被控节点必须要完成。
换个意思理解,playbook 字面意思,即剧本,现实中由演员按照剧本表演,在Ansible中,这次由计算机进行表演,由计算机安装,部署应用,提供对外服务,以及组织计算机处理各种各样的事情。
使用playbook你可以方便的重用这些代码,可以移植到不同的机器上面,像函数一样,最大化的利用代码。在你使用ansible的过程中,你会发现,你所处理的大部分操作都是编写playbook。可以把常见的应用都编写成playbook,之后管理服务器会变得十分简单。
【ansible playbook格式】
playbook由YAML语言编写。
YAMLL( /ˈjæməl/ )参考了其他多种语言,包括:XML、C语言、Python、Perl以及电子邮件格式RFC2822,Clark Evans在2001年5月在首次发表了这种语言,另外Ingy döt Net与OrenBen-Kiki也是这语言的共同设计者。
YMAL格式是类似于JSON的文件格式,便于人理解和阅读,同时便于书写。首先学习了解一下YMAL的格式,对我们后面书写playbook很有帮助。
以下为playbook常用到的YMAL格式:
1、文件的第一行应该以”- - -” (三个连字符)开始,表示YAML文件的开始。
2、在同一行中,#之后的内容表示注释,类似于shell,Python和ruby
3、YAML中的列表元素以” - ” 开头,然后紧跟着一个空格,后面为元素内容;同一个列表中的元素应该保持相同的缩进,否则会被当做错误处理。
4、不能空格和tab混用
5、区别大小写
6、一个完整的代码块功能需要最少元素包括name: task
使用ansible-playbook运行playbook文件,得到输出信息,输出内容为JSON格式,并且由不同颜色组成,便于识别。一般而言:
绿色代表执行成功,系统保持原样
黄色代表系统状态发生改变
红色代表执行失败,显示错误输出。
在/etc/ansible/ansible.cfg文件中有所定义:
[root@centos7 ansible]# vim /etc/ansible/ansible.cfg
[colors]
#highlight = white
#verbose = blue
#warn = bright purple
#error = red
#debug = dark gray
#deprecate = purple
#skip = cyan
#unreachable = red
#ok = green
#changed = yellow
#diff_add = green
#diff_remove = red
#diff_lines = cyan
playbook的核心元素:
hosts:主机
tasks:任务列表
variables
templates:包含了模板语法的文本文件
handlers:由特定条件触发的任务
playbooks配置文件的基础组件:
hosts:运行指定任务的目标主机
remote_user:在远程主机上执行任务的用户
sudo_user:
tasks:任务列表
模块,模块参数;
格式:
(1) action: module arguments
(2) module: arguments
注意:shell和command模块后面直接跟命令,而非key=value类的参数列表;
(1) 某任务的状态在运行后为changed时,可通过“notify”通知给相应的handlers;
(2) 任务可以通过“tags“打标签,而后可在ansible-playbook命令上使用-t指定进行调用;
【handlers】
用于当关注的资源发生变化时采取一定的操作;
“notify” 这个action可用于在每个play的最后被触发,这样可以避免多次有改变发生时每次 都执行hiding的操作,取而代之仅在所有的变化发生完成后一次性地执行指定操作;
在notify中列出的操作称为handler也即notify中调用handler中定义的操作;
[注意]:在notify中定义内筒一定要和task中定义的- name内容一样,这样才能达到触发的效果,否则会不生效。
tasks:
– name: TASK_NAME
module: arguments
notify: HANDLER_NAME
handlers:
– name: HANDLER_NAME
module: arguments
eg:
- name: deliver config
notify: restart nginx //要和handler中的name相同
handlers:
- name: restart nginx
service: name=nginx state=restarted
【variables】
(1)facts:可直接调用;
注意:可使用setup模块直接获取目标主机的facts
(2)用户自定义变量:
ansible-playbook 命令,命令行中的
-e VARS,–extra-vars=VARS
在playbook中定义变量的方法:
vars:
- var1: value1
- var2: value2
(3)通过roles传递变量
(4)host inventory
向不同的主机传递不同的变量
IP/HOSTNAME variables=value1 var2=value2
向组中的主机传递相同的变量
[groupname:vars]
variable=value
运行playbook:
(1)测试
ansible-playbook –check #只检测可能会发生的改变,但不真正执行操作
ansible-playbook –list-hosts #列出运行任务的主机
(2)直接运行
【templates模板】
文本文件,嵌套有脚本(使用模板编程语言编写)
Jinja2:Jinja2是python的一种模板语言,以Django的模板语言为原本
支持:
字符串:使用单引号或双引号;
数字:整数,浮点数;
列表:[item1, item2, …]
元组:(item1, item2, …)
字典:{key1:value1, key2:value2, …}
布尔型:true/false
算术运算:
+, -, , /, //, %, *
比较操作:
==, !=, >, >=, <, <=
逻辑运算:
and, or, not
条件测试:
when语句:在task中使用,jinja2的语法格式
tasks:
- name: install conf file to centos7
template: src=files/nginx.conf.c7.j2
when: ansible_distribution_major_version == "7"
- name: install conf file to centos6
template: src=files/nginx.conf.c6.j2
when: ansible_distribution_major_version == "6"
迭代with_items:需要重复执行的任务;
对迭代项的引用,固定变量名为”item“,而后要在task中使用with_items给定要迭代的元素列表;
eg:
- hosts: web
remote_user: root
tasks:
- name: install app
yum: name={{ item }} state=present //固定的变量名
with_items: //元素列表
- httpd
- php
with_items 字典:
- hosts: web
remote_user: root
tasks:
- name: add user
user: name={{ item.name }} groups={{ item.group }} //字典功能,可有多个值
with_items:
- { name: "aaa" , group: "natasha" } //为一组
- { name: "bbb" , group: "root"}
【角色定制roles】
对于以上所有的方式有个弊端就是无法实现复用假设在同时部署web、db、ha时或不能服务器组合不同的应用就需要写多个yml文件,这样就很难实现灵活的调用。
roles用于层次性、结构化地组织playbook。roles能够根据层次型结构自动装载变量文件、tasks以及handlers。要使用roles只需要在playbook中使用include指令即可。
简单来讲,roles就是通过分别将变量(vars)、文件(file)、任务(tasks)、模块(modules)及处理器(handlers)放置于单独的目录中,并可以便捷地include它们的一种机制。角色一般用于置于主机构建服务的场景中,但也可以是用于构建守护进程等场景中。
角色集合:
roles/
files/ :存储由copy或script等模块调用的文件;
tasks/ :此目录中至少应该有一个名为main.yml的文件,用于定义各task;其他的文件需要由main.yml进行包含调用;
handles/ :此目录中至少应该有一个名为main.yml的文件,用于定义各handler;其他的文件需要由main.yml进行包含调用;
vars/ :此目录中至少应该有一个名为main.yml的文件,用于定义各variable;其他的文件需要由main.yml进行包含调用;
templates/ :存储由template模块调用的模板文本;
meta/ :此目录中至少应该有一个名为main.yml的文件,定义当前角色的特殊设定及其依赖关系,其他的文件需要由main.yml进行包含调用;
default/ :此目录中至少应该有一个名为main.yml的文件,用于设定默认变量;
# cd /etc/ansible/roles/nginx
# tree
├── default #为当前角色设定默认变量时使用使用此目录
├── files #存储由copy或script等模块调用的文件
├── handlers #用于定义此角色用到的和handler;也可包含其它文件
├── meta #用于定义此角色的特殊设定及其依赖关系
├── tasks #其定义了此角色的任务列表;此文件可以使用include包含其它的位于此目录中的task文件
├── templates #template模块会自动在此目录中寻找Jinja2模板文件
└── vars #应当包含一个main.yml文件,用于定义此角色用到的变量
└── main.yml
【实现角色定制】
1、在/etc/ansible/roles下生成对应的目录结构:
mkdir -pv ./nginx/{files,templates,vars,tasks,handlers,meta,default}
2、进入roles/nginx目录下
3、定义tasks/main.yml 配置文件
# vim tasks/main.yml
- name: cp
copy: src=nginx-1.10.2-1.el7.ngx.x86_64.rpm dest=/app/nginx-1.10.2-1.el7.ngx.x86_64.rpm
#copy模块将nginx安装包推给主机节点
- name: install
yum: name=/app/nginx-1.10.2-1.el7.ngx.x86_64.rpm state=latest
#yum模块在主机节点上安装nginx服务
- name: conf
template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf
tags: nginxconf
notify: new conf to reload
#将nginx.conf.j2配置文件推给主机组
- name: start service
service: name=nginx state=started enabled=true
tags: startnginx
#service模块启动主机组上的nginx服务
4、定义nginx.conf.j2文件
# cp /etc/nginx/nginx.conf ./nginx.conf.j2
# vim nginx.conf.j2 #这里我们只自定义了监听端口一个变量
server {
listen {{ nginxport }};
5、修改变量文件
# vim vars/main.yml
nginxport: 9999
#该变量在服务器端的nginx.conf文件中有将端口定义为{{ nginxport }} ,因此这里需要给变量赋值。
6、定义handlers文件
# vim handlers/main.yml
- name: new conf to reload
service: name=nginx state=restarted
7、定义/etc/ansible/nginx.yml的playbook文件
# vim /etc/ansible/nginx.yml
- hosts: web
remote_user: root
roles:
- nginx
8、执行
# ansible-playbook nginx.yml
或者根据标签启动(自定义选择):
# ansible-playbook nginx.yml --tags startnginx
node:
[root@node1 ~]# cd /app/
[root@node1 app]# ls
nginx-1.10.2-1.el7.ngx.x86_64.rpm
[root@node1 app]# ss -ntl
State Recv-Q Send-Q Local Address:Port Peer Address:Port
LISTEN 0 128 *:9999 *:*
LISTEN 0 128 *:80 *:*
LISTEN 0 128 *:22 *:*
LISTEN 0 100 127.0.0.1:25 *:*
LISTEN 0 128 :::22 :::*
LISTEN 0 100 ::1:25 :::*
9999端口已经启动,证明上述所做角色定制已经成功~~~