Playbooks
playbook简介
1 playbook是什么?
Playbooks 是 Ansible的配置,部署,编排语言.他们可以被描述为一个需要希望远程主机执行命令的方案,或者一组IT程序运行的命令集合.
Playbooks 与 adhoc 相比,是一种完全不同的运用 ansible 的方式,是非常之强大的.
简单来说,playbooks 是一种简单的配置管理系统与多机器部署系统的基础, 非常适合于复杂应用的部署.
在playbook中我们可以编排有序的执行过程,甚至可以实现多组机器之间来回有序执行我们指定的任务!并且可以实现同步或异步的发起任务
在使用adhoc时,我们主要使用/usr/bin/ansible 程序执行任务,在使用playbook时,我们更多的是将任务别写在剧本文件当中,使用ansible-playbook命令读取执行任务
2 Playbook 语言的示例
Playbooks 的格式是YAML, playbook 由一个或多个 ‘plays’ 组成.它的内容是一个以 ‘plays’ 为元素的列表! 在 play 之中,一组机器被映射为定义好的角色.在 ansible 中,play 的内容,被称为 tasks,即任务.在基本层次的应用中,一个任务就是一个对 ansible 模块的调用
通过 playbook,可以编排步骤进行多机器的部署,比如在 webservers 组的所有机器上运行一定的步骤, 然后在 database server 组运行一些步骤,最后回到 webservers 组,再运行一些步骤,诸如此类.
下面有一个playbook的例子:
- hosts: webservers
vars:
http_port: 80
max_clients: 200
remote_user: root
tasks:- name: ensure apache is at the latest version
yum: pkg=httpd state=latest - name: write the apache config file
template: src=/srv/httpd.j2 dest=/etc/httpd.conf
notify:- restart apache
- name: ensure apache is running
service: name=httpd state=started
handlers:- name: restart apache
service: name=httpd state=restarted
playbook的基础
1 主机和用户
你可以为 playbook 中的每一个 play,去选择要操作的目标机器是哪些,以哪个用户身份去完成要执行的步骤
- name: restart apache
- name: ensure apache is at the latest version
- hosts: webservers
remote_user: root
我们也还可以在一个任务中定义自己的远程用户:
- hosts: webservers
remote_user: root
tasks:- name: test connection
ping:
remote_user: yourname
- name: test connection
也支持sudo的调用
- hosts: webservers
remote_user: yourname
sudo: yes
如果你需要在使用 sudo 时指定密码,可在运行 ansible-playbook 命令时加上选项 --ask-sudo-pass (-K)
2 Tasks 列表
每个play都包含一个task列表(任务列表),一个task在目标主机执行完毕后,才会执行下一个任务,需要大家明白的是,在同一个play当中,所有的主机都会收到接受到相同的指令,
每个 task 的目标在于执行一个模块(module), 通常是带有特定的参数来执行.在参数中可以使用变量
modules 具有”幂等”性,意思是如果你再一次地执行 moudle,moudle 只会执行必要的改动,只会改变需要改变的地方.所以重复多次执行 playbook 也很安全.
每一个 task 必须有一个名称 name,这样在运行 playbook 时,从其输出的任务执行信息中可以很好的辨别出是属于哪一个 task 的. 如果没有定义 name,‘action’ 的值将会用作输出信息中标记特定的 task.
下面是一种基本的task的定义
service 模块使用 key=value 格式的参数,这也是大多数 module 使用的参数格式:
tasks:
- name: make sure apache is running
service: name=httpd state=running
但是有两个特殊的模块shell模块和command模块,它们不是用key=value的格式,而是这样的:
tasks:
- name: disable selinux
command: /sbin/setenforce 0
使用shell模块和command模块我们需要考虑返回码的问题,若返回码不为0说明命令没有执行成功,那么模块执行的状态也为失败,任务可能就会终止,我们可以按如下执行来解决状态码的问题:
tasks: - name: run this command and ignore the result
shell: /usr/bin/somecommand || /bin/true
或者:
tasks: - name: run this command and ignore the result
shell: /usr/bin/somecommand
ignore_errors: True
练习:
- 请在ansible主机上创建主机webservers,请编写playbook,在webservers主机组中:
a) 安装httpd
b) 关闭防火墙和selinux
c) 启动httpd并设置为开机自启
d) 推送测试页面: hello playbook
3 变量定义
3.1 合法的变量名
在使用变量之前最好先知道什么是合法的变量名. 变量名可以为字母,数字以及下划线.变量始终应该以字母开头
3.2 在Inventory(清单文件)中定义变量
3.3 在playbook中定义变量
- hosts: webservers
vars:
http_port: 80
4 变量的引用
4.1 playbook中引用变量
我们可以在playbook文件中引用变量 - hosts: webservers
vars:
base_dir: /usr/local/nginx
shell: {{ base_dur }}/sbin/nignx
4.2 模板文件中引用变量
我们也可以通过template模块将变量引用到文件当中,Ansible允许你使用Jinja2模板系统在playbook中引用变量
例如:
我们创建文件file.j2,内容:
mysql name is {{ user_name }}
在playbook文件中定义变量:
- hosts: webservers
vars:
user_name: tom
tasks: - name: copy a fille to host
template: src=file.j2 dest=/root/
template常用于配置文件的推送,我们可以把一些常用的参数,例如nginx的监听地址,网站根目录,网站域名等!我们可以把这些参数都做成变量,然后在配置文件中引用,这样我们以后只需更改playbook文件中变量的值即可!增加了配置的灵活度
4.3 YAML陷阱
YAML语法要求如果值以{{ foo }}开头的话我们需要将整行用双引号包起来.这是为了确认你不是想声明一个YAML字典!
例子:
错误的写法:
- hosts: app_servers
vars:
app_path: {{ base_path }}/22
正确的写法:
- hosts: app_servers
vars:
app_path: “{{ base_path }}/22”
4.4 使用Facts获取的信息
在ansible中有些自带的变量,不需要用户定义,直接引用就可以
Facts通过访问远程系统获取相应的信息,比如像查看远程主机的ip地址和系统版本,那么我们可以执行:
ansible hostname -m setup
不过这样执行会返回非常多的变量数据!这里面的变量我们都可以直接引用!
例如{{ ansible_hostname }}就可以获取远程主机的主机名,{{ ansible_eth0[“ipv4”][“address”] }}获取eth0的ipv4的ip地址,当然这些变量我们也可以通过template模块,直接在模板文件中引用
4.5 变量文件分割
我们有时可能会有敏感数据存放到playbook当中的情况,比如账号密码等!那么如果直接公开我们的playbook源码可能会有隐私数据泄露的情况!那么我么可以把这些敏感数据可以跟playbook进行分割!
我们可以把变量在一个外部变量文件中定义:
somevar: somevalue
password: magic
在playbook中直接引用这个变量文件
-
hosts: all
remote_user: root
vars:
favcolor: blue
vars_files:- /vars/vars.yml
tasks:
- name: this is just a placeholder
command: /bin/echo foo
5 Handlers: 在发生改变时执行的操作
我们可以使用handlers定义一些触发任务,这些触发任务可以在其他的任务中调用,但是执行条件是该任务有更改时才会触发这些触发任务!比如如下例子:
- name: template configuration file
template: src=template.j2 dest=/etc/foo.conf
notify:- restart memcached
- restart apache
handlers: - name: restart memcached
service: name=memcached state=restarted - name: restart apache
service: name=apache state=restarted
重启memcache和apache只有当我们使用template模块分发的配置文件有更改时才会被执行,如果配置文件没有更改则不会执行重启
Handlers 最佳的应用场景是用来重启服务,或者触发系统重启操作.除此以外很少用到了.
练习:
编写playbook批量源码部署Nginx:
在playbook中定义变量:
- 监听ip
- 监听端口
- 网站根目录
- 网站域名
- 启用worker进程数量、
- nginx运行用户
配置nginx配置文件模板,模板文件中调用playbook中定义的变量
使用template分发nginx配置文件模板
请为分发nginx配置文件任务调用触发重启的handlers触发任务
请为分发nginx配置文件任务定义一个tags
成功部署nginx
点击跳转编写playbook批量源码部署Nginx
条件选择
在有些时候我们需要选择主机去执行不同的任务,比如我们在关闭防火墙的时候,Centos6和Centos7关闭的方式是不同的,所有我们需要判断主机的系统版本来执行对应的任务
when语句
有时候用户有可能需要某一个主机越过某一个特定的步骤,比如在不同的系统上安装不同版本的rpm包,或者是某个主机的磁盘满了,执行清理任务,等等!这种需要满足某个条件再执行的任务,就需要通过when来实现!