1、playbook简介
playbook 是由一个或多个 “play” 组成的列表,play 的主要功能在于把预定义的一组主机,装扮成事先通过 ansible 中的 task 定义好的角色。task 实际是调用 ansible 的一个模块,将多个 play 组织在一个 playbook 中,按照事先编排的机制执行预定义的动作。playbook 文件采用 YAML 语言编写
2、YAML语言
YAML 是一个高可读性,用来表达资料序列的格式,更多介绍参见:YAML官网
2.1、YAML语法简介
- 在单一文件的第一行,用三个 “-” 开始
- 第二行开始写 playbook 的内用,一般建议写 playbook 的功能介绍
- 使用 “#” 注释代码
- 严格缩进,不能空格和 tab 混用
- 缩进的级别必须一致,同样的缩进代表形同的级别,程序判别配置的级别是通过缩进结合换行来实现的
- YAML 文件内容区分大小写,key / value 的值均需大小写敏感
- 多个 key / value 可以写在同一行,同行使用逗号(,)分隔
- value 可以是一个字符串,也可以是一个列表
- 一个完整的代码块功能,需要包括 name 和 task
- 一个 name 只能包含一个 task
- YAML 文件的扩展名一般为 yml 或 yaml
2.2、list列表
列表由多个元素组成
-
定义列表
# 使用 - 定义列表 - apple - orange - mango # 使用 [] 定义列表 [apple,orange,mango]
2.3、dictionary字典
字典由多个 key 和 value 组成
-
定义字典
name: wang age: 25 job: dev children: - name: zhangsan age: 15 job: it - name: wangwu age: 21 job: dev {name:"wang",age:25,job:"dev"}
2.4、常见数据格式
-
XML:可扩展标记语言,用于数据交换和配置
<servers> <server> <name>server1</name> <owner>user</owner> <passwd>123456</passwd> </server> </servers>
-
JSON:对象表记法,用于数据交换或配置,不支持注释
{ servers: [ { name:server1 owner:user passwd:123456 } ] }
-
YMAL:主要用于配置
servers: - name: server1 owner: user passwd: 123456
3、playbook核心元素
- hosts:需要执行任务的远程主机列表
- tasks:任务集
- variables:内置变量或自定义变量在 playbook 中调用
- templates:模板,可替换模板文件中的变量并实现一些简单逻辑的文件
- handlers 和 notify 结合使用,由特定条件触发的操作,满足条件即可执行,否则不执行
- tags:标签,指定某条任务执行,用于选择运行 playbook 中的部分代码
3.1、playbook命令
-
语法
ansible-playbook <filename.yml> [选项]
-
常用选项
--check:只检测会发生的改变,不实际执行 --list-hosts:列出需要执行任务的主机 --list-tags:列出tag --list-tasks:列出task --limit <主机列表>:只针对主机列表中的主机执行
-
使用示例
# 检测playbook ansible-playbook --check install_httpd.yml # 执行playbook ansible-playbook install_httpd.yml # 只在特定主机上执行 ansible-playbook install_httpd.yml --limit=192.168.137.11
3.2、hosts组件
hosts 主要用于指定需要执行任务的主机,需事先在主机清单中配置
- hosts:
svr1
192.168.137.12
3.3、remote_user组件
用于执行任务的用户,可用于 host 和 task 中,其可以用于 play 全局或某个任务
- hosts: svr1
remote_user: root
tasks:
- name: test ping
ping:
remote_user: root
3.4、task列表和action组件
paly 的主体部分是 taks 列表,task 列表中由一个或多个 task,各 task 按次序逐个在 hosts 中指定的所有主机上运行,等在所有主机上执行完第一个 task 后,才开始执行第二个 task
task 的目的是使用指定的参数执行模块,而且在模块参数中可以使用变量
每个 task 都应该有 name,用于 playbook 的执行结果输出,建议其内容能清晰的描述任务执行步骤;未提供 name,则 action 的结果将用于输出
3.4.1、task的两种格式
需要注意的是,在模块名称的冒号后面有一个空格
-
action:模块名 参数
-
模块:参数(常用)
3.4.2、示例
---
- hosts: svr1
remote_user: root
# 不收集facts信息
gather_facts: no
tasks:
- name: install httpd
yum: name=httpd
- name: start httpd
service: name=httpd state=started enabled=yes
3.5、handlers与notify组件
handlers 本质上就是一个 task list,类似于 MySQL 中的触发器的触发行为,playbook 中的 task 和普通的 task 相同,唯独不同的是 notify 用于对关注的资源发生变化时,才会采取一定的动作。notify 对应的动作可用于在每个 play 的最后被触发,这样可以避免多次有发生改变时每次都执行指定的操作,而是仅在所有变化都完成后,一次性的执行指定操作
在 notify 中列出来的操作称之为 handler,其实就是 notify 调用 handler 中定义的操作(notify 中的名称必须和 handlers 中名称相同)
-
示例
--- - hosts: svr1 remote_user: root gather_facts: no tasks: - name: install httpd yum: name=httpd - name: install configure file copy: src=/files/httpd.conf dest=/etc/httpd/conf/httpd.conf notify: restart httpd - name: start httpd service: name=httpd state=started enabled=yes handlers: - name: restart httpd service: name=httpd state=restarted
3.6、tags组件
在 playbook 文件中,可以利用 tags 组件,为特定 task 指定标签,当在执行 playbook 时,可以只执行特定的 task,而非整个 playbook 文件
-
示例
# YAML文件 --- - hosts: svr1 remote_user: root gather_facts: no tasks: - name: install httpd yum: name=httpd - name: install configure file copy: src=/files/httpd.conf dest=/etc/httpd/conf/httpd.conf notify: restart httpd tags: config - name: restart httpd service: name=httpd state=started enabled=yes tags: service handlers: - name: restart httpd service: name=httpd state=restarted # 执行指定tags ansible-playbook install_httpd.yml -t config,service
4、变量
4.1、定义变量
变量名只能由字母、数字、下划线组成,且只能以字母开头
-
语法
变量名=值
-
示例
http_port=80
4.2、变量调用
在 playbook 中,使用 {{ 变量名 }} 的方式来调用变量,且在变量名前后建议添加空格,有时需要使用 “ {{ 变量名 }} ” 的方式调用才会生效
4.3、变量定义方式
在所有变量定义方式中,在 playbook 命令行中定义的变量的优先级最高
4.3.1、使用setup模块中的变量
ansible 的 setup facts 远程主机上的所有变量都可以直接使用,但是只能在 playbook 中使用,不能使用 ansible 命令调用
需要注意的是,使用 setup 模块中的变量,不能将 gather_facts 禁用
# 创建var.yml变量文件
---
- hosts: all
remote_user: root
tasks:
- name: create file
file: name=/files/{{ ansible_nodename}}.txt state=touch
# 使用变量文件
ansible-playbook var.yml
4.3.2、在playbook命令行中定义变量
通过命令行指定变量,其优先级最高
# 创建var.yml变量文件
---
- hosts: all
remote_user: root
tasks:
- name: install package
yum: name={{ pkname }} state=present
# 定义变量
ansible-playbook -e pkname=httpd var.yml
4.3.3、在playbook文件中定义变量
---
- hosts: all
remote_user: root
vars:
- username: user01
- groupname: group01
tasks:
- name: create group
group: name={{ groupname }} state=persent
- name: create user
user: name={{ username }} state=persent
4.3.4、使用变量文件
可以在一个独立的 playbook 文件中定义变量,在另一个 playbook 文件中引用变量文件中的变量,比 playbook 中定义的变量优先级高
# 创建var.yml
---
pk_name: httpd
svr_name: httpd
# 引用var.yml
---
- hosts: all
remote_user: root
vars_files:
- /files/var.yml
tasks:
- name: install package
yum: name={{ pk_name }} state=present
- name: start httpd
service: name={{ svr_name }} state=started enabled=yes
4.3.5、主机清单文件中定义变量
在主机清单文件中定义变量时,主机变量优先于组变量
-
主机变量
在主机清单中为指定主机定义变量名,便于在 playbook 中使用
[appservers] 192.168.137.11 host=node1 http_port=8080 192.168.137.12 host=node2 http_port=8081
-
组变量
[appservers:vars] domain=123.com
-
使用变量名
# 修改主机名称 ansible appservers -m hostname -a 'name={{ host }}.{{ domain }}'
5、when判断
when 语句可以实现条件测试功能。如果需要根据变量、facts 或此前任务的执行结果来做为某个 task 执行与否的前提时,需要使用到条件测试,通过在 task 后添加 when 语句即可实现条件测试
-
示例
# 重新启动RedHat系统的主机 --- - hosts: svr1 remote_user: root tasks: - name: restart redhat hosts command: /sbin/reboot -h now # 判断是否是RedHat系统 when: ansible_os_family == "RedHat"
6、whith_items迭代(循环)
当有需要执行重复性工作时,可以使用迭代机制。对迭代项的引用,固定变量名为 item,要在 task 中使用 with_items 指定需要迭代的元素列表
-
列表元素格式
- 字符串
- 字典
-
示例
(1)、使用字符串执行迭代
--- - hosts: svr1 remote_user: root tasks: - name: create several user user: name={{ item }} state=present with_items: - user1 - user2
(2)、使用字典执行迭代
--- - hosts: svr1 remote_user: root tasks: - name: create several goup group: name={{ item }} state=present with_items: - group_1 - group_2 - name: create several user user: name={{ item.name }} group={{ item.group }} state=present with_items: - {name: 'user1',group: 'group_1'} - {name: 'user2',group: 'group_2'}
7、roles角色
role(角色)主要是用于层次性、结构化的组织 playbook ,roles 能够根据层次性结构自动装载变量文件、tasks 及 handlers 等,要使用 roles 只需要在 playbook 中使用 include 指令即可。简单来说,roles 就是通过分别将变量、文件、任务、模板及处理器放到单独的目录中,并可以快捷的包含它们的一种机制。角色一般使用于较为复杂的运维环境,提高代码的复用性
roles 是多个角色的集合,可以将多个 role 分别存放于 roles 目录下的子目录中
7.1、roles目录结构
roles 的目录结构为:roles/project/:项目名称下有以下子目录
- files/:存放由 copy 或 script 等模块调用的文件
- template/:template 模块查找所需要模板文件的目录
- tasks/:定义 task、role 的基本元素,至少因该包含一个名为 main.yml 的文件,其他文件需要在此文件中通过 include 进行包含( 建议一个任务创建一个task )
- handlers/:至少因该包含一个名为 main.yml 的文件,其他文件需要在此文件中通过 include 进行包含
- vars/:定义变量,至少因该包含一个名为 main.yml 的文件,其他文件需要在此文件中通过 include 进行包含
- meta/:定义当前角色的特殊设定及其依赖关系,至少因该包含一个名为 main.yml 的文件,其他文件需要在此文件中通过 include 进行包含
- default/:设定默认变量时使用此目录中的 main.yml 文件,比 vars 的优先级低
7.2、创建role的步骤
-
roles 默认存放路径:/etc/ansible/roles
-
创建以 roles 命名的目录
-
在 roles 目录中分别创建以各角色命名的目录,如 mysql 等
-
在每个角色目录中分别创建 files、handlers、meta、tasks、templates、vars 目录,暂时使用不到的目录可以创建空目录,也可以不创建
-
在 playbook 中调用各角色
-
目录结构示例
httpd-role.yml └── roles └── httpd ├── files │ └── main.yml ├── tasks │ ├── groupadd.yml │ ├── install.yml │ ├── main.yml │ ├── restart.yml │ └── useradd.yml └── vars └── main.yml
7.3、playbook调用角色
-
普通调用角色
--- - hosts: svr1 remote_user: root roles: - httpd
-
调用角色并传递参数
--- - hosts: svr1 remote_user: root roles: - httpd - { role:httpd, username:user01}
-
基于条件调用角色
--- - hosts: svr1 remote_user: root roles: - httpd - { role: httpd, username: user01, when: ansible_os_family == "RedHat"}
-
roles中使用tags
# 在playbook文件中使用 --- - hosts: svr1 remote_user: root roles: - { role: httpd, tags: ['httpd', 'web'] } - { role: httpd, tags: ['httpd', 'web'], when: ansible_os_family == "RedHat" } # 或者在执行时使用 ansible-playbook --tags="httpd, web" httpd-role.yml
7.4、使用示例
创建一个 httpd 部署 roles
# 创建相关目录
mkdir roles/httpd/{tasks,files,handlers}
#创建各tasks
vim tasks/install.yml
- name: install httpd
yum: name=httpd
vim tasks/config.yml
- name: config file
copy: src=httpd.conf dest=/etc/httpd/conf backup=yes
notify: restart service
vim tasks/index.yml
- name: index.html
copy: src=index.html dest=/var/www/html/
vim tasks/service.yml
- name: start service
service: name=httpd state=started enabled=yes
vim handlers/main.yml
- name: restart service
service: name=httpd state=restarted
vim tasks/main.yml
- include: install.yml
- include: config.yml
- include: index.yml
- include: service.yml
# 准备相关文件
ls /etc/ansible/roles/httpd/files/
httpd.conf index.html
# 在playbook中调用roles
vim httpd_install_role.yml
---
- hosts: host
remote_user: root
gather_facts: no
roles:
- httpd
# 最终roles文件结构
tree /etc/ansible/roles/
/etc/ansible/roles/
└── httpd
├── files
│ ├── httpd.conf
│ └── index.html
├── handlers
│ └── main.yml
└── tasks
├── config.yml
├── index.yml
├── install.yml
├── main.yml
└── service.yml
# 执行playbook
ansible-playbook httpd_install_role.yml