Ansible角色 使用Ansible角色可以有更多的机会去重用以前便携的Playbook中的代码。可以在标准化目录结构中打包所有任务、变量、文件、模版以及调配基础架构或部署应用其他资源。
除了自行编写、使用角色外,也可从其他来源获取角色。常用红帽企业Linux管理角色包含在rhel-system-roles软件包中可以方便的去使用。也可以从Ansible Galaxy网站获取由社区提供的其他角色。
使用ansible-galaxy list可以看到在在当前Ansible配置环境下找到了Role角色列表。
那么Ansible怎么发现这些Role呢?这些Role的路径在ansible.cfg配置文件中已经定义好了,每个目录之间通过冒号分隔:
[defaults] inventory =./inventoryremote_user =devopsroles_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文件来定义。与其他变量一样,使用这些变量需要在角色文件中引入{{ VARS_NAME }}。这些变量具有较高的优先级,无法被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_vars或host_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角色任务:
--- - 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变量:
v2ray_download_from: "Github" v2ray_download_path: "/tmp/v2ray" v2ray_config: "files/v2ray.conf" v2ray_present: true 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