一、 roles简介

  • 为了实现playbook重用,可以使用role角色
  • 角色role相当于把任务打散,放到不同的目录中。
  • 再把一些固定的值,如用户名、软件包、服务等,用变量来表示。
  • role角色定义好之后,可以在其他playbook中直接调用

二、 角色集合

roles/
  mysql/
  nginx/
  httpd/

tasks目录:角色需要执行的主任务文件放置在此目录中,默认的主任务文件名为main.yml,当调用角色时,默认会执行main.yml文件中的任务,你也可以将其他需要执行的任务文件通过include的方式包含在tasks/main.yml文件中。

handlers目录:当角色需要调用handlers时,默认会在此目录中的main.yml文件中查找对应的handler

defaults目录:角色会使用到的变量可以写入到此目录中的main.yml文件中,通常,defaults/main.yml文件中的变量都用于设置默认值,以便在你没有设置对应变量值时,变量有默认的值可以使用,定义在defaults/main.yml文件中的变量的优先级是最低的。

vars目录:角色会使用到的变量可以写入到此目录中的main.yml文件中,看到这里你肯定会有疑问,vars/main.yml文件和defaults/main.yml文件的区别在哪里呢?区别就是,defaults/main.yml文件中的变量的优先级是最低的,而vars/main.yml文件中的变量的优先级非常高,如果你只是想提供一个默认的配置,那么你可以把对应的变量定义在defaults/main.yml中,如果你想要确保别人在调用角色时,使用的值就是你指定的值,则可以将变量定义在vars/main.yml中,因为定义在vars/main.yml文件中的变量的优先级非常高,所以其值比较难以覆盖。

meta目录:如果你想要赋予这个角色一些元数据,则可以将元数据写入到meta/main.yml文件中,这些元数据用于描述角色的相关属性,比如 作者信息、角色主要作用等等,你也可以在meta/main.yml文件中定义这个角色依赖于哪些其他角色,或者改变角色的默认调用设定,在之后会有一些实际的示例,此处不用纠结。

templates目录: 角色相关的模板文件可以放置在此目录中,当使用角色相关的模板时,如果没有指定路径,会默认从此目录中查找对应名称的模板文件。

files目录:角色可能会用到的一些其他文件可以放置在此目录中,比如,当你定义nginx角色时,需要配置https,那么相关的证书文件即可放置在此目录中。

三、 角色定制实例

1. 在roles目录下生成对应的目录结构,也可以使用剧本嵌套循环的方式创建

方法一:
# cd /etc/ansible/roles
# mkdir -pv ./{nginx,mysql,httpd}/{files,templates,vars,tasks,handlers,meta,defaults}
# tree
.
├── httpd
│   ├── defaults
│   ├── files
│   ├── handlers
│   ├── meta
│   ├── tasks
│   ├── templates
│   └── vars
├── mysql
│   ├── defaults
│   ├── files
│   ├── handlers
│   ├── meta
│   ├── tasks
│   ├── templates
│   └── vars
└── nginx
    ├── defaults
    ├── files
    ├── handlers
    ├── meta
    ├── tasks
    ├── templates
    └── vars

方法二:

# vim /root/with_fileglob.yaml 
---
- hosts: web1
  tasks:
  - name: mkdir
    file:
      path: "/etc/ansible/roles/{{item.0}}/{{item.1}}/"
      state: directory
    with_nested:
      - [ nginx,mysql ]
      - [ files,templates,vars,tasks,handlers,meta,defaults ]
    connection: local

2、定义配置文件(以nginx为例)
tasks
---
- name: install package
  yum:
    name: "{{ item }}"
    state: present
  loop: "{{ package }}"
- name: start nginx
  service:
    name: "{{ item }}"
    state: started
  loop: "{{ package }}"
- name: copy nginx.conf
  template:
    src: nginx.conf
    dest: /etc/nginx/
  notify: restart nginx
- name: copy keepalived
  template:
    src: keepalived.conf
    dest: /etc/keepalived/
  notify: restart keepalived
- name: copy check.sh
  copy:
    src: check.sh
    dest: /etc/keepalived/
    mode: "0755"
- name:
  copy:
    content: ansible2
    dest: /usr/share/nginx/html/index.html
  when: ansible_hostname == "ansible2"
- name:
  copy:
    content: ansible3
    dest: /usr/share/nginx/html/index.html
  when: ansible_hostname == "ansible3"

handlers
# vim nginx/handlers/main.yml
---
- name: restart nginx
  service:
    name: nginx
    state: restarted
- name: restart keepalived
  service:
    name: keepalived
    state: restarted

