Ansible roles介绍

前言

之前介绍了ansible-playbook的使用方法,对于批量任务的部署和操作非常方便,但是耦合度比较高,不便于模块化、层次化的复用,为了层次性、结构化地组织playbook,我们可以使用roles来更加高效地组织playbooks;roles能够根据层次型结构自动装载变量文件、tasks以及handlers等。要使用roles只需要在playbook中使用include指令即可。

roles初体验

简单来讲,roles就是通过分别将变量、文件、任务、模板及处理器放置于单独的目录中,比较复杂的场景建议使用roles,代码复用度高。

创建roles的步骤如下:

  1. 创建以roles命名的目录。
  2. 生成以各角色名称命名的目录,如test1;可以使用简单的命令生成一个标准的role文件夹:ansible-galaxy init test1
  3. 每个角色名称命名的目录中,要有files、handlers、meta、tasks、templates和vars目录;用不到的目录可以创建为空目录,也可以不创建,用命令方式默认会创建所有目录

ansible在执行playbook命令时,会在以下路径依次寻找role:

  • 与playbook并列的roles目录
  • /etc/ansible/roles中
  • 通过在ansible.cfg文件中配置roles_path来设置系统级role的位置,也可以通过设置ANSIBLE_ROLES_PATH环境变量来覆盖这个设置

生成出来的文件夹目录如下:

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

通过目录结构,我们可以看到以下几个比较有用的目录:

  1. files:存放由copy或script模块等调用的文件
  2. templates:template模块查找所需要模板文件的目录
  3. tasks:定义task,role的基本元素,至少有一个名为main.yml的文件;其它的文件需要在此文件中通过include引入
  4. handlers:至少有一个名为main.yml的文件;其它的文件需要在此文件中通过include引入
  5. vars:定义变量,至少有一个名为main.yml的文件;其它的文件需要在此文件中通过include引入
  6. meta:定义当前角色的特殊设定及其依赖关系,至少有一个名为main.yml的文件,其它文件需在此文件中通过include引入
  7. default:设定默认变量时使用此目录中的main.yml文件,比vars的优先级低

playbook调用roles方式

在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,是最好的学习方法,下面我们就编排一个简单的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

playbook结果

完整结构定义好后,执行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  

通过执行结果我们可以知道:

  • playbook会按照定义的roles顺序执行
  • handlers会在全部roles都执行完后再执行

你可能感兴趣的:(自动化运维,#,Ansible,python,运维开发)