运维自动化之ansible--(playbook模式)
一、Ansible Playbook简介
playbook是ansible用于配置,部署,和管理被控节点的剧本。
通过playbook的详细描述,执行其中的一系列tasks,可以让远端主机达到预期的状态。playbook就像Ansible控制器给被控节点列出的的一系列to-do-list,而被控节点必须要完成。也可以这么理解,playbook 字面意思,即剧本,现实中由演员按照剧本表演,在Ansible中,这次由计算机进行表演,由计算机安装,部署应用,提供对外服务,以及组织计算机处理各种各样的事情。
二、Ansible playbook使用场景
使用ad-hoc命令可以方便的执行一些简单的任务来解决问题,但是有时一个设施过于复杂,需要大量的操作时候,执行的ad-hoc命令是不适合的,这时最好使用playbook。
就像执行shell命令与写shell脚本一样,也可以理解为批处理任务,不过playbook有自己的语法格式。
使用playbook你可以方便的重用这些代码,可以移植到不同的机器上面,像函数一样,最大化的利用代码。在你使用Ansible的过程中,你也会发现,你所处理的大部分操作都是编写playbook。可以把常见的应用都编写成playbook,之后管理服务器会变得十分简单。
三、Ansible playbook格式
playbook由YMAL语言编写。YAML参考了其他多种语言,包括:XML、C语言、Python、Perl以及电子邮件格式RFC2822。
YMAL格式是类似于JSON的文件格式,便于人理解和阅读,同时便于书写。以下为playbook常用到的YMAL格式。
①文件的第一行应该以 ”—” (三个连字符,无空格)开始,表明YMAL文件的开始。
②在同一行中,#之后的内容表示注释,类似于shell,python和ruby。
③YMAL中的列表元素以”-”开头然后紧跟着一个空格,后面为元素内容。就像这样- apple
④[ “apple”, “banana”, “orange” ] 同一个列表中的元素应该保持相同的缩进。否则会被当做错误处理。
⑤play中hosts,variables,roles,tasks等对象的表示方法都是键值中间以”:”分隔,”:”后面还要增加一个空格。
house:
family: { name: Doe, parents: [John, Jane], children: [Paul, Mark, Simone] }
address: { number: 34, street: Main Street, city: Nowheretown, zipcode: 12345 }
⑥剧本以.yml后缀
四、在mysql.yml剧本中,主要由三个部分组成
①hosts部分:使用hosts指示使用哪个主机或主机组来运行下面的tasks,每个playbook都必须指定hosts,hosts也可以使用通配符格式。主机或主机组在inventory清单中指定,可以使用系统默认的/etc/ansible/hosts,也可以自己编辑,在运行的时候加上-i选项,指定清单的位置即可。在运行清单文件的时候,-list-hosts选项会显示哪些主机将会参与执行task的过程中。
②remote_user:指定远端主机中的哪个用户来登录远端系统,在远端系统执行task的用户,可以任意指定,也可以使用sudo,但是用户必须要有执行相应task的权限。
③tasks:指定远端主机将要执行的一系列动作。tasks的核心为ansible的模块,前面已经提到模块的用法。tasks包含name和要执行的模块,name是可选的,只是为了便于用户阅读,不过还是建议加上去,模块是必须的,同时也要给予模块相应的参数。
五、执行有三个步骤:
1、收集facts
2、执行tasks
3、报告结果
示例:安装samba服务并启动
vim /etc/ansible/smb.yml
---
- hosts: web
remote_user: root
tasks:
- name: yum install samba
yum: name=samba state=latest
- name: start smb
service: name=smb state=started
tags: startsmb #标记此start smb任务
执行:ansible-playbook smb.yml
六、Playbook的核心元素:
Hosts:主机
Tasks:任务列表
Variables 变量
Templates:包含了模板语法的文本文件;
Handlers:由特定条件触发的任务;
Playbooks配置文件的基础组件:
Hosts:运行指定任务的目标主机;
remoute_user: 在远程主机上执行任务的用户;
sudo_user:sudo权限的用户
tasks:任务列表
1、模块,模块参数格式:
(1) action: module arguments
(2) module: arguments
注意:shell和command模块后面直接跟命令,而非key=value类的参数列表;
(1) 某任务的状态在运行后为changed时,可通过“notify”通知给相应的handlers;
(2) 任务可以通过“tags“打标签,而后可在ansible-playbook命令上使用-t指定进行调用;
示例:
vim /etc/ansible/nginx.yml
---
- hosts: web
remote_user: root
tasks:
- name: yum install nginx #安装nginx
yum: name=nginx state=latest
- name:copy nginx.conf #拷贝配置文件
copy: src=/etc/nginx/nginx.conf dest=/etc/nginx/nginx.conf backup=yes
notify: reload #会触发handlers中名字为reload的任务
tags: reloadnginx
- name: start nginx #启动nginx服务
service: name=nginx state=started
tags: startnginx
handlers:
- name: reload #重载配置
service: name=nginx state=reloaded
执行:ansible-playbook nginx.yml -vv
修改配置文件内容之后执行时调用标签ansible-playbook nginx.yml -vv -t reloadnginx,就会跳过安装步骤直接重载配置文件并启动服务
2、variables:变量
(1) facts:可直接调用;
注意:可使用setup模块直接获取目标主机的facters;
(2) 用户自定义变量:
(a) ansible-playbook命令的命令行中的
-e VARS, --extra-vars=VARS
(b) 在playbook中定义变量的方法:
vars:
- var1: value1
- - var2: value2
(3) 通过roles传递变量;
(4) Host Inventory
(a) 用户自定义变量
(i) 向不同的主机传递不同的变量;
IP/HOSTNAME varaiable=value var2=value2
(ii) 向组中的主机传递相同的变量;
[groupname:vars]
variable=value
比如:向web组传递变量rpmname=samba
[web]
172.17.251.188
172.17.250.209
[web:vars]
rpmname=samba
示例:使用变量rpmname来代替服务名
vim /etc/ansible/nginx.yml
---
- hosts: web
remote_user: root
vars:
- rpmname: nginx
tasks:
- name: yum install {{ rpmname }} #安装{{ rpmname }}
yum: name={{ rpmname }} state=latest
- name: copy {{ rpmname }}.conf #拷贝配置文件
copy: src=/etc/{{ rpmname }}/{{ rpmname }}.conf dest=/etc/{{ rpmname }}/{{ rpmname }}.conf backup=yes
notify: reload #会触发handlers中名字为reload的任务
tags: reload{{ rpmname }}
- name: start {{ rpmname }} #启动{{ rpmname }}服务
service: name={{ rpmname }} state=started
tags: start{{ rpmname }}
handlers:
- name: reload #重载配置
service: name={{ rpmname }} state=reloaded
运行:ansible-playbook nginx.yml
3、模板:模板文件以.j2后缀
示例:
编辑模板配置文件
cp /etc/nginx/nginx.conf /etc/nginx/nginx.conf.j2
vim /etc/nginx/nginx.conf.j2
worker_processes {{ ansible_processor_vcpus }}; #引用内置变量获得cpu颗数
listen {{ nginxport }}; #自定义变量
编辑剧本:vim /etc/ansible/nginx.yml
---
- hosts: web
remote_user: root
vars:
- rpmname: nginx
nginxport: 8888 #定义nginx监听端口为8888
tasks:
- name: yum install {{ rpmname }} #安装{{ rpmname }}
yum: name={{ rpmname }} state=latest
- name: copy {{ rpmname }}.conf #拷贝配置文件
template: src=/etc/{{ rpmname }}/{{ rpmname }}.conf.j2 dest=/etc/{{ rpmname }}/{{ rpmname }}.conf backup=yes
notify: reload #会触发handlers中名字为reload的任务
tags: reload{{ rpmname }}
- name: start {{ rpmname }} #启动{{ rpmname }}服务
service: name={{ rpmname }} state=started
tags: start{{ rpmname }}
handlers:
- name: reload #重载配置
service: name={{ rpmname }} state=reloaded
运行:ansible-playbook nginx.yml -t reloadnginx
查看是否开启端口8888:ansible web -m shell -a 'ss -ntlp|grep "nginx"'
4、循环:迭代,即需要重复执行的任务。
对迭代项的引用,固定变量名为”item“,而后,要在task中使用with_items给定要迭代的元素列表:
比如:vim /etc/ansible/items.yml
---
- hosts: web
remote_user: root
tasks:
- name: install packages #安装with_items中列出的包
yum: name={{ item }} state=latest
with_items:
- vsftpd
- php
- php-mysql
执行:ansible-playbook items.yml 就会安装列表中的包
5、Ansible playbook字典:实现一一对应
示例:vim adduser.yml
---
- hosts: web
remote_user: root
tasks:
- name: add some groups #添加一些组
group: name={{ item }} state=present
with_items:
- group11
- group12
- group13
- name: add some users #创建用户到对应的组
user: name={{ item.name }} group={{ item.group }} state=present
with_items:
- { name: 'user11', group: 'group11' }
- { name: 'user12', group: 'group12' }
- { name: 'user13', group: 'group13' }
执行:ansible-playbook adduser.yml 就会创建对应的用户及组
6、角色定制:roles
对于以上所有的方式有个弊端就是无法实现复用假设在同时部署Web、db、ha 时或不同服务器组合不同的应用就需要写多个yml文件。很难实现灵活的调用。
roles 用于层次性、结构化地组织playbook。roles 能够根据层次型结构自动装载变量文件、tasks以及handlers等。要使用roles只需要在playbook中使用include指令即可。简单来讲,roles就是通过分别将变量(vars)、文件(file)、任务(tasks)、模块(modules)及处理器(handlers)放置于单独的目录中,并可以便捷地include它们的一种机制。角色一般用于基于主机构建服务的场景中,但也可以是用于构建守护进程等场景中。
示例:定制三个角色(nginx、mysql、tomcat)
(1)、在roles目录下生成对应的目录结构
mkdir -pv /etc/ansible/roles/{nginx,mysql,tomcat}/{files,templates,vars,tasks,handlers,meta,default}
(2)、定义tasks/main.yml的配置文件.先将模板文件考到template目录下
cp /etc/nginx/nginx.conf.j2 ./roles/nginx/templates/
vim task/main.yml
- name: cp
copy: src=/etc/ansible/roles/nginx/files/nginx-1.10.2-1.el7.ngx.x86_64.rpm dest=/tmp/nginx-1.10.2- 1.el7.ngx.x86_64.rpm
- name: install
yum: name=/tmp/nginx-1.10.2-1.el7.ngx.x86_64.rpm state=latest
- name: conf
template: src=/etc/ansible/roles/nginx/templates/nginx.conf.j2 dest=/etc/nginx/nginx.conf
tags: nginxconf
notify: new conf to reload #触发名字为new conf to reload的handles执行
- name: start service
service: name=nginx state=started
(3)、修改变量文件vars/main.yml
添加变量nginxport: 8080
(4)、定义handlers文件handlers/main.yml
- name: new conf to reload
service: name=nginx state=reload
(5)、定义/etc/ansible/roles.yml的playbook文件
- hosts: web
remote_user: root
roles:
- nginx
运行剧本:ansible-playbook roles.yml
查看端口:ansible web -m shell -a 'ss -ntlp|grep "nginx"'
总结:ansible-playbook模式比较易于实现功能以及排错,除非是很简单的业务实现可以使用hoc模式,其他较复杂的场景一般都是playbook模式。