0%

Ansible 角色

Ansible角色

使用Ansible角色可以有更多的机会去重用以前便携的Playbook中的代码。可以在标准化目录结构中打包所有任务、变量、文件、模版以及调配基础架构或部署应用其他资源。

除了自行编写、使用角色外,也可从其他来源获取角色。常用红帽企业Linux管理角色包含在rhel-system-roles软件包中可以方便的去使用。也可以从Ansible Galaxy网站获取由社区提供的其他角色。

使用ansible-galaxy list可以看到在在当前Ansible配置环境下找到了Role角色列表。

那么Ansible怎么发现这些Role呢?这些Role的路径在ansible.cfg配置文件中已经定义好了,每个目录之间通过冒号分隔:

[defaults]
inventory=./inventory
remote_user=devops
roles_path=./roles:/usr/share/ansible/roles:/etc/ansible/roles

Ansible角色子目录

子目录 描述
defaults 此目录中的main.yml文件包含角色变量的默认值,使用角色时可以覆盖这些默认值。这些变量的优先级较低,应该在Play中更改和定义。
files 此目录包含由角色要处理的全部静态文件
handles 此目录中的main.yml文件包含角色的处理程序
meta main.yml中包含角色相关信息,如作者、许可证、平台、角色依赖项
tasks main.yml中包含角色任务的定义
templates 此目录包含角色引用的template模板
tests 此目录包含清单和test.yml Playbook,用于进行测试
vars 此目录的main.yml文件定义角色的变量值。这些变量通常用于角色内部用途。这些变量的优先级较高,不应在Playbook中覆盖修改

定义变量和默认值

对于角色变量可以通过在vars目录下的main.yml文件来定义。与其他变量一样,使用这些变量需要在角色文件中引入。这些变量具有较高的优先级,无法被Ansible中清单变量覆盖。

默认变量在defaults目录下的main.yml文件中定义。它们的变量优先级是最低的,任何定义变量的形式都会将其覆盖,所以更改默认变量可以使Play操作更精准、更适合受控主机。

可以在vars/main.yml或defaults/main.yml中定义具体的变量,但没必要在两者中都定义变量。

在Playbook中使用Ansible角色

可以在Play中引入roles即可使用。

- hosts: remote server
roles:
- role1
- role2

角色中使用的任何copy、script、template或include_tasks/import_tasks任务都可以引用角色中相关的文件、模版或任务文件,并且无需使用相对路径或绝对路径,因为Ansible会自动在角色的files、templates、tasks子目录下去寻找他们。

控制执行顺序

在Ansible中的每一个Play是会按照Play的顺序依次执行。在每个Play中如果定义了角色,那么会优先运行角色,之后再运行任务。在最后执行被激活的handles处理程序。

在某些情况下,可能需要在执行角色任务之前执行一些任务,你可以为Play配置pre_tasks部分,这样就可以在运行角色之前执行一部分任务。如果配置在pre_tasks中的任务出发了handles处理程序。那么也会在角色或其他普通任务之前执行处理程序。

当然也可以使用为Play配置post_tasks部分,来让任务在普通任务之后和激活的处理程序之后再运行。

---
- name: Play to illustrate order
hosts: example.com
pre_tasks:
- debug:
msg: "I am pre task"
notify: my handler
roles:
- role1
tasks:
- debug:
msg: "I am nomal task"
notify: my handler
post_tasks:
- debug:
msg: "I am posted handler"
...

上面的例子中,每个任务部分都会执行debug任务来通知my handler处理程序。my handler任务执行了三次:

  • 第一次在执行了所有的pre_tasks任务后执行处理程序
  • 第二次在执行角色结束后的普通tasks任务后执行
  • 第三次是在执行完post_tasks任务后执行处理程序

除了将角色包含在Play中的roles部分外,也可以将角色添加到普通的tasks中。使用include_role模块可以动态包含角色,使用import_role模块可以静态导入角色。

---
- name: Execute a role as a task
hosts: localhost
tasks:
- name: a simple task
debug:
msg: "Im first task"

- name: "A task to include role here"
include_role:
name: linux-system-roles.network
...

RHEL 系统角色

RHEL红帽系统中,从Linux 7.4开始,系统内随附了多个Ansible角色。它们位于rhel-system-roles软件包内。RHEL8中,需要启动AppStream仓库来安装此软件包。

角色名 描述
rhel-system-roles.kdump 配置kdump崩溃恢复服务
rhel-system-roles.network 配置网络
rhel-system-roles.postfix 配置postfix服务为每个主机配置邮件传输代理
rhel-system-roles.selinux 配置和管理SELinux自定义,包括模式、文件、端口上下文、布尔值设置和SELinux用户
rhel-system-roles.timesync 使用网络时间协议配置时间同步

访问RHEL系统角色文档

安装后,这些RHEL系统角色文档存放在/usr/share/doc/rhel-system-roles中,其中还包含了如何去使用以及使用的例子。

