Role - Playbook的“Package”

Role比include更强大灵活的代码重用和分享机制。Include类似于编程语言中的include,是重用单个文件的,重用的功能有限。

而Role类似于编程语言中的“Package”,可以重用一组文件形成完整的功能。例如安装和配置apache,需要tasks实现安装包和拷贝模版等,httpd.conf和index.html的模版文件,和handler文件实现重起功能。这些文件都可以放在一个role里面,供不同的playbook文件重用。

Ansible非常提倡在playbook中使用role,并且提供了一个分享role的平台Ansible Galaxy, https://galaxy.ansible.com/, 在galaxy上可以找到别人写好的role。在后面的章节中,我们再详细介绍如果使用它。

定义role完整的目录结构

在ansible中,通过遵循特定的目录结构,就可以实现对role的定义。。具体遵循的目录结构是什么呢?看下面的例子:

下面的目录结构定义了一个role:名字为myrole。在site.yml,调用了这个role。











role的目录结构

site.yml中调用role



  1. site.yml
    roles/
    ├── myrole
    ├── tasks
    └── main.yml
    ├── handlers
    └── main.yml
    ├── defaults
    └── main.yml
    ├── vars
    └── main.yml
    ├── files
    ├── templates
    ├── README.md
    ├── meta
    └── main.yml
    └── tests
    ├── inventory
    └── test.yml







  1. —-
    - hosts: webservers
    roles:
    - myrole



ansible并不要求role包含上述所有的目录及文件,根据role的功能需要加入对应的目录和文件。下面是每个目录和文件的功能。

  • 如果 roles/x/tasks/main.yml 存在, 其中列出的 tasks 将被添加到 play 中,所以这个文件也可以视作role的入口文件,想看role做了什么操作,可以从此文件看起。
  • 如果 roles/x/handlers/main.yml 存在, 其中列出的 handlers 将被添加到 play 中
  • 如果 roles/x/vars/main.yml 存在, 其中列出的 variables 将被添加到 play 中
  • 如果 roles/x/meta/main.yml 存在, 其中列出的 “角色依赖” 将被添加到 roles 列表中
  • roles/x/tasks/main.yml中所有tasks,可以引用 roles/x/{files,templates,tasks}中的文件,不需要指明文件的路径。

你自己在写role的时候,一般都要包含role入口文件roles/x/tasks/main.yml,其它的文件和目录,可以根据需求选择加入。

学会写一个完整功能的role是一个想对复杂的过程,也是ansible中稍高级的使用方法。在本小节,我们重点介绍如何使用别人已经写好的role。在后面的章节中,我们会通过具体的示例来逐步介绍写role的所需的知识。

带参数的Role

参数在role中是如何定义的呢

定义一个带参数的role,名字是myrole,那么目录结构为

  1. main.yml
  2. roles
  3. role_with_var
  4. tasks
  5. main.yml

在roles/myrole/tasks/main.yml中,使用{{ }}定义的变量就可以了

  1. ---
  2. - name: use param
  3. debug: msg="{{ param }}"

使用带参数的role

那么在main.yml就可以用如下的方法使用myrole

  1. ---
  2. - hosts: webservers
  3. roles:
  4. - { role: myrole, param: 'Call some_role for the 1st time' }
  5. - { role: myrole, param: 'Call some_role for the 2nd time' }

或者写成yml字典格式:

  1. ---
  2. - hosts: webservers
  3. roles:
  4. - role: myrole
  5. param: 'Call some_role for the 1st time'
  6. - role: myrole
  7. param: 'Call some_role for the 2nd time'

role指定默认的参数

指定默认参数后,如果在调用时传参数了,那么就使用传入的参数值.如果调用的时候没有传参数,那么就使用默认的参数值.

指定默认参数很简单,以上面的role_with_var为例

  1. main.yml
  2. roles:
  3. myrole
  4. tasks
  5. main.yml
  6. defaults
  7. main.yml

在roles/myrole/defaults/main.yml中,使用yml的字典定义语法定义param的值,如下:

  1. param: "I am the default value"

这样在main.yml中,下面两种调用方法都可以

  1. ---
  2. - hosts: webservers
  3. roles:
  4. - role_with_var
  5. - { role: role_with_var, param: 'I am the value from external' }

更多的例子在https://github.com/shijingjing1221/ansible-first-book-examples/blob/master/role_vars.yml

role与条件语句when一起执行

下面的例子中,my_role只有在RedHat系列的server上才执行。

  1. ---
  2. - hosts: webservers
  3. roles:
  4. - { role: my_role, when: "ansible_os_family == 'RedHat'" }

同样也可以写成yml字典格式

  1. ---
  2. - hosts: webservers
  3. roles:
  4. - role: my_role
  5. when: "ansible_os_family == 'RedHat'"

roles和tasks的执行顺序

如果一个playbook同时出现role和tasks,他们的调用顺序是什么样的呢?

先揭晓答案,在根据实例来验证:

pre_tasks > role > tasks > post_tasks

  1. ---
  2. - hosts: lb
  3. user: root
  4. pre_tasks:
  5. - name: pre
  6. shell: echo 'hello'
  7. roles:
  8. - { role: some_role }
  9. tasks:
  10. - name: task
  11. shell: echo 'still busy'
  12. post_tasks:
  13. - name: post
  14. shell: echo 'goodbye'

执行的结果为:

  1. PLAY [lb] **********************************************************************
  2. TASK [setup] *******************************************************************
  3. ok: [rhel7u3]
  4. TASK [pre] *********************************************************************
  5. changed: [rhel7u3]
  6. TASK [some_role : some role] ***************************************************
  7. ok: [rhel7u3] => {
  8. "msg": "Im some role"
  9. }
  10. TASK [task] ********************************************************************
  11. changed: [rhel7u3]
  12. TASK [post] ********************************************************************
  13. changed: [rhel7u3]
  14. PLAY RECAP *********************************************************************
  15. rhel7u3 : ok=5 changed=3 unreachable=0 failed=0