Ansible Roles
Ansible Role 就是 playbooks 的集合,举一个简单的例子,将配置 nginx 的 playbook、配置 php 的 playbook 和配置 mysql 的 playbook 组合到一块就可以是一个配置 lnmp 的角色。
常见的角色有三种:
- RHEL 自带的角色,通过
yum install rhel-system-roles
安装的角色是 RHEL 自带的角色 - 通过 https://galaxy.ansible.com/ui/ 角色仓库下载角色
- 红帽也有收费的角色,没用过。
RHEL 自带的系统角色安装后可以在
/usr/share/ansible/roles/
找到。
使用 Roles
使用角色需要通过 Playbook,以下是一个使用角色的 Playbook:
---
- name: use roles
hosts: servera
roles:
- role1
- role2
这个 Playbook 表示调用 role1
和 role2
两个角色。
角色的优先级会比 tasks
高,举个例子:
---
- name: use roles
hosts: servera
tasks:
- name: debug
ansible.builtin.debug:
msg: "Hello World!"
roles:
- role1
- role2
这个 YAML 的 tasks
虽然在 roles
的前边,但是 roles
会比 tasks
先执行。
创建一个自定义角色并使用
初始化一个角色
通过 ansible-galaxy role init
可以初始化一个角色。
[root@awx-1 ansible]# ansible-galaxy role init roles/test-role
- Role roles/test-role was created successfully
[root@awx-1 ansible]# ls roles
test-role
[root@awx-1 ansible]# tree roles/test-role/
roles/test-role/
├── defaults
│ └── main.yml
├── files
├── handlers
│ └── main.yml
├── meta
│ └── main.yml
├── README.md
├── tasks
│ └── main.yml
├── templates
├── tests
│ ├── inventory
│ └── test.yml
└── vars
└── main.yml
8 directories, 8 files
- defaults
- 作用:存放默认变量(优先级最低)。
- 文件:通常包含一个
main.yml
文件。 - 使用场景:为角色定义一些可被覆盖的默认变量值。
- vars
- 作用:定义角色内部使用的变量(优先级高于
defaults
)。 - 文件:通常也是
main.yml
。 - 注意:这些变量不容易被外部覆盖,一般用于角色内部逻辑所依赖的重要值。
- 作用:定义角色内部使用的变量(优先级高于
- files
- 作用:存放要通过
copy
模块或script
模块分发到目标主机的静态文件。
- 作用:存放要通过
- templates
- 作用:存放 Jinja2 模板文件(通常是
.j2
结尾)。 - 用途:动态生成配置文件,使用变量进行渲染。
- 配合模块:
template
模块使用。
- 作用:存放 Jinja2 模板文件(通常是
- tasks
- 作用:定义该角色的主要任务。
- 文件:必须包含
main.yml
,可通过include
引入其他任务文件。 - 用法:角色执行时从
tasks/main.yml
开始执行。
- handlers
- 作用:定义响应
notify
调用的任务,比如重启服务。 - 文件:也是
main.yml
,里面写name:
配合notify
。
- 作用:定义响应
- meta
- 作用:定义角色的元数据,比如依赖的其他角色、作者、许可等。
- 文件:常见的是
main.yml
。
- tests
- 作用:用于测试该角色的用例。
- 通常包含:
inventory
:测试主机清单test.yml
:用于调用该角色的 playbook
- README.md
- 作用:文档说明角色的用途、变量、使用方法等。
再来个简明总结
目录 | 作用简介 |
---|---|
defaults/ |
定义默认变量(优先级最低,易被覆盖) |
vars/ |
定义内部变量(优先级较高,不易被覆盖) |
files/ |
存放静态文件,配合 copy/script 模块使用 |
templates/ |
存放 Jinja2 模板,配合 template 模块使用 |
tasks/ |
定义主要任务入口,必须有 main.yml |
handlers/ |
定义被 notify 调用的处理器(如重启服务) |
meta/ |
定义角色依赖和元信息 |
tests/ |
存放测试 playbook 和 inventory |
README.md |
角色说明文档 |
上边做了这些目录的解释,下边针对这些目录做个简单配置。
配置角色
tasks
tasks
目录是最重要的目录,因为它定义了角色的任务。在 tasks
定义任务和 Playbook 有些不同,tasks
不需要声明被控主机,任务需要写到 main.yml
。以下是一个 tasks
目录下的文件内容:
[root@awx-1 ansible]# cat roles/test-role/tasks/main.yml
---
# tasks file for roles/test-role
- name: Print the role information
ansible.builtin.debug:
msg: "{{ ROLE_INFORMATION }}"
- name: Prinet default address
ansible.builtin.debug:
msg: "{{ ansible_facts[DEFAULT_NETCARD].ipv4.address }}"
- name: print hostname
ansible.builtin.debug:
var: ansible_hostname
- name: print system version
ansible.builtin.debug:
msg: System version is {{ ansible_distribution }} {{ ansible_distribution_version }}!
- name: set hosts
ansible.builtin.template:
src: templates/hosts.j2
dest: /etc/hosts
mode: 0644
owner: root
group: root
- name: copy motd to master node
ansible.builtin.copy:
src: files/motd
dest: /etc/motd
mode: 0644
owner: root
group: root
when: MASTER_NODE | default('') != ''
- name: copy motd to worker node
ansible.builtin.copy:
content: "Worker Node"
dest: /etc/motd
mode: 0644
owner: root
group: root
when: MASTER_NODE is not defined or not MASTER_NODE
- name: set PermitRootLogin
ansible.builtin.lineinfile:
path: /etc/ssh/sshd_config
regex: "[(# )|#]PermitRootLogin|^PermitRootLogin"
line: "PermitRootLogin yes"
notify: restart sshd
可以通过
ansible.builtin.include_task
和ansible.builtin.import_task
导入其他文件的任务。
handlers
[root@awx-1 ansible]# cat roles/test-role/handlers/main.yml
---
# handlers file for roles/test-role
- name: restart sshd
ansible.builtin.systemd:
name: sshd
state: restarted
listen: restart sshd
和 tasks
一样,写到 main.yml
下。
templates
这个目录是空的,需要在里边创建文件,这里创建了一个 hosts.j2
文件。
[root@awx-1 ansible]# cat roles/test-role/templates/hosts.j2
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
{% for host in groups['all'] %}
{{ hostvars[host].ansible_facts.default_ipv4.address }} {{ hostvars[host].ansible_facts.fqdn }} {{ hostvars[host].ansible_facts.hostname }}
{% endfor %}
files
和 templates
一样,需要自己创建文件。
[root@awx-1 ansible]# cat roles/test-role/files/motd
Master Node!
vars
定义变量,固定写在 main.yml
下。
[root@awx-1 ansible]# cat roles/test-role/vars/main.yml
---
# vars file for roles/test-role
ROLE_INFORMATION: "Test the Ansible role"
用于定义不需要修改赋值的变量。
defaults
定义默认变量,固定写在 main.yml
下。
[root@awx-1 ansible]# cat roles/test-role/defaults/main.yml
---
# defaults file for roles/test-role
DEFAULT_NETCARD: "eth0"
用于定义一些需要修改赋值的变量。
这里设置了一个变量
DEFAULT_NETCARD
为网卡名,用于打印网卡地址。默认是 eth0,如果被控服务器网卡名为其他的,比如 ens18,可以通过在其他地方重新给变量赋值以覆盖变量。
meta
用于定义 role
的描述信息,里边自带一个 main.yml
,文件里写了模板,按模板修改就行。
tests
用于测试,可以看现成的文件。
调用角色
# 设置角色路径
[root@awx-1 ansible]# grep roles_path ansible.cfg
roles_path=./roles
# 配置主机清单
[root@awx-1 ansible]# cat inventory
[k8s]
base-k8s-master-1 MASTER_NODE=true
base-k8s-worker-1
base-k8s-worker-2
[all:vars]
ansible_ssh_user = root
ansible_ssh_password = redhat
ansible_become = false
ROLE_INFORMATION = "test ansible inventory"
# 配置 Playbook
[root@awx-1 ansible]# cat roles.yml
---
- name: Use roles
hosts: k8s
roles:
- test-role
# 执行 Playbook,重新给 DEFAULT_NETCARD 赋值以覆盖默认变量
[root@awx-1 ansible]# ansible-playbook -e DEFAULT_NETCARD=ens18 roles.yml