Ansible 角色管理
异步并行
配置 async
ansible 默认行为:必须等当前任务执行完成,才能执行下一个任务。
有些操作需要很长时间才能完成,例如下载一个大文件,重启服务器等。使用异步并行模式,ansible可以很快在受管主机上这些执行命令,但是需要等待命令执行完成才能将主机置于相应状态。
Ansible使用async触发异步并行运作任务:
- async:async的值是ansible等待运行这个任务的最大超时值(如果执行超时任务会强制中断导致失败)。
- poll:ansible检查这个任务是否完成的时间间隔。ansible poll_interval 默认值是 15。
示例1: 任务执行失败,在规定时间内容任务没有执行完成。
---
- name: connection
hosts: node1
tasks:
- name: conneciton
shell: sleep 10
async: 5
poll: 2
示例2: 放入后台下载,立刻执行下一个任务。
---
- name: connection
hosts: node1
tasks:
- name: download
get_url:
url: http://192.168.48.100/ISOS/openEuler-24.03-LTS-x86_64-dvd.iso
dest: /home/yy
async: 100
poll: 0
示例3: ansible 默认行为,等该任务执行完,再执行下一个任务。
---
- name: connection
hosts: node1
tasks:
- name: conneciton
shell: sleep 10
async: 0
poll: 2
async_status 模块
使用 async_status 模块检查之前的任务是否运行完成。
与async配套使用
示例:
---
- name: test async_status
hosts: node1
tasks:
- shell: sleep 10
async: 20
poll: 0
register: out
- name: wait for
async_status:
# 通过任务的 ansible_job_id 属性跟踪任务
jid: "{{ out.ansible_job_id }}"
register: job_result
# 根据当前任务执行结果的finished值,判断跟踪任务是否执行完成
until: job_result.finished
retries: 30
delay: 2
选项说明:
- retries,设置重试次数,默认值为3。
- delay,设置检测时间间隔,默认5秒检测一次
wait_for 模块
使用 wait_for 模块检查之前的任务是否达到预期状态。
示例1: 测试文件是否存在
---
- name: test wait for
hosts: node1
tasks:
- shell: sleep 10 && touch /tmp/hello
# async时间要大于sleep的时间
async: 20
poll: 0
register: out
- name: wait for create /tmp/hello
wait_for:
path: /tmp/hello
state: present
delay: 5
timeout: 30
sleep: 2
选项说明:
- delay,设置检测前延迟时间。
- timeout,设置检测超时时间。
- sleep,设置检测时间间隔。
示例2: 测试主机端口是否打开
---
- name: test wait_for
hosts: node1,node2
tasks:
- name: reboot node1
shell: shutdown -r now "Ansible updates triggered"
async: 1
poll: 0
when: inventory_hostname == "node1"
- name: wait for node1 come back
wait_for:
host: node1
port: 22
state: started
delay: 10
sleep: 2
timeout: 300
when: inventory_hostname == "node2"
Including 和 importing 文件
如果playbook很长或很复杂,可以将其分成较小的文件以便于管理。
采用模块化方式将多个playbook组合为一个main playbook或者将文件中的任务列表插入play。这样可以更轻松地在不同项目中重用play或任务。
ansible重用内容主要有两种方式:
- 使用任何 include 关键字任务(include_tasks、include_role 等),它将是动态的。
- 使用任何 import 关键字任务(import_playbook、import_tasks、import_role等),它将是静态的。
- 只使用include的任务(用于 task 级别和 Playbook 级别)仍然可用,**此功能将在 2.12 版中删除
playbook 级别
import_playbook 支持导入外部playbooks。
- 导入的内容是完整的playbook,只能在play级别使用。
- 导入的多个playbooks,则按导入顺序执行。
示例:
主剧本内容如下
- name: prepare the web server import_playbook: pre_web.yml - name: prepare the vsftpd server import_playbook: pre_vsftpd.yml - name: prepare the databse server import_playbook: pre_db.yml
pre_web.yml 内容如下:
cat > pre_web.yml << EOF - name: Play web hosts: node1 tasks: - name: install httpd yum: name: httpd state: present EOF
pre_vsftpd.yml 内容如下:
cat > pre_vsftpd.yml << EOF - name: Play vsftpd hosts: node1 tasks: - name: install vsftpd yum: name: vsftpd state: present EOF
pre_db.yml 内容如下:
cat > pre_db.yml << EOF - name: Play db hosts: node1 tasks: - name: install mariadb-server yum: name: mariadb-server state: present EOF
task 级别
示例:
主剧本内容如下:
--- - name: Install web server hosts: node1 tasks: - name: import a task file import_tasks: tasks.yaml #include: tasks.yaml #include_tasks: tasks.yaml
tasks.yaml 内容如下:
- name: Install the httpd yum: name: httpd state: present - name: Starts httpd service: name: httpd state: started
task 级别
示例:
主剧本内容如下:
--- - name: Install web server hosts: node1 tasks: - name: import a task file import_tasks: tasks.yaml #include: tasks.yaml #include_tasks: tasks.yaml
tasks.yaml 内容如下:
- name: Install the httpd yum: name: httpd state: present - name: Starts httpd service: name: httpd state: started
Ansible 角色
Ansible 角色介绍
可以把 Ansible 角色(Role)理解成 “预制好的‘功能工具箱’” —— 就像你组装家具时,商家会把 “拧螺丝的扳手、装木板的卡扣、贴防撞条的胶” 打包成一个 “组装套件”,不用你再零散找工具。
比如要部署一个网站,你不用在 Playbook 里写 “安装 nginx、改配置、传静态文件、启服务” 这些零散步骤,而是直接拿一个叫 “nginx_role” 的 “工具箱”:
- 这个 “箱子” 里早就按规矩分好了格子:
- “tasks” 格放着 “怎么装 nginx、怎么启服务” 的操作指南;
- “templates” 格塞着带变量的 nginx 配置模板(像能自动填服务器 IP 的填空题);
- “files” 格存着要传到服务器的静态网页文件;
- “handlers” 格里藏着 “配置改了就重启 nginx” 的触发开关。
用的时候也简单,在 Playbook 里写一句 “用 nginx_role 这个箱子”,Ansible 就会自动打开箱子,按顺序用里面的工具完成部署 —— 下次另一个项目要装 nginx,直接再拿这个 “箱子” 用,不用重新凑工具;团队里谁要改 nginx 配置,直接去 “templates” 格子里改模板就行,不用翻整个 Playbook。
在生产环境中play会更长更复杂,有许多包含或导入的文件,以及用于管理各种情况的任务和处理程序。
随着开发的playbook越来越多,有很多机会重复利用以前编写的playbook中的代码。例如,为某一应用配置MySQL数据库的play ,可以通过不同的主机名、用户和密码等为另一个应用配置MySQL数据库。
**Ansible提供了角色,可以轻松实现重复利用Ansible代码。**在准化目录结构中打包所有任务、变量、文件、模板,以及调配基础架构或部署应用所需的其他资源。只需将角色从一个项目复制到另一个项目,在play中调用该角色即可。
Ansible 角色结构
顶级目录定义角色本身的名称。子目录按照各个文件在角色中的用途进行命名:
- defaults,此目录中的main.yml文件包含角色变量的默认值。
- 几乎任何其他变量都会覆盖角色的默认变量,如清单变量 、play中vars声明的变量等。
- 这些变量旨在让人们在编写使用该角色的play时可以准确地自定义或控制它将要执行的操作,应该在play中更改和自定义default变量值。
- file,此目录包含由角色任务引用的静态文件。
- handlers,此目录中的main.yml文件包含角色的处理程序定义。
- meta,此目录中的main.yml文件包含与角色相关的信息,如作者、许可证、平台和可选的角色依赖项。
- tasks,此目录中的main.yml文件包含角色的任务定义。
- templates,此目录包含由角色任务引用的Jinja2模板。
- tests,此目录可以包含清单和test.yml playbook,可用于测试角色。
- vars,此目录中的main.yml文件定义角色变量值。
- vars中变量具有较高的优先级,facts、include_vars 加载的变量、register变量和角色参数可以覆盖角色vars目录中定义的变量。
- vars中变量优先级高于清单变量和play中vars声明的变量。在playbook中使用时不应更改。
- vars中变量旨在供角色的内部功能使用。
- README.md,提供人类可读的基本角色描述、有关如何使用该角色的文档和示例,以及其发挥作用所需要满足的任何非Ansible要求。
说明:并非每个角色都拥有所有目录,部分目录可以省略。
ansible-galaxy 命令后续详细介绍。
Ansible 角色目录位置
默认role使用以下三个目录:
- ~/.ansible/roles
- /usr/share/ansible/roles
- /etc/ansible/roles
优先级从上到下依次降低。
可以在ansible.cfg配置文件[defaults]块中通过变量roles_path定义role位置:
[defaults]
roles_path = ./roles
......
多个路径使用冒号分隔:
roles_path = /etc/ansible/roles:/home/student/web/roles
创建角色
[yy@controller web 11:30:08]$ vim ansible.cfg
[defaults]
roles_path = ./roles
[yy@controller web 11:28:04]$ mkdir roles
[yy@controller web 11:29:06]$ ansible-galaxy init apache
- Role apache was created successfully
[yy@controller web 11:29:26]$ mv apache/ roles
[yy@controller web 11:29:37]$ ansible-galaxy list
# /home/yy/web/roles
- apache, (unknown version)
[yy@controller web 11:32:03]$ cd roles/apache/
从tasks开始,tasks/main.yml内容如下:
--- # tasks file for apache - name: install web yum: name: "{{ web_package }}" state: latest - name: "start {{ web_service }}" service: name: "{{ web_service }}" state: started enabled: yes - name: prepare motd template: src: motd.j2 dest: /etc/motd - name: prepare yy site template: src: yy.conf.j2 dest: /etc/httpd/conf.d/yy.conf notify: - restart_web - name: prepare DocumentRoot file: path: "/var/www/html/{{ ansible_hostname }}" state: directory - name: prepare index.html template: src: index.html.j2 dest: "/var/www/html/{{ ansible_hostname }}/index.html"
defaults/main.yml vim 内容如下:
--- # defaults file for apache web_package: httpd web_service: httpd
templates/motd.j2 内容如下:
hello guys! Welcome to {{ ansible_fqdn }}!
templates/yy.conf.j2 内容如下:
# {{ ansible_managed }} <VirtualHost *:80> ServerAdmin yy@{{ ansible_fqdn }} ServerName {{ ansible_fqdn }} ErrorLog logs/{{ ansible_hostname }}-error.log CustomLog logs/{{ ansible_hostname }}-common.log common DocumentRoot /var/www/html/{{ ansible_hostname }}/ <Directory /var/www/html/{{ ansible_hostname }}/> Options +Indexes +FollowSymlinks +Includes Order allow,deny Allow from all </Directory> </VirtualHost>
handlers/main.yml 内容如下:
--- # handlers file for apache - name: restart_web service: name: "{{ web_service }}" state: restarted
templates/index.html.j2 内容如下:
Welcome to {{ ansible_fqdn }} !
meta/main.yml 内容如下:
--- galaxy_info: author: yy description: yy web company: yy world license: license (GPLv2, CC-BY, etc) min_ansible_version: 2.4 platforms: - name: Fedora versions: - all - 25 - name: SomePlatform versions: - all galaxy_tags: [apache,web] dependencies: []
调用角色
playbook中可以直接使用roles。role中的tasks,handlers,variables和依赖都会按顺序引入到playbook中。role中的任何copy,script,template或者include任务都可以引用相关文件、模板、任务,而且可以不指定绝对路径或者相对路径,Ansible会在role的files,templates和tasks目录中查找。
调用角色:
语法一:
--- - hosts: servers roles: - rolename
语法二:调用时候传递变量给角色。
--- - hosts: servers roles: - role: role1 var1: value1 - { role: role2, var2: value2, var3: value3 }
示例1:
---
- name: deploy apache
hosts: node1
roles:
- apache
使用系统角色
系统角色介绍
可以把 系统角色 理解成操作系统里的 “专职岗位”—— 就像公司里有 “财务岗”“行政岗”,每个岗位有固定职责,系统角色也有明确的 “权限范围”,规定了 “哪些操作能做、哪些不能做”,核心是帮系统管理权限、保障安全。
比如常见的系统角色:
- 管理员角色(如 Linux 的 root、Windows 的 Administrator):相当于 “公司老板”,拥有系统的 “全部权限”—— 能装软件、删文件、改核心配置,甚至能查看所有用户的文件,负责系统的 “全局管理”。
- 普通用户角色(如 Linux 的普通账号、Windows 的标准用户):像 “公司员工”,权限有限 —— 只能操作自己的文件(比如自己电脑里的文档),不能改系统核心设置(比如不能删系统文件、不能装需要全局权限的软件),避免误操作搞崩系统。
- 服务角色(如 Linux 的 nginx、mysql 账号):类似 “外包技工”,专门给某个程序 “打工”—— 比如 nginx 角色只负责运行 nginx 服务器,只能访问 nginx 的配置文件和网页文件,没有其他权限;就算程序出问题被攻击,也不会影响到系统其他部分,相当于 “隔离保护”。
简单说,系统角色就是给不同 “使用者”(人或程序)划好 “权限边界”,让该干活的能干活,不该碰的碰不到,既保证系统正常运行,又防止乱操作或攻击带来的风险。
自RHEL7.4开始,操作系统rhel-system-roles软件包提供多个Ansible角色。在RHEL8中,该软件包可从AppStream频道获取。系统角色的目的是标准化配置版本6.10及以上的任何RHEL主机。
举例而言,RHEL7的建议时间同步服务为chronyd服务,RHEL6的建议服务为ntpd服务。在混合了RHEL6和7主机的环境中,管理员必须管理这两个服务的配置文件。借助RHEL系统角色,管理员不再需要维护这两个服务的配置文件。管理员可以使用rhel-system-roles.timesync角色来配置RHEL6和7主机的时间同步。一个包含角色变量的简化YAML文件可以为这两种类型的主机定义时间同步配置。
系统角色安装和说明
[yy@controller ~]$ sudo yum install -y rhel-system-roles
# RHEL系统角色位于/usr/share/ansible/roles/
[yy@controller ~]$ ls -1 /usr/share/ansible/roles/
# Ansible默认roles_path包含/usr/share/ansible/roles,可以直接引用这些角色。
# 系统角色的文档位于/usr/share/doc/rhel-system-roles
[yy@controller ~]$ ls /usr/share/doc/rhel-system-roles
# 每个角色的文档目录均包含一个README.md文件。
# README.md文件含有角色的说明,以及角色用法信息。
# README.md文件也会说明影响角色行为的角色变量。
# README.md文件中含有playbook代码片段,用于演示常见配置场景的变量设置。
角色使用案例-timesync
rhel-system-roles.timesync角色说明文档位于/usr/share/doc/rhel-system-roles/timesync/README.md。此文件说明了影响角色行为的所有变量,还包含演示了不同时间同步配置的三个playbook代码片段。
为了手动配置NTP服务器,该角色具有一个名为timesync_ntp_servers的变量。此变量取一个要使用的NTP服务器的列表作为值。列表中的每一项均由一个或多个属性构成。
两个关键属性如下:
hostname,要与其同步的NTP服务器的主机名。
iburst,布尔值,用于启用或禁用快速初始同步。在角色中默认为no,但您通常应该将该属性设为yes。
示例:
- name: Manage timesync with 3 servers
hosts: all
vars:
timesync_ntp_servers:
- hostname: ntp.aliyun.com
iburst: true
roles:
- rhel-system-roles.timesync
[yy@controller web 13:57:29]$ vim ansible.cfg
roles_path = ./roles:/usr/share/ansible/roles
安装角色
# 安装角色(下载角色)
[yy@controller ~]$ ansible-galaxy install geerlingguy.haproxy
# 一次性安装多个角色
[yy@controller ~]$ vim requires.yml
# from galaxy
- name: docker
src: https://github.com/geerlingguy/ansible-role-docker/archive/2.7.0.tar.gz
- name: haproxy
src: https://github.com/geerlingguy/ansible-role-haproxy/archive/1.1.2.tar.gz
[yy@controller ~]$ ansible-galaxy install -r requires.yml
- downloading role from https://github.com/geerlingguy/ansible-role-docker/archive/2.7.0.tar.gz
- extracting docker to /root/.ansible/roles/docker
- docker was installed successfully
- downloading role from https://github.com/geerlingguy/ansible-role-haproxy/archive/1.1.2.tar.gz
- extracting haproxy to /root/.ansible/roles/haproxy
- haproxy was installed successfully