控制任务运行位置:委派和本地操作

默认情况下,Ansible 会在与您的 Playbook 的 hosts 行匹配的机器上收集事实并执行所有任务。此页面向您展示如何将任务委派给不同的机器或组,将事实委派给特定的机器或组,或者在本地运行整个 Playbook。使用这些方法,您可以精确有效地管理相互关联的环境。例如,在更新您的 Web 服务器时,您可能需要暂时将它们从负载均衡池中移除。您不能在 Web 服务器本身上执行此任务。通过将任务委派给本地主机,您可以将所有任务保留在同一个 Play 中。

无法委派的任务

某些任务始终在控制节点上执行。这些任务,包括 includeadd_hostdebug,无法委派。您可以从 connection 属性文档中确定是否可以委派操作。如果 connection 属性指示 supportFalseNone,则该操作不使用连接,并且无法委派。

委派任务

如果您想在引用其他主机的情况下在一个主机上执行任务,请在任务上使用 delegate_to 关键字。这对于管理负载均衡池中的节点或控制停机窗口非常理想。您可以将委派与 serial 关键字一起使用,以控制一次执行的主机数量。

---
- hosts: webservers
  serial: 5

  tasks:
    - name: Take out of load balancer pool
      ansible.builtin.command: /usr/bin/take_out_of_pool {{ inventory_hostname }}
      delegate_to: 127.0.0.1

    - name: Actual steps would go here
      ansible.builtin.yum:
        name: acme-web-stack
        state: latest

    - name: Add back to load balancer pool
      ansible.builtin.command: /usr/bin/add_back_to_pool {{ inventory_hostname }}
      delegate_to: 127.0.0.1

此 Play 中的第一个和第三个任务在 127.0.0.1 上运行,这是运行 Ansible 的机器。还有一种简写语法,您可以在每个任务的基础上使用:local_action。以下是与上述相同的 Playbook,但使用简写语法委派给 127.0.0.1。

---
# ...

  tasks:
    - name: Take out of load balancer pool
      local_action: ansible.builtin.command /usr/bin/take_out_of_pool {{ inventory_hostname }}

# ...

    - name: Add back to load balancer pool
      local_action: ansible.builtin.command /usr/bin/add_back_to_pool {{ inventory_hostname }}

您可以使用本地操作调用 ‘rsync’ 将文件递归复制到受管服务器

---
# ...

  tasks:
    - name: Recursively copy files from management server to target
      local_action: ansible.builtin.command rsync -a /path/to/files {{ inventory_hostname }}:/path/to/target/

请注意,您必须为此配置无密码的 SSH 密钥或 ssh-agent,否则 rsync 会要求输入密码。

要指定更多参数,请使用以下语法

---
# ...

  tasks:
    - name: Send summary mail
      local_action:
        module: community.general.mail
        subject: "Summary Mail"
        to: "{{ mail_recipient }}"
        body: "{{ mail_body }}"
      run_once: True

注意

  • ansible_host 变量和其他连接变量(如果存在)反映有关任务委派到的主机的信息,而不是 inventory_hostname。

  • 任务委派到的主机不继承委派该任务的主机的变量。

警告

尽管您可以 delegate_to 一个清单中不存在的主机(通过添加 IP 地址、DNS 名称或连接插件所需的任何内容),但这样做不会将该主机添加到您的清单中,并且可能会导致问题。以这种方式委派的主机会从“all”组继承变量(假设 VARIABLE_PRECEDENCE 包括 all_inventory)。如果您必须 delegate_to 一个非清单主机,请使用 add host 模块

委派上下文中的模板

请注意,在委派下,执行解释器(通常是 Python)、connectionbecomeshell 插件选项现在将使用委派到的主机的值进行模板化。除 inventory_hostname 外的所有变量现在都将从此主机而不是原始任务主机中使用。如果需要来自原始任务主机的那些选项的变量,则必须使用 hostvars[inventory_hostname]['varname'],即使 inventory_hostname_short 也引用委派的主机。

委派和并行执行

默认情况下,Ansible 任务并行执行。委派任务不会改变这一点,也不会处理并发问题(多个 Fork 写入同一文件)。最常见的是,当为所有主机更新单个委派到的主机上的单个文件(例如,使用 copytemplatelineinfile 模块)时,用户会受到此影响。它们仍将在并行 Fork(默认 5 个)中运行并相互覆盖。

这可以通过几种方式处理

- name: "handle concurrency with a loop on the hosts with `run_once: true`"
  lineinfile: "<options here>"
  run_once: true
  loop: '{{ ansible_play_hosts_all }}'

通过使用 serial: 1 的中间 Play 或在任务级别使用 throttle: 1,有关更多详细信息,请参阅 控制 Playbook 执行:策略等

委派事实

委派 Ansible 任务就像在现实世界中委派任务一样 - 您的杂货属于您,即使其他人将它们送到您家。同样,委派任务收集的任何事实默认情况下都会分配给 inventory_hostname(当前主机),而不是生成事实的主机(委派到的主机)。要将收集的事实分配给委派的主机而不是当前主机,请将 delegate_facts 设置为 true

---
- hosts: app_servers

  tasks:
    - name: Gather facts from db servers
      ansible.builtin.setup:
      delegate_to: "{{ item }}"
      delegate_facts: true
      loop: "{{ groups['dbservers'] }}"

此任务收集 dbservers 组中机器的事实,并将事实分配给这些机器,即使 Play 的目标是 app_servers 组。这样,即使 dbservers 不是 Play 的一部分,或者通过使用 --limit 排除在外,您也可以查找 hostvars[‘dbhost1’][‘ansible_default_ipv4’][‘address’]

本地 Playbook

在远程主机上本地使用 Playbook 而不是通过 SSH 连接可能很有用。这对于通过将 Playbook 放入 crontab 中来确保系统的配置非常有用。这也可以用于在操作系统安装程序(例如 Anaconda kickstart)中运行 Playbook。

要在本地运行整个 Playbook,只需将 hosts: 行设置为 hosts: 127.0.0.1,然后像这样运行 Playbook

ansible-playbook playbook.yml --connection=local

或者,可以在单个 Playbook Play 中使用本地连接,即使 Playbook 中的其他 Play 使用默认的远程连接类型也是如此

---
- hosts: 127.0.0.1
  connection: local

注意

如果您将连接设置为 local 并且没有设置 ansible_python_interpreter,则模块将在 /usr/bin/python 下运行,而不是在 {{ ansible_playbook_python }} 下运行。请确保在 host_vars/localhost.yml 中设置 ansible_python_interpreter: “{{ ansible_playbook_python }}”,例如。您可以通过使用 local_actiondelegate_to: localhost 来避免此问题。

另请参阅

Ansible Playbook

Playbook 简介

控制 Playbook 执行:策略等

更多控制 Ansible 执行方式和位置的方法

沟通

有疑问?需要帮助?想分享您的想法?请访问 Ansible 通信指南