├── kdump
│   ├── COPYING
│   ├── README.html
│   └── README.md
├── network
│   ├── example-bond-with-vlan-playbook.yml
│   ├── example-bridge-with-vlan-playbook.yml
│   ├── example-down-profile-playbook.yml
│   ├── example-eth-simple-auto-playbook.yml
│   ├── example-eth-with-vlan-playbook.yml
│   ├── example-infiniband-playbook.yml
│   ├── example-inventory
│   ├── example-macvlan-playbook.yml
│   ├── example-remove-profile-playbook.yml
│   ├── LICENSE
│   ├── README.html
│   └── README.md
├── postfix
│   ├── COPYING
│   ├── README.html
│   └── README.md
├── selinux
│   ├── COPYING
│   ├── example-selinux-playbook.yml
│   ├── README.html
│   └── README.md
└── timesync
├── COPYING
├── example-timesync-playbook.yml
├── example-timesync-pool-playbook.yml
├── README.html
└── README.md

时间同步角色例子

如果为受控主机配置NTP时间同步服务,那么可以使用rhel-system-roles.timesync角色自动化配置。

通过/usr/share/doc/rhel-system-roles/timesync/README.md查看示例和需要用到的变量。

---
- name: Config NTP sync service
hosts: all
vars:
timesync_ntp_servers:
- hostname: 0.rhel.pool.ntp.org
iburst: yes
- hostname: 1.rhel.pool.ntp.org
iburst: yes
timezone: Asia/Shanghai
roles:
- rhel-system-roles.timesync

tasks:
- name: Set TimeZone
timezone:
name: "{{ timezone }}"
...

也可以把在Play中定义的变量放到变量文件中。将变量文件可以放到group_varshost_vars子目录中。

配置SELinux角色

使用linux-system-roles.selinux角色控制SELinux行为。t

通过/usr/share/doc/rhel-system-roles/selinux/README.md查看示例和需要用到的变量。

设置SELinux运行模式

变量 selinux_state: enforcing。可以设置为enforing、permissive、disabled。如果不设置则不更改。

设置SELinux布尔值

例如将httpd_enable_homedirs布尔值永久设置为no

selinux_booleans:
- name: 'http_enable_homedirs'
state: 'on'
persistent: 'yes'

设置SELinux fcontext上下文

下面的例子完成了对/srv/www目录下的所有文件的默认SELinux类型设置为httpd_sys_content_t

selinux_fcontexts:
- target: '/srv/www(/.*)?'
setype: 'httpd_sys_content_t'
state: present

使用selinux_restore_dirs变量指定要对其运行restorecon目录的列表。

设置SELinux端口

使用selinux_ports变量可以对端口进行管理。

selinux_ports: 
- ports: '82'
setype: 'http_port_t'
proto: 'tcp'
state: 'present'

创建角色框架

创建角色不需要额外的开发工具,角色是文件目录结构和文件组成的。可以使用创建目录和编辑文件命令配合完成创建一个角色框架。为了节省时间,可以使用ansible-galaxy init来创建角色框架。

ansible-galaxy init my_role

$ ls my_role/
defaults files handlers meta README.md tasks templates tests vars

默认变量的覆盖

在以下情况中,角色中defaults目录中定义的默认变量会被覆盖:

  • 在清单文件中定义,作为主机变量或组变量
  • 在playbook项目的group_vars或hosts_vars目录下的YAML文件中定义
  • 作为变量嵌套Play的vars关键字中定义
  • 在Play的定义roles角色时的所定义的变量

安装V2ray-core服务角色示例

功能如下:

  • 自动安装最新版本
  • 按照受控节点平台自动选择platform平台
  • 可以选择从Github/Jsdelivr/用户自定义V2ray-core地址下载
  • 可以控制卸载

Tasks角色任务:

---
# tasks file for v2ray
- name: Prepare to Install V2ray-core
block:
- name: V2ray download path is exist
file:
path: "{{ v2ray_download_path }}"
state: directory
mode: 0755
- set_fact:
install_error: false

when: v2ray_present

- name: Get the latest V2ray version and servers info
block:

- name: Get Server machine platform
shell: |
case "${1:-"{{ ansible_facts.machine }}"}" in
i686|i386)
echo '32'
;;
x86_64|amd64)
echo '64'
;;
*armv7*|armv6l)
echo 'arm'
;;
*armv8*|aarch64)
echo 'arm64'
;;
*mips64le*)
echo 'mips64le'
;;
*mips64*)
echo 'mips64'
;;
*mipsle*)
echo 'mipsle'
;;
*mips*)
echo 'mips'
;;
*s390x*)
echo 's390x'
;;
ppc64le)
echo 'ppc64le'
;;
ppc64)
echo 'ppc64'
;;
*)
return 1
;;
esac
register: return_machine
- name: Get the latest V2ray version and servers info
shell: >
curl -H "Accept: application/json" -H "User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:74.0) Gecko/20180101 Firefox/74.0" -s "https://api.github.com/repos/v2ray/v2ray-core/releases/latest" --connect-timeout 10| grep 'tag_name' | cut -d\" -f4
register: return_version
args:
warn: false
- set_fact:
latest_v2ray: "{{ return_version.stdout_lines[0] }}"
machine: "{{ return_machine.stdout }}"
rescue:
- name: "ERROR: Get the latest V2ray version and servers info. Please check your Network Connection and V2ray-core version"
set_fact:
install_error: true
when: v2ray_present and not install_error

- name: Download V2ray-core
block:
- name: "Download V2ray-core{{ latest_v2ray }} from jsdelivr"
get_url:
url: "https://cdn.jsdelivr.net/gh/v2ray/dist/v2ray-linux-{{ machine }}.zip"
dest: "{{ v2ray_download_path }}"
when: v2ray_download_from == "jsdelivr"
- name: "Download V2ray-core{{ latest_v2ray }} from Github"
get_url:
url: "https://github.com/v2ray/v2ray-core/releases/download/{{ latest_v2ray }}/v2ray-linux-{{ machine }}.zip"
dest: "{{ v2ray_download_path }}"
when: v2ray_download_from == "Github"
- name: "Download V2ray-core{{ latest_v2ray }} from {{ v2ray_download_from }}"
get_url:
url: "{{ v2ray_download_from }}"
dest: "{{ v2ray_download_path }}"
when: |
v2ray_download_from != "jsdelivr"
and
v2ray_download_from != "Github"
rescue:
- name: "ERROR: Download V2ray-core. Please check your Network Connection and V2ray-core version"
set_fact:
install_error: true
when: v2ray_present and not install_error


- name: Unarchive V2ray-core
block:
- name: Create unarchive V2ray-core directory
file:
path: "{{ v2ray_download_path }}/v2ray-linux-{{ machine }}"
state: directory
mode: 0755
- name: Unarchive V2ray-core
unarchive:
src: "{{ v2ray_download_path }}/v2ray-linux-{{ machine }}.zip"
dest: "{{ v2ray_download_path }}/v2ray-linux-{{ machine }}"
remote_src: true
rescue:
- name: "ERROR: Unarchive V2ray-core. Please check your platform"
set_fact:
install_error: true
when: v2ray_present and not install_error

- name: Install V2ray-core and Start V2ray-core
block:
- name: Create V2ray install directory
file:
path: "{{ item }}"
state: directory
mode: 0755
loop: "{{ v2ray_installed_dir }}"
- name: Copy binary file into directory
copy:
src: "{{ v2ray_download_path }}/v2ray-linux-{{ machine }}/{{ item.src }}"
dest: "{{ item.dest }}"
remote_src: true
mode: 0755
loop: "{{ v2ray_binary }}"
- name: Copy V2ray config and Start V2ray-core
copy:
src: "{{ v2ray_config }}"
dest: /etc/v2ray/config.json
mode: 0755
notify: Start V2ray Service
rescue:
- name: "ERROR: Install V2ray-core. Please check your permissions"
set_fact:
install_error: true
when: v2ray_present and not install_error


- name: Remove v2ray-core
block:
- name: Stop V2ray-core service
systemd:
name: v2ray.service
daemon_reload: true
enabled: false
state: stopped
ignore_errors: true
- name: Remove V2ray-core service
file:
path: /etc/systemd/system/v2ray.service
state: absent
- name: Remove v2ray-core file
file:
path: "{{ item }}"
state: absent
loop: "{{ v2ray_installed_dir }}"

when: not v2ray_present or install_error

- name: Check remove result
debug:
msg: Removed v2ray-core
when: not v2ray_present

- name: Check install result
debug:
msg: Install V2ray-core Failure
failed_when: yes
when: v2ray_present and install_error

- name: Check install result
debug:
msg: Install V2ray-core Successful
when: v2ray_present and not install_error

Default变量:

# You can download the latest V2ray-core from Github/jsdelivr/(https://yourself)
v2ray_download_from: "Github"
v2ray_download_path: "/tmp/v2ray"
v2ray_config: "files/v2ray.conf"

# user_control_boolean
v2ray_present: true

# Ansible Role Control vars (Don't change it!!!)
v2ray_installed_dir:
- /etc/v2ray
- /var/log/v2ray
- /usr/bin/v2ray
- "{{ v2ray_download_path }}"
v2ray_binary:
- src: geoip.dat
dest: /usr/bin/v2ray
- src: geosite.dat
dest: /usr/bin/v2ray
- src: v2ctl
dest: /usr/bin/v2ray
- src: v2ray
dest: /usr/bin/v2ray
- src: systemd/v2ray.service
dest: /etc/systemd/system
  • 本文作者: YeeFire
  • 本文链接: https://blog.yeefire.com/2020_06/ansible_role.html
  • 版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。您可以自由复制、散布、展示及演出本作品;若您改变、转变或更改本作品,仅在遵守与本作品相同的许可条款下,您才能散布由本作品产生的派生作品!由于本人水平有限,不保证作品内容准确无误,亦不承担任何由于使用此作品所导致的损失。

欢迎关注我的其它发布渠道