Ansible - Roles的使用

Roles 的概念来自于这样的想法:通过 include 包含文件并将它们组合在一起,组织成一个简洁、可重用的抽象对象。这种方式可使你将注意力更多地放在大局上,只有在需要时才去深入了解细节。

Ad-Hoc 适用于临时命令的执行,Playbook 适合中小项目,而大项目一定要是有 Roles。Roles 不仅支持 Tasks 的集合,同时包括 var_files、tasks、handlers、meta、templates等。

  1. Roles 目录结构
  2. 调用过程解析
  3. handlers:动态变更
    1. 示例
  4. Files:文件传输
  5. Templates:模板替换

Roles 目录结构

Roles 严重依赖目录命名规则和目录摆放,所以目录的命名和目录位置都非常重要。下面是一个案例的目录结构:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
liuhao@liuhao-pc:~/ansible$ tree fab2ansible/
fab2ansible/
├── group_vars
│   └── all
├── roles
│   ├── git
│   │   ├── files
│   │   │   └── main.yml
│   │   ├── tasks
│   │   │   ├── create_dir.yml
│   │   │   ├── git_checkout.yml
│   │   │   ├── main.yml
│   │   │   └── static_git_pull.yml
│   │   └── vars
│   │   └── main.yml
│   └── user
│   ├── tasks
│   │   ├── main.yml
│   │   └── user-config.yml
│   └── vars
│   └── main.yml
└── userconf.yml

9 directories, 11 files

对应的模块调用结构:

Role 模块调用结构

调用过程解析

参考上图,下面来针对 roles 目录中的 git 模块进行剖析。

  1. group_vars/all 文件:定义 roles 变量
1
2
3
4
5
6
7
8
9
10
11
---
# 以下列出的变量对所有主机和组有效,即全局有效
flag: king
javaflag: java
tech: php
damn: '-'
git: git
svn: svn
package_dir: /srv/deploy/
project_dir: /srv/www/
project: cp

group_vars 目录下文件定义 Roles 中调用的变量,Roles 对应调用该目录同名文件中定义的变量,文件名为 all 的文件定义的变量是全局变量,针对所有的 Roles 有效。

  1. userconf.yml 文件:设置调用 Roles 的 git 模块。
1
2
3
4
5
6
7
8
---
# 该playbook用于初始化用户配置

- hosts: localhost
remote_user: root

roles:
- role: git

roles 为关键字,role:git 表示调用 roles 的 git 模块。如希望同时调用图中的 user 模块,于该行下同级别对齐添加如下配置即可。

1
- role: user
  1. roles/git/tasks/main.yml 文件:设置调用 git 模块实现的功能。
1
2
3
4
5
---

- include: create_dir.yml
- include: static_git_pull.yml
- import_playbook: git_checkout.yml

通过 include 引用其他功能模块。在新版本中 ansible2.4 中,include 用 import_playbook 替换:http://docs.ansible.com/ansible/latest/playbooks_reuse_includes.html

  1. create_dir.yml、git_checkout.yml、static_git_pull.yml 文件:设置我们希望完成的具体功能。
  • create_dir.yml
1
2
3
4
5
6
7
8
9
10
11
---  
- hosts: localhost
tasks:
- name: create_dir
file:
path: "{{ package_dir }}{{ project }}-release-{{ git_commit }}/{{ flag }}-{{ project }}"
owner: www
group: www
mode: 0755
recurse: yes
state: directory

{ { } } 在 Ansible 中表示变量引用, create_dir.yml 实现的功能是递归创建目录并设置了目录的相关属性。

  • static_git_pull.yml

作用是拉取指定的 git 版本至指定目录

1
2
3
4
5
6
7
8
9
---  
- hosts: localhost
tasks:
- name: Git pull
git:
repo: "{{ repository_static }}"
dest: "{{ package_dir }}{{ project }}-release-{{ git_commit }}/{{ flag }}-{{ project }}"
version: "{{ git_commit }}"
force: yes
  • git_checkout.yml

实现 Git 项目初始化,Checkout 最新代码至指定目录。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
---  
- hosts: localhost
tasks:
- name: Git init before git pull
command: /usr/bin/git fetch
args:
chdir: "{{ package_dir }}{{ project }}-release-{{ git_commit }}/{{ flag }}-{{ project }}"