templates
# vim nginx/templates/nginx.conf
http {
...

 {% if usepass == "true" %}
    upstream ansible_nginx {
         server 192.168.100.102:80;
         server 192.168.100.100:80;

    }
     {% endif %}

     server {
        listen       80 default_server;
        server_name  _;
        include /etc/nginx/default.d/*.conf;

        {% if usepass == "false" %}
        location / {
            root  /usr/share/nginx/html;
            index index.html;
        }
        {% endif%}

        {% if usepass == "true" %}
        location / {
            proxy_pass http://ansible_nginx;
        }
        {% endif %}
    }
}

# vim nginx/templates/keepalived.conf

! Configuration File for keepalived
global_defs {
   router_id {{ ansible_hostname }}
}

vrrp_script check_nginx {
   script "/etc/keepalived/check.sh"
   interval 2
}

vrrp_instance VI_1 {
{% if ansible_hostname == "ansible2" %}
    state MASTER
    interface ens33
    priority 100
{% elif ansible_hostname == "ansible3" %}
    state BACKUP
    interface ens33
    priority 80
{% endif %}
    virtual_router_id 50
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass pass
    }
    virtual_ipaddress {
        192.168.100.99/24
    }
    track_script {
        check_nginx
    }
}

vars
# vim nginx/vars/main.yml
---
package: [ nginx , keepalived ]

defaults
# vim nginx/defaults/main.yml
---
usepass: "false"

files
# vim nginx/files/main.yml
# /bin/bash

curl -l localhost &> /dev/null
if [ $? -ne 0  ];then
     sysetmctl stop keepalived

fi

roles
第一种:
# vim nginx.yml
---
 - hosts: web3
   remote_user: root
   roles:
     - nginx
   tasks:

第二种:

需要在meta目录里面添加main.yaml文件添加参数才能重复调用角色,传入不同的变量

meta
# vim nginx/meta/main.yaml 
---
allow_duplicates: true


# vim nginx.yml
---
 - hosts: web3
   roles:
     - role: nginx
       usepass: "true"
       when: ansible_hostname == "ansible2"
     - role: nginx
       usepass: "false"
       when: ansible_hostname == "ansible3"
   tasks:

# ansible-playbook nginx.yml 

各目录下的文件:
# tree nginx
nginx
├── defaults
│   └── main.yaml
├── files
│   └── check.sh
├── handlers
│   └── main.yaml
├── meta
│   └── main.yaml
├── tasks
│   └── main.yaml
├── templates
│   ├── keepalived.conf
│   └── nginx.conf
└── vars
    └── main.yaml

tasks目录里面的main.yaml还可以进行拆分,通过include_tasks模块进行调用

tasks
nginx/tasks/main.yaml

---
- include_tasks: n1.yaml
- include_tasks: n2.yaml
- include_tasks: n3.yaml

nginx/tasks/n1.yaml
---
- name: install
  yum:
    name: "{{ item }}"
    state: present
  loop: "{{ package }}"
- name: start
  service:
    name: "{{ item }}"
    state: started
  loop: "{{ package }}"

nginx/tasks/n2.yaml
---
- name: nginx.conf
  template:
    src: nginx.conf
    dest: /etc/nginx/
  notify: restart nginx

- name: keepalived.conf
  template:
    src: keepalived.conf
    dest: /etc/keepalived/
  notify: restart keepalived

- name: copy check.sh
  copy:
    src: check.sh
    dest: /etc/keepalived/
    mode: "0755"

nginx/tasks/n3.yaml
- name: index.html
  copy:
    content: ansible1
    dest: /usr/share/nginx/html/index.html
  connection: local
- name: index.html
  copy:
    content: ansible2
    dest: /usr/share/nginx/html/index.html
  when: ansible_hostname == "ansible2"
- name: index.html
  copy:
    content: ansible3
    dest: /usr/share/nginx/html/index.html
  when: ansible_hostname == "ansible3"

各目录下的文件:

nginx
├── defaults
│   └── main.yaml
├── files
│   └── check.sh
├── handlers
│   └── main.yaml
├── meta
│   └── main.yaml
├── tasks
│   ├── main.yaml
│   ├── n1.yaml
│   ├── n2.yaml
│   └── n3.yaml
├── templates
│   ├── keepalived.conf
│   └── nginx.conf
└── vars
    └── main.yaml

        设置自己的角色搜索目录,编辑/etc/ansible/ansible.cfg配置文件,设置roles_path选项,此项默认是注释掉的,将注释符去掉,当你想要设置多个路径时,多个路径之间用冒号隔开,示例如下:

roles_path    = /etc/ansible/roles:/tmp/roles:/roles

除了使用”-e”传入的变量的优先级,其他变量(包括主机变量)的优先级均低于vars/main.yml中变量的优先级。

其实说白了,role角色就是将编写的剧本进行拆分,更加高效有序的管理文件,学到这里,相信大家对Ansible拥有了整体的认识,再接再厉。