首页/系统与基础设施/自动化运维速查/委派执行与单次执行的用法
Ansible 核心70 条

委派执行与单次执行的用法

委派把单个任务的执行目标换成另一台主机,单次执行让该任务在一批主机里只跑一次,两者常配合完成共享资源的单点操作。业务变量与主机名仍属于当前主机,连接设置按被委派主机解析;与滚动批次叠加时会按批重复。

​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌​​‌​‌‌‌‌​‌‌​​​​‌​‌‌‌​‌​‌​‌‌‌​‌​​​‌‌​‌‌‌‌​‌‌​‌‌​‌​‌‌​​​​‌​‌‌‌​‌​​​‌‌​‌​​‌​‌‌​‌‌‌‌​‌‌​‌‌‌​​​‌​‌‌‌‌​‌‌​​‌​​​‌‌​​‌​‌​‌‌​‌‌​​​‌‌​​‌​‌​‌‌​​‌‌‌​‌‌​​​​‌​‌‌‌​‌​​​‌‌​​‌​‌​​‌​‌‌​‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌​‌​‌‌‌​​‌​​‌‌‌​‌​‌​‌‌​‌‌‌​​​‌​‌‌​‌​‌‌​‌‌‌‌​‌‌​‌‌‌​​‌‌​​​‌‌​‌‌​​‌​‌​​‌​‌‌​‌​‌‌‌​‌​‌​‌‌‌​​‌‌​‌‌​​​​‌​‌‌​​‌‌‌​‌‌​​‌​‌​​‌​‌‌‌​​‌‌​‌​​​​‌‌‌​‌​​​‌‌​‌‌​‌​‌‌​‌‌​​

把任务放到别的主机上执行

默认情况下任务在“当前这台主机”上执行。委派机制允许把它改到另一台机器上执行,典型场景是共享资源的单点操作:把主机注册到负载均衡、在统一的登记系统里写一条记录。与之配套的单次执行开关让该任务在整批主机里只跑一次,避免同样的操作重复几十遍。

基本信息

委派执行把某个任务的执行目标换成另一台主机,连接按被委派主机建立
单次执行该任务在一批主机中只执行一次,通常与委派配合使用
变量归属连接相关变量按被委派主机解析,业务变量与事实仍属于当前主机
事实归属可通过开关决定采集到的事实记在当前主机还是被委派主机上
批次影响配合滚动批次使用时,单次执行会在每一批各执行一次
依赖前提被委派的目标需要在清单中可见,或使用本机这一特殊目标

典型使用场景

  • 负载均衡注册:所有主机装完后由控制节点统一更新一次后端列表
  • DNS 与配置中心:写共享记录只需一次,不必每台主机各写一遍
  • 控制节点上的编排动作:调用外部接口、拉取构件、生成证书请求
  • 绕过访问限制:只有某台跳板机能访问外部服务时,把动作委派给它
  • 共享锁与配额检查:全局性判断只应执行一次,避免并发争抢
  • 跨主机取值:需要读取另一台主机的状态时,把查询委派过去

写法与变量归属

写法与变量归属
- hosts: web
  tasks:
    - name: 每台主机各自装包
      ansible.builtin.package:
        name: app-server
        state: present

    - name: 只在控制节点执行一次,把主机登记到负载均衡
      ansible.builtin.uri:
        url: "http://lb.internal/api/backends"
        method: POST
        body_format: json
        body:
          host: "{{ inventory_hostname }}"      # 仍是当前主机的名字
          port: "{{ app_port }}"
      delegate_to: localhost
      run_once: true
      register: register_result

    - name: 单次执行注册的变量对整批主机可用
      ansible.builtin.debug:
        msg: "登记结果 {{ register_result.status }}"
      when: register_result is defined

    - name: 委派到另一台主机并让事实记在它名下
      ansible.builtin.setup:
        gather_subset: ['network']
      delegate_to: bastion1
      delegate_facts: true
      run_once: true

组合方式对照

组合行为适用
委派到本机在控制节点执行该任务调用接口、生成构件、写共享记录
委派到清单内主机在指定主机上执行,连接指向它跳板机动作、读取特定主机状态
单次执行整批只执行一次共享资源的单点操作
单次执行加滚动批次每批各执行一次需确认是否真的只需要全局一次
委派并转移事实采到的事实记在被委派主机名下需要以被委派主机视角记录信息
最容易混淆的是变量视角:任务被委派后,业务变量与主机名仍表达“当前处理的那台主机”,而连接相关设置按被委派主机解析。这也是同一任务里既能取到当前主机名、又能在另一台机器上执行的原因。
单次执行与滚动批次叠加时会按批重复,原本假定“全局只做一次”的操作(例如初始化集群元数据)就会被执行多次。使用前先确认该动作在多次执行下是否安全,必要时加幂等判断或改用显式的串行步骤。

什么时候该改设计

如果大量任务都要靠委派与单次执行才能正确工作,说明剧本的职责划分有问题:共享级别的操作本应拆成单独的 play 或独立剧本,在明确的一台主机上执行。用得越多越偏离“任务与被管主机一一对应”的直觉,维护成本也随之上升。

易错点

  • 把共享资源的操作写在每台主机上都执行的任务里,同一动作重复几十次,产生相互覆盖
  • 忘记委派,本该在控制节点执行的接口调用被发到每台被管主机上
  • 单次执行与滚动批次叠加后按批重复,假定只执行一次的初始化被做了多次
  • 误以为委派的机器也纳入了目标范围,实际它没有参与后续任务
  • 依赖被委派主机的连接设置却按当前主机变量配置,认证或端口不匹配导致失败

数据来源与参考

  • Ansible 官方文档 Controlling where tasks run: delegation and local actions
  • Ansible 官方文档 run_once 与 delegate_facts 说明
  • Ansible 官方文档 Playbook 关键字 delegates

整理校对:其其网ICT文档中心 · 本页地址:docs.qiqicto.com/automation/delegate-to-run-once-usage.html

​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌​​‌​‌‌‌‌​‌‌​​​​‌​‌‌‌​‌​‌​‌‌‌​‌​​​‌‌​‌‌‌‌​‌‌​‌‌​‌​‌‌​​​​‌​‌‌‌​‌​​​‌‌​‌​​‌​‌‌​‌‌‌‌​‌‌​‌‌‌​​​‌​‌‌‌‌​‌‌​​‌​​​‌‌​​‌​‌​‌‌​‌‌​​​‌‌​​‌​‌​‌‌​​‌‌‌​‌‌​​​​‌​‌‌‌​‌​​​‌‌​​‌​‌​​‌​‌‌​‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌​‌​‌‌‌​​‌​​‌‌‌​‌​‌​‌‌​‌‌‌​​​‌​‌‌​‌​‌‌​‌‌‌‌​‌‌​‌‌‌​​‌‌​​​‌‌​‌‌​​‌​‌​​‌​‌‌​‌​‌‌‌​‌​‌​‌‌‌​​‌‌​‌‌​​​​‌​‌‌​​‌‌‌​‌‌​​‌​‌​​‌​‌‌‌​​‌‌​‌​​​​‌‌‌​‌​​​‌‌​‌‌​‌​‌‌​‌‌​​