- name: Git reset
command: /usr/bin/git reset --hard
args:
chdir: "{{ package_dir }}{{ project }}-release-{{ git_commit }}/{{ flag }}-{{ project }}"

- name: Git checkout
command: /usr/bin/git checkout {{ git_commit }}
args:
chdir: "{{ package_dir }}{{ project }}-release-{{ git_commit }}/{{ flag }}-{{ project }}"

handlers:动态变更

Roles 不仅支持 Tasks 调用,同时支持 vars、files、handlers、meta、templates 的调用。本节介绍 Handlers 在 Roles 中的使用技巧。

Handlers 通常和 Notify 搭配使用,当(文件、进程、返回等)状态有变换时,Notify 会通过 Handlers 做指定的变更。我们通过一个功能完整的 Roles 来整体了解 Vars、Files、Handlers、Meta、Templates,然后逐步深入 Roles Handlers 用法。请看示例 example.yml:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
site.yml
webservers.yml
fooservers.yml
roles/
common/
files/
templates/
tasks/
handlers/
vars/
defaults/
meta/
webservers/
files/
templates/
tasks/
handlers/
vars/
defaults/
meta/

example.yml 包含两个 Role, common 和 webservers,每个 Role 均包括 files、templates、tasks、handlers、vars、defaults、meta。在 Playbooks 中的调用方式如下:

1
2
3
4
5
---  
- hosts: webservers
roles:
- common
- webservers

了解了 Roles 支持的功能集和调用方式后,我们再来了解这些功能集的含义。

  • roles/x/tasks/main.yml:主函数,包括在其中的所有任务将被执行
  • roles/x/handlers/main.yml:所有包括在其中的 handlers 将被执行
  • roles/x/vars/main.yml:所有包括在其中的变量将在 roles 中生效
  • roles/x/meta/main.yml:roles 所有依赖将被正常登入。
  • roles/x/{files,templates,tasks}/(dir depends on task):所有文件、模板都可存放在这里,不用指定绝对路径

示例

当 Apache 配置文件发生变化时重启 Apache。

  1. 编排 Roles 目录结构
1
2
3
4
5
6
7
8
9
10
11
.
├── apache.yml
└── roles
└── apache
├── handlers
│   └── main.yml
└── tasks
├── main.yml
└── restart.yml

4 directories, 4 files
  1. 编辑 roles/apache/handlers/main.yml 的内容
1
2
3
4
---  
# sleep 10s
- name: restart apache
service: name=httpd state=restarted

该 YML 要实现的功能非常简单:重启 Apache 进程。

  1. 编辑 roles/apache/tasks/restart.yml 内容
1
2
3
4
5
6
7
8
---
- name: transfer apache config
lineinfile:
path: /etc/httpd/conf/httpd.conf
regexp: '^Listen 80'
line: 'Listen 801'
notify:
- restart apache

该 YML 功能为更新 Apache 配置文件,如配置文件有变化则重启 Apache。

  1. 编辑 roles/apache/tasks/main.yml 内容
1
2
3
---

- import_tasks: restart.yml
  1. 编辑 Roles 同级目录 apache.yml 文件内容
1
2
3
4
5
---  
- hosts: webserver
remote_user: root
roles:
role: apache

该 YML 为总调度文件,完成 Apache 配置文件的变更和 Apache 的重启工作。

  1. 执行命令 ansible-playbook apache.yml,验证结果。

命令运行结果为更新 Apache 配置文件,如配置文件有更新则重启 Apache,如无错误返回为正常。

Files:文件传输

Files 和 Templates 均用于 Ansible 文件处理,两者主要区别是:Files(不是 file 模块)目录下的文件无需写绝对路径即可将文件传输至远程主机;Templates 目录下的文件以 Jinja2 渲染,且传输文件至远程主机的同时支持预定义变量替换。接下来我们看 Roles 中 Files 的使用方式。

案例场景:将 example role 下的 MAGEDU.PPT 和 STANLEY.PPT 两个文件传输至远程,并修改文件名为英文小写。

  1. 编排目录结构如下
1
2
3
4
5
6
7
8
9
10
11
12
13
[root@centos7 file]# tree
.
├── file.yml
└── roles
└── example
├── files
│   ├── MAGEDU.PPT
│   └── STANLEY.PPT
└── tasks
├── file.yml
└── main.yml

4 directories, 5 files
  1. 依次创建文件 MAGEDU.PPT、STANLEY.PPT,在文件中随意添加内容。

  2. 编辑 ./file.yml

1
2
3
4
5
6
7
---  
# 该playbook是整个项目的调度入口
- hosts: localhost
remote_user: root
gather_facts: false
roles:
- role: example
  1. 编辑 ./roles/example/tasks/file.yml
1
2
3
4
5
6
7
8
9
10
---
- name: file change example
copy:
src: "{{ item.src }}"
dest: "/data/{{ item.dest }}"
owner: root
group: root
with_items:
- { src: 'MAGEDU.PPT',dest: 'magedu.ppt' }
- { src: 'STANLEY.PPT',dest: 'stanley.ppt' }
  1. 编辑 ./roles/example/tasks/main.yml
1
2
3
--- 

- import_tasks: file.yml
  1. 执行命令 ansible-playbook file.yml,验证结果。

Roles 的 Files 功能设计主要针对业务文件传输需求,凡存放于对应的 Roles 的 Files 目录下的文件,传输时只需指定相对路径即可,这在很大程度上保证了管理机故障迁移时 Ansible 的健壮性,同时也从规则上使使用者有意规范自己的文件存放习惯。

在企业中不仅会遇到文件传输的需求,对于应用的配置文件,针对不同的主机需要进行相应的变更该怎么办呢?Templates 可以满足我们需求。

Templates:模板替换

Templates 常被用作传输文件,同时支持预定义变量替换。因 Templates 由 Jinja2 渲染格式,Jinja2 官网 http://jinja.pocoo.org/

案例场景:将 order.j2 分发至远程主机 /data// 目录下,并改名为 order.conf,且替换配置文件中变量为对应的值。

  1. 编排目录如下
1
2
3
4
5
6
7
8
9
10
11
12
├── roles
│   └── template
│   ├── tasks
│   │   ├── main.yml
│   │   └── template.yml
│   ├── templates
│   │   └── order.j2
│   └── vars
│   └── main.yml
└── template.yml

5 directories, 5 files
  1. 编辑 template.yml 任务总调度文件
1
2
3
4
5
6
7
---
# 该playbook是整个项目的调度入口
- hosts: localhost
remote_user: root
gather_facts: false
roles:
- role: template

该 YML 文件是任务总调用文件,主要指定远程主机、执行用户、调用的roles等,相当于「总指挥」的角色。

  1. 编辑 roles/template/tasks/main.yml
1
2
3

---
- import_tasks: template.yml
  1. 编辑 roles/template/tasks/template.yml
1
2
3
4
5
---
- name: template example
template:
src: "order.j2"
dest: "/data/{{ PROJECT }}/order.conf"

的变量引用文件即本节伊始提到的 Jinja2 格式。源文件是 order.j2 ,远程目录及目的文件名分别是 /data// 和 order.conf。

  1. 编辑 roles/template/templates/order.j2 定义模板文件
1
2
3
project: {{ PROJECT }}  
switch: {{ SWITCH }}
dbport: {{ DBPORT }}
  1. 编辑 roles/template/vars/main.yml 定义变量
1
2
3
4
5
---  

PROJECT: "JAVA"
SWITCH: "ON"
DBPORT: "3306"
  1. 执行命令并看返回及结果
1
2
3
4
5
6
7
8
9
10
11
12
13
14
[root@centos7 template]# ansible-playbook template.yml 

PLAY [localhost] *********************************************************************************************************************

TASK [template : template example] ***************************************************************************************************
changed: [localhost]

PLAY RECAP ***************************************************************************************************************************
localhost : ok=1 changed=1 unreachable=0 failed=0

[root@centos7 template]# cat /data/JAVA/order.conf
project: JAVA
switch: ON
dbport: 3306
hoxis wechat
一个脱离了高级趣味的程序员,关注回复1024有惊喜~
赞赏一杯咖啡
  • 本文作者: hoxis | 微信公众号【不正经程序员】
  • 本文链接: https://hoxis.github.io/ansible-roles.html
  • 版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 3.0 许可协议。转载请注明出处!
  • 并保留本声明和上方二维码。感谢您的阅读和支持!
0%