之前介绍了ansible-playbook的使用方法,对于批量任务的部署和操作非常方便,但是耦合度比较高,不便于模块化、层次化的复用,为了层次性、结构化地组织playbook,我们可以使用roles来更加高效地组织playbooks;roles能够根据层次型结构自动装载变量文件、tasks以及handlers等。要使用roles只需要在playbook中使用include指令即可。
简单来讲,roles就是通过分别将变量、文件、任务、模板及处理器放置于单独的目录中,比较复杂的场景建议使用roles,代码复用度高。
创建roles的步骤如下:
ansible-galaxy init test1
。ansible在执行playbook命令时,会在以下路径依次寻找role:
生成出来的文件夹目录如下:
roles
├── test1
│ ├── README.md
│ ├── defaults
│ │ └── main.yml
│ ├── files
│ ├── handlers
│ │ └── main.yml
│ ├── meta
│ │ └── main.yml
│ ├── tasks
│ │ └── main.yml
│ ├── templates
│ ├── tests
│ │ ├── inventory
│ │ └── test.yml
│ └── vars
│ └── main.yml
通过目录结构,我们可以看到以下几个比较有用的目录:
在playbook中,我们可以使用多种灵活的方式调用roles,话不多说,直接举例子更加清晰,我们定义下面的一个playbook,并且用不同的方式调用相应的roles:
---
- hosts: tencent
remote_user: root
roles:
- test1 // 直接使用
- { role: nginx, username: nginx, when: ansible_distribution_major_version == ‘7’ } // 以对象k,v的方式,可以基于条件测试
- { role: mysql ,tags: [ 'mysql', 'db' ] } // 添加tags
用一个实际的例子来实战一下roles,是最好的学习方法,下面我们就编排一个简单的roles,我们先创建如下的目录结构,会用到test1 test2两个roles,并且用 ansible_role_test.yaml 作为playbook执行文件。
├── ansible_role_test.yaml
└── roles
├── test1
│ ├── README.md
│ ├── defaults
│ │ └── main.yml
│ ├── files
│ ├── handlers
│ │ └── main.yml
│ ├── meta
│ │ └── main.yml
│ ├── tasks
│ │ ├── file.yml
│ │ ├── main.yml
│ │ └── mkdir.yml
│ ├── templates
│ ├── tests
│ │ ├── inventory
│ │ └── test.yml
│ └── vars
│ └── main.yml
└── test2
├── README.md
├── defaults
│ └── main.yml
├── files
├── handlers
│ └── main.yml
├── meta
│ └── main.yml
├── tasks
│ ├── main.yml
│ └── template.yml
├── templates
│ └── test2.txt.j2
├── tests
│ ├── inventory
│ └── test.yml
└── vars
└── main.yml
编写主playbook - ansible_role_test.yaml,引入两个roles。
- hosts: tencent
remote_user: root
roles:
- test1
- test2
test1
tasks目录:
# main.yml(引入mkdir.yml和file.yml)
- include: mkdir.yml
- include: file.yml
# file.yml
- name: test touch file
shell: cd /tmp/roles && touch {{ filename }}
notify: test end
# mkdir.yml
- name: test mkdir
shell: mkdir -p /tmp/roles
vars目录:
# main.yml(用于task的file.yml中使用)
filename: test_role.txt
handlers目录,主要对应上面tasks中file.yml的notify:
- name: test end
debug:
msg: '任务结束了'
test2
tasks目录:
# main.yml
- include: template.yml
# template.yml
- name: 测试模版文件复制
template: src=test2.txt.j2 dest=/tmp/roles/text2.txt
templates目录,用于保存templates模版文件,基于jinja2语法:
# test2.txt.js
test {{ var1 }}
test1 {{ var1 + var2 }}
vars目录:
var1: 5
var2: 10
完整结构定义好后,执行ansible-playbook ansible_role_test.yaml
执行结果如下:
PLAY [tencent] ********************************************************************************************************************************************************************************************
TASK [Gathering Facts] ************************************************************************************************************************************************************************************
ok: [42.194.184.177]
ok: [159.75.83.204]
TASK [test1 : test mkdir] *********************************************************************************************************************************************************************************
changed: [42.194.184.177]
changed: [159.75.83.204]
TASK [test1 : test touch file] ****************************************************************************************************************************************************************************
changed: [42.194.184.177]
changed: [159.75.83.204]
TASK [test2 : 测试模版文件复制] ***************************************************************************************************************************************************************************
changed: [42.194.184.177]
changed: [159.75.83.204]
RUNNING HANDLER [test1 : test end] ************************************************************************************************************************************************************************
ok: [42.194.184.177] => {
"msg": "任务结束了"
}
ok: [159.75.83.204] => {
"msg": "任务结束了"
}
PLAY RECAP ************************************************************************************************************************************************************************************************
159.75.83.204 : ok=5 changed=3 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
42.194.184.177 : ok=5 changed=3 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
通过执行结果我们可以知道: