1
2
3
4
5
作者:李晓辉

微信联系:Lxh_Chat

联系邮箱: 939958092@qq.com

委派任务

有时候,Ansible 在执行 playbook 时,需要确保系统配置正确,但有些任务必须在别的系统上运行,而不是当前的受管主机上。

简单来说,delegate_to 就是让 Ansible 把某个任务丢给另一台机器去执行,而不是当前的受管主机。

比如,假设你有几台服务器要安装软件,装完之后,你想在 一台日志服务器 里记录一下安装情况。这时候,你就可以在记录日志的任务里加上 delegate_to: 日志服务器,这样安装软件的任务还是在各自的服务器上跑,但日志记录的部分就被“委派”到日志服务器上了。

更酷的是,被委派的主机 甚至不需要在 Ansible 的 inventory 里,只要能 SSH 过去或者能执行相应的 API 请求就行!这样就更灵活了,比如你可以让某台受管主机去调用一个外部 API,而不用把 API 服务器放进 Ansible 清单里。是不是很方便?

假设你有一组 Web 服务器 (web1web2),你需要在它们上面安装 Nginx,并且每装完一台,就要把安装结果记录到一台日志服务器 (logserver) 上。这里 delegate_to 就派上用场了:

1
2
3
4
5
6
7
8
9
10
11
12
- name: 安装 Nginx 并记录日志
hosts: web_servers
become: yes
tasks:
- name: 安装 Nginx
ansible.builtin.yum:
name: nginx
state: present

- name: 记录安装情况到日志服务器
ansible.builtin.command: echo "{{ inventory_hostname }} 安装完成" >> /var/log/install.log
delegate_to: logserver

这里用了 delegate_to: logserver,所以 echo 命令不会在 web1web2 上执行,而是跳到 logserver 上执行。这样,你既能让 web1web2 分别执行安装任务,又能让 logserver 负责集中记录安装情况,是不是很实用?

委派到执⾏环境时的注意事项

1
2
3
4
5
6
7
8
9
10
11
- name: 收集磁盘使用情况并在本地打印
hosts: web_servers
tasks:
- name: 获取磁盘使用情况
ansible.builtin.command: df -h
register: disk_usage

- name: 在本地打印结果
ansible.builtin.debug:
msg: "{{ inventory_hostname }} 磁盘使用情况:\n{{ disk_usage.stdout }}"
delegate_to: localhost

RHAAP2引入了 自动化执行环境(Execution Environment,EE),这让 delegate_to: localhost 的行为有了一些变化。

以前,你用 ansible-playbook 运行 playbook,delegate_to: localhost 任务会直接在 控制节点(本机) 执行。

但是,现在如果你用 ansible-navigator 来执行 playbook,delegate_to: localhost 任务 会跑在自动化执行环境的容器里,而不是裸机上

换句话说,localhost 现在默认是在 执行环境容器 里,而不是真正的控制节点。如果你的任务需要访问本机的资源(比如文件系统、数据库、网络服务),那就要注意这个变化,可能需要 挂载目录 或者 改用 delegate_to: <控制节点的实际主机名> 来确保它在物理机上运行。

总之,执行环境 = 容器,所以 localhost 也被“容器化”了,跟以前裸跑 playbook 时的行为不太一样。用 ansible-navigator 运行的时候,得注意别踩坑了!

委派facts

delegate_factsdelegate_to 的一个小伙伴,专门用来处理 委派任务时的 facts 变量

当你用 delegate_to 把任务委派到别的主机上,默认情况下,Ansible 只会收集 当前受管主机 的 facts,而不会去获取被委派主机的 facts。
如果你想让被委派的主机的 facts 也能用,那就需要 delegate_facts: true

举个例子:

假设你有一台 web 服务器,它需要知道 db 服务器的 IP 地址,但你不想单独去 db 主机执行 setup 模块来收集 facts,你可以这样做:

1
2
3
4
5
6
7
8
9
10
11
- name: 获取 DB 服务器信息并在 Web 服务器上使用
hosts: web
tasks:
- name: 获取 DB 服务器的 facts
ansible.builtin.setup:
delegate_to: db
delegate_facts: true

- name: 显示 DB 服务器的 IP
ansible.builtin.debug:
msg: "数据库服务器的 IP 是 {{ hostvars['db']['ansible_default_ipv4']['address'] }}"

发生了什么?

  1. setup 任务被 委派db 服务器上执行,所以 db 的 facts 会被收集。
  2. delegate_facts: truedb 服务器的 facts 存入 hostvars['db'],这样 web 服务器也能访问 db 的信息。
  3. debug 任务里,我们就能用 hostvars['db']['ansible_default_ipv4']['address'] 拿到 db 的 IP 地址,在 web 服务器上使用。

如果没有 delegate_facts: true 会怎样?

如果去掉 delegate_facts: truedb 的 facts 不会 存入 hostvars,所以 web 服务器根本拿不到 db 的 IP。
相当于 setup 任务只是执行了一下,但没把数据共享出来,白跑了

适用场景

  • 让一台服务器获取 另一台服务器的 facts(比如 db 获取 web 的信息)。
  • 需要跨主机获取系统信息,而不想专门去执行 setup 模块。
  • 让一个 playbook 里的主机互相“共享”自己的 facts,避免重复查询。

这东西说白了就是:delegate_to 过去的任务,顺便把 facts 带回来,不然默认是拿不到的!