六、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格式
1、格式简介
playbook由 YMAL语言编写。YAML( /ˈ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、文件的第一行应该以 "---" (三个连字符)开始,表明YMAL文件的开始。
2、在同一行中,#之后的内容表示注释,类似于shell,python和ruby。
3、YMAL中的列表元素以”-”开头然后紧跟着一个空格,后面为元素内容。
4、同一个列表中的元素应该保持相同的缩进。否则会被当做错误处理。
5、play 中 hosts,variables,roles,tasks等对象的表示方法都是键值中间以":"分隔表示,":"后面还要增加一个空格。
下面剧本就是给某台机子安装nginx
---
- hosts: 172.17.0.5
remote_user: root
tasks:
- name: copy grabber.py
copy: src=/tmp/grabber.py dest=/usr/lib/python2.7/site-packages/urlgrabber/ force=yes
- name: copy nginx.repo
copy: src=/etc/yum.repos.d/nginx.repo dest=/etc/yum.repos.d/ force=yes
- name: install nginx
yum: name=nginx state=present
- name: copy nginx.conf
copy: src=/root/default.conf dest=/etc/nginx/conf.d/
notify: reload
tags: reloadnginx
- name: start nginx service
shell: /usr/sbin/nginx
tags: startnginx
handlers:
- name: reload
shell: /usr/sbin/nginx -s reload
基于容器安装Nginx其实得看他有没有yum源,还有一些依赖包
我们的文件名称应该以.yml
结尾,像我们上面的例子就是mysql.yml
。其中,有三个部分组成:
host部分
:使用 hosts 指示使用哪个主机或主机组来运行下面的 tasks ,每个 playbook 都必须指定 hosts ,hosts也可以使用通配符格式。主机或主机组在 inventory 清单中指定,可以使用系统默认的/etc/ansible/hosts
,也可以自己编辑,在运行的时候加上-i
选项,指定清单的位置即可。在运行清单文件的时候,–list-hosts
选项会显示那些主机将会参与执行 task 的过程中。
remote_user
:指定远端主机中的哪个用户来登录远端系统,在远端系统执行 task 的用户,可以任意指定,也可以使用 sudo,但是用户必须要有执行相应 task 的权限。
tasks
:指定远端主机将要执行的一系列动作。tasks 的核心为 ansible 的模块,前面已经提到模块的用法。tasks 包含name
和要执行的模块
,name 是可选的,只是为了便于用户阅读,不过还是建议加上去,模块是必须的,同时也要给予模块相应的参数。
使用ansible-playbook运行playbook文件,得到如下输出信息,输出内容为JSON格式。并且由不同颜色组成,便于识别。一般而言
| 绿色代表执行成功,系统保持原样
| 黄色代表系统代表系统状态发生改变
| 红色代表执行失败,显示错误输出
2、核心元素
Playbook的核心元素:
Hosts
:主机组;
Tasks
:任务列表;
Variables
:变量,设置方式有四种;
Templates
:包含了模板语法的文本文件;
Handlers
:由特定条件触发的任务;
handlers
:任务,在特定条件下触发;接收到其它任务的通知时被触发;
(1) 某任务的状态在运行后为changed时,可通过“notify”通知给相应的handlers;
(2) 任务可以通过“tags“打标签,而后可在ansible-playbook命令上使用-t指定进行调用;
4、variables 部分
上文中,我们说到了variables
是变量,有四种定义方法,现在我们就来说说这四种定义方法:
① facts :可直接调用
上一篇中,我们有说到setup
这个模块,这个模块就是通过调用facts组件来实现的。我们这里的variables
也可以直接调用facts
组件。
具体的facters
我们可以使用setup
模块来获取,然后直接放入我们的剧本中调用即可。
ansible_all_ipv4_addresses:仅显示ipv4的信息 ---> [u'192.168.95.143']
ansible_eth0['ipv4']['address']:仅显示ipv4的信息 ---> eth0 的ip地址
ansible_devices:仅显示磁盘设备信息
ansible_distribution:显示是什么系统,例:centos,suse等
ansible_distribution_version:仅显示系统版本
ansible_machine:显示系统类型,例:32位,还是64位
ansible_eth0:仅显示eth0的信息
ansible_hostname:仅显示主机名
ansible_kernel:仅显示内核版本
ansible_lvm:显示lvm相关信息
ansible_memtotal_mb:显示系统总内存
ansible_memfree_mb:显示可用系统内存
ansible_memory_mb:详细显示内存情况
ansible_swaptotal_mb:显示总的swap内存
ansible_swapfree_mb:显示swap内存的可用内存
ansible_mounts:显示系统磁盘挂载情况
ansible_processor:显示cpu个数(具体显示每个cpu的型号)
ansible_processor_vcpus:显示cpu个数(只显示总的个数)
ansible_python_version:显示python版本
例如:批量修改主机 host 文件
---
- hosts: web
vars:
IP: "{{ ansible_eth0['ipv4']['address'] }}"
tasks:
- name: 将原有的hosts文件备份
shell: cp /etc/hosts /etc/hosts_bak
- name: 将ansible端的hosts复制到各自机器上
copy: src=/root/hosts dest=/etc/ force=yes owner=root group=root mode=0644
- name: 在新的hosts文件后面追加各自机器内网ip和hostname
lineinfile: dest=/etc/hosts line="{{ IP }} {{ ansible_hostname }}"
---
- hosts: web
vars:
IP: "{{ ansible_eth0['ipv4']['address'] }}"
DNS: "www.tianyun.com"
tasks:
- name: backup hosts
shell: cp /etc/hosts /etc/hosts_bak
- name: cp ansible hosts to node hosts
copy: src=/etc/hosts dest=/etc/hosts2 force=yes
- name: add ip and hostname to node hosts
lineinfile: dest=/etc/hosts2 line="{{ IP }} {{ ansible_hostname }} {{ DNS }}"
我们就使用全局替换把我们刚刚编辑的文件修改一下:
[root@server ansible]# vim nginx.yml
② 拷贝配置文件
我们想要在被监管的机器上安装什么服务的话,就直接在我们的server端上把该服务的配置文件拷贝到我们的
/tmp/
目录下。这样我们的剧本才能正常运行。
我们就以
keepalived
服务为例:
[root@server ansible]# cp /etc/keepalived/keepalived.conf /tmp/keepalived.conf
③ 运行剧本,变量由命令行传入
[root@server ansible]# ansible-playbook nginx.yml -e rpmname=keepalived
Ansible Inventory 内置参数
使用内置变量把用户名密码写在Inventory中,也就是/etc/ansible/hosts文件里,缺点就是暴露了账号密码,不安全。如果有多个主机需要使用同样的变量,可以用组变量的形式,书写格式如下:
[web]
192.168.100.10
192.168.100.11
192.168.100.12
[web:vars] #给名为webservers的组定义一个变量,:vars是固定格式
ansible_ssh_port=22
ansible_ssh_user='root'
ansible_ssh_pass='1234.com'
① 定义模板
我们直接把之前定义的/tmp/nginx.conf
改个名,然后编辑一下,就可以定义成我们的模板文件了:
[root@server ansible]# cd /tmp
[root@server tmp]# mv nginx.conf nginx.conf.j2
[root@server tmp]# vim nginx.conf.j2
worker_processes {{ ansible_processor_vcpus }};
listen {{ nginxport }};
② 修改剧本
我们现在需要去修改剧本来定义变量:
[root@server ansible]# vim nginx.yml
template 复制模板到目标文件,不能copy模块
8、角色订制:roles
① 简介
对于以上所有的方式有个弊端就是无法实现复用假设在同时部署Web、db、ha 时或不同服务器组合不同的应用就需要写多个yml文件。很难实现灵活的调用。
roles 用于层次性、结构化地组织playbook。roles 能够根据层次型结构自动装载变量文件、tasks以及handlers等。要使用roles只需要在playbook中使用include指令即可。简单来讲,roles就是通过分别将变量(vars)、文件(file)、任务(tasks)、模块(modules)及处理器(handlers)放置于单独的目录中,并可以便捷地include它们的一种机制。角色一般用于基于主机构建服务的场景中,但也可以是用于构建守护进程等场景中。
② 角色集合
角色集合:roles/
mysql/
httpd/
nginx/
files/:存储由copy或script等模块调用的文件;
tasks/:此目录中至少应该有一个名为main.yml的文件,用于定义各task;其它的文件需要由main.yml进行“包含”调用;
handlers/:此目录中至少应该有一个名为main.yml的文件,用于定义各handler;其它的文件需要由main.yml进行“包含”调用;
vars/:此目录中至少应该有一个名为main.yml的文件,用于定义各variable;其它的文件需要由main.yml进行“包含”调用;
templates/:存储由template模块调用的模板文本;
meta/:此目录中至少应该有一个名为main.yml的文件,定义当前角色的特殊设定及其依赖关系;其它的文件需要由main.yml进行“包含”调用;
default/:此目录中至少应该有一个名为main.yml的文件,用于设定默认变量;
③ 角色定制实例
1. 在roles目录下生成对应的目录结构
[root@server ansible]# cd roles/
[root@server roles]# ls
[root@server roles]# mkdir -pv ./{nginx,mysql,httpd}/{files,templates,vars,tasks,handlers,meta,default}
[root@server roles]# tree
.
├── httpd
│ ├── default
│ ├── files
│ ├── handlers
│ ├── meta
│ ├── tasks
│ ├── templates
│ └── vars
├── mysql
│ ├── default
│ ├── files
│ ├── handlers
│ ├── meta
│ ├── tasks
│ ├── templates
│ └── vars
└── nginx
├── default
├── files
├── handlers
├── meta
├── tasks
├── templates
└── vars
24 directories, 0 files
4. 修改变量文件
我们在模板中定义的变量,也要去配置文件中加上:
[root@server nginx]# vim vars/main.yml
nginxprot: 9999
5. 定义handlers文件
我们在配置文件中定义了notify
,所以我么也需要定义handlers
,我们来修改配置文件:
[root@server nginx]# vim handlers/main.yml
- name: new conf to reload
service: name=nginx state=restarted
6. 定义剧本文件
接下来,我们就来定义剧本文件,由于大部分设置我们都单独配置在了roles里面,所以,接下来剧本就只需要写一点点内容即可:
[root@server ansible]# vim roles.yml
- hosts: web
remote_user: root
roles:
- nginx
7. 启动服务
剧本定义完成以后,我们就可以来启动服务了:
[root@server ansible]# ansible-playbook roles.yml