一、 playbook简介
本质上playbook就是ansible命令的合集,是个采用YAML语言编写的脚本文件。
图解playbook:
playbook由多条play组成,每条play都有一个task对应的操作,然后调用modules,应用在主机清单host上,通过ssh远程连接,从而控制远程主机或者网络设备
Playbook核心元素
- Hosts:待执行的远程主机列表
- Tasks:要做的任务集
- Variables:内置变量或自定义变量
- Templates:可替换模板文件中的变量并实现一些简单逻辑的文件
- Handlers和notify:特定条件触发的操作,满足条件方才执行,否则不执行
- tags:指定某条任务执行,用于选择运行playbook中的部分代码。
补充一句,当你把上面这些分别放在不同目录,并在总的playbook文件里调用它们,这就是后面要讨论的ansible的roles。
二、 yaml语言简介
1. 名称来源
YAML Ain't Markup Language,即YAML不是XML。不过,在开发的这种语言时,YAML的意思其实是:"Yet Another Markup Language"(仍是一种标记语言)
2. 语法简介
- 以三个连字号 --- 作为yaml文件开头
- 以三个点号 ... 作为yaml文件结尾(非必须)
- 次行开始正常写Playbook的内容,一般建议写明该Playbook的功能
- 使用#号注释代码
- 缩进符号必须是统一的,不能空格和tab混用
- 缩进级别也必须是一致的,程序判别配置的级别是通过缩进结合换行来实现的
- 文件内容区分大小写,k/v的值均大小写敏感
- 多个k/v可同行写也可换行写,同行使用:分隔
- v可是个字符串,也可是另一个列表[]
- 一个完整的代码块功能最少元素需包括 name 和 task
- 一个name只能包括一个task
- name只用于输出其中内容,task真正干活
- YAML文件扩展名通常为yml或yaml
3. 简单示例
- List:列表,其所有元素均使用 - 打头,列表代表同一类型的元素
# A list of tasty fruits
- Apple
- Orange
- Strawberry
- Mango
- Dictionary:字典,通常由多个key与value构成 键值对
# An employee record
name: Example Developer
job: Developer
skill: Elite
# 也可以将key:value放置于{}中进行表示,用,分隔多个key:value
# 注意逗号后面有空格
{name: Example Developer, job: Developer, skill: Elite}
三、 playbook基础用法
1. 简单例子
---
# 安装并启动http service
- hosts: websrvs
remote_user: root
tasks:
- name: Install httpd
yum: name=httpd state=present
- name: Install configure file
copy: src=files/httpd.conf dest=/etc/httpd/conf/
- name: start service
service: name=httpd state=started enabled=yes
- hosts:待操作主机集,可以不写,执行时通过 -i 调用host文件
- remote_user:在远端使用哪个用户执行
- tasks:任务集(核心)
- name:只是一个文本提示,执行时会输出其中内容(例如输出Install httpd)
- yum: name=httpd state=present:真正干活的部分,其实就是前篇文章中的ansible命令
2. 运行yml文件
运行playbook的方式
ansible-playbook <filename.yml> ... [options]
常见选项
--check -C:语法检查,不真正执行操作
--list-hosts:列出运行任务的主机
--list-tags:列出tags
--list-tasks:列出tasks
--limit 主机列表:只针对主机列表中的主机执行
-v -vv -vvv:显示过程,v越多越详细
示例
# 只检查语法
ansible-playbook hello.yml --check
# 显示运行任务的主机
ansible-playbook hello.yml --list-hosts
# 只在websrvs主机运行命令
ansible-playbook hello.yml --limit websrvs
3. shell脚本转playbook
比如以下shell脚本
#!/bin/bash
# 安装Apache
yum install --quiet -y httpd
# 复制配置文件
cp /tmp/httpd.conf /etc/httpd/conf/httpd.conf
cp/tmp/vhosts.conf /etc/httpd/conf.d/
# 启动Apache,并设置开机启动
service httpd start
chkconfig httpd on
最简单的转法 —— 全部用shell模块实现
---
- hosts: all
remote_user: root
tasks:
- name: "安装Apache"
shell: yum install --quiet -y httpd
- name: "复制配置文件"
shell: cp /tmp/httpd.conf /etc/httpd/conf/httpd.conf
- name: "复制配置文件"
shell: cp/tmp/vhosts.conf /etc/httpd/conf.d/
- name: "启动Apache"
shell: service httpd start
- name: "设置开机启动"
shell: chkconfig httpd on
将各命令转为使用对应模块
---
- hosts: all
remote_user: root
tasks:
- name: "安装Apache"
yum: name=httpd
- name: "复制配置文件"
copy: src=/tmp/httpd.conf dest=/etc/httpd/conf/
- name: "复制配置文件"
copy: src=/tmp/vhosts.conf dest=/etc/httpd/conf.d/
- name: "启动Apache,并设置开机启动"
service: name=httpd state=started enabled=yes
四、 handlers和notify
先看一个例子
---
- hosts: websrvs
remote_user: root
tasks:
- name: Install httpd
yum: name=httpd state=present
- name: Install configure file
copy: src=files/httpd.conf dest=/etc/httpd/conf/
notify: restart httpd # 注意这里
- name: ensure apache is running
service: name=httpd state=started enabled=yes
handlers: # 注意这里
- name: restart httpd # 这个名字跟notify后一定是对应的
service: name=httpd state=restarted
实际上它们就是一个触发器,当notify的前一行(copy: src=files/httpd.conf dest=/etc/httpd/conf/)被执行,notify就会被触发,进而调用其后的restart httpd部分。而restart httpd部分内容是什么,就在下面的handlers中定义。
所以上面代码想实现的功能其实是:当ansible主机上的httpd.conf配置文件有改动,执行了copy操作时(如果没有改动则copy语句不会被执行到),触发重启httpd服务的操作,使配置自动生效。
handlers和notify可以有多个,例如:
---
- hosts: websrvs
remote_user: root
tasks:
- name: add group nginx
tags: user
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: config
copy: src=/root/config.txt dest=/etc/nginx/nginx.conf
notify:
- Restart Nginx
- Check Nginx Process
handlers:
- name: Restart Nginx
service: name=nginx state=restarted enabled=yes
- name: Check Nginx process
shell: killall -0 nginx > /tmp/nginx.log
---
- hosts: hbhosts
remote_user: root
tasks:
- name: ensure heartbeat latest version
yum: name=heartbeat state=present
- name: authkeys configure file
copy: src=/root/hb_conf/authkeys dest=/etc/ha.d/authkeys
- name: authkeys mode 600
file: path=/etc/ha.d/authkeys mode=600
notify:
- restart heartbeat
- name: ha.cf configure file
copy: src=/root/hb_conf/ha.cf dest=/etc/ha.d/ha.cf
notify:
- restart heartbeat
handlers:
- name: restart heartbeat
service: name=heartbeat state=restarted
五、 tags
tags 可以为某个或多个命令添加一个标签,添加标签后,可以指定只执行该标签相关命令。
示例:httpd.yml
---
- hosts: websrvs
remote_user: root
tasks:
- name: Install httpd
yum: name=httpd state=present
tage: install
- name: Install configure file
copy: src=files/httpd.conf dest=/etc/httpd/conf/
tags: conf
- name: start httpd service
service: name=httpd state=started enabled=yes
tags: service
# 指定执行install,conf 两个标签对应命令
ansible-playbook –t install,conf httpd.yml
综合例子
---
- hosts: testsrv
remote_user: root
tags: inshttpd
tasks:
- name: Install httpd
yum: name=httpd state=present
- name: Install configure file
copy: src=files/httpd.conf dest=/etc/httpd/conf/
tags: rshttpd
notify: restart httpd
handlers:
- name: restart httpd
service: name=httpd status=restarted
ansible-playbook -t rshttpd httpd2.yml
六、 变量
1. 命名规则
变量名仅能由字母、数字和下划线组成,且只能以字母开头。
2. 变量定义与调用
- 系统自带变量
ansible setup facts 远程主机的所有变量都可直接调用
# 查询主机名
ansible all -m setup -a 'filter="ansible_nodename"'
# 查询主机内存大小
ansible all -m setup -a 'filter="ansible_memtotal_mb"'
# 查询系统版本
ansible all -m setup -a 'filter="ansible_distribution_major_version"'
# 查询主机cpu个数
ansible all -m setup -a 'filter="ansible_processor_vcpus"'
通过{{ var_name }} 调用变量,变量名前后可以加空格,有时用"{{ var_name }}"才生效
# 示例:使用setup变量 var.yml
---
- hosts: websrvs
remote_user: root
tasks:
- name: create log file
file: name=/var/log/ {{ ansible_fqdn }} state=touch
# 执行playbook
ansible-playbook var.yml
- host文件中定义变量
主机变量
vim /etc/ansible/hosts
[appsrvs]
192.168.38.17 http_port=817 name=www
192.168.38.27 http_port=827 name=web
# 调用变量
# 更改主机名为各自被定义的变量
ansible appsrvs -m hostname -a'name={{ name }}'
组变量
vim /etc/ansible/hosts
[appsrvs]
192.168.38.17 http_port=817 name=www
192.168.38.27 http_port=827 name=web
[appsrvs:vars]
make="-"
# ansible调用变量
ansible appsrvs -m hostname -a 'name={{name}}{{mark}}{{http_port}}'
- 通过命令行指定变量
### vi var.yml
---
- hosts: websrvs
remote_user: root
tasks:
- name: install package
yum: name={{ pkname }} state=present
# 执行playbook
ansible-playbook –e pkname=httpd var.yml
- playbook中定义
### 示例:playbook定义变量 var.yml
---
- hosts: websrvs
remote_user: root
vars:
- username: oracle
- groupname: oinstall
tasks:
- name: create group
group: name={{ groupname }} state=present
- name: create user
user: name={{ username }} state=present
# 调用playbook
ansible-playbook var.yml
ansible-playbook -e "username=user2 groupname=group2" var.yml
- 在独立的变量yml文件中定义
vim vars.yml
pack: vsftpd
service: vsftpd
# 引用变量文件
vars_files:
- vars.yml
- 在role中定义:后面介绍,其实也是在yml文件中定义
参考:
《ansible权威指南》