1.. _playbooks_delegation: 2 3Controlling where tasks run: delegation and local actions 4========================================================= 5 6By default Ansible gathers facts and executes all tasks on the machines that match the ``hosts`` line of your playbook. This page shows you how to delegate tasks to a different machine or group, delegate facts to specific machines or groups, or run an entire playbook locally. Using these approaches, you can manage inter-related environments precisely and efficiently. For example, when updating your webservers, you might need to remove them from a load-balanced pool temporarily. You cannot perform this task on the webservers themselves. By delegating the task to localhost, you keep all the tasks within the same play. 7 8.. contents:: 9 :local: 10 11Tasks that cannot be delegated 12------------------------------ 13 14Some tasks always execute on the controller. These tasks, including ``include``, ``add_host``, and ``debug``, cannot be delegated. 15 16.. _delegation: 17 18Delegating tasks 19---------------- 20 21If you want to perform a task on one host with reference to other hosts, use the ``delegate_to`` keyword on a task. This is ideal for managing nodes in a load balanced pool or for controlling outage windows. You can use delegation with the :ref:`serial <rolling_update_batch_size>` keyword to control the number of hosts executing at one time:: 22 23 --- 24 - hosts: webservers 25 serial: 5 26 27 tasks: 28 - name: Take out of load balancer pool 29 ansible.builtin.command: /usr/bin/take_out_of_pool {{ inventory_hostname }} 30 delegate_to: 127.0.0.1 31 32 - name: Actual steps would go here 33 ansible.builtin.yum: 34 name: acme-web-stack 35 state: latest 36 37 - name: Add back to load balancer pool 38 ansible.builtin.command: /usr/bin/add_back_to_pool {{ inventory_hostname }} 39 delegate_to: 127.0.0.1 40 41The first and third tasks in this play run on 127.0.0.1, which is the machine running Ansible. There is also a shorthand syntax that you can use on a per-task basis: ``local_action``. Here is the same playbook as above, but using the shorthand syntax for delegating to 127.0.0.1:: 42 43 --- 44 # ... 45 46 tasks: 47 - name: Take out of load balancer pool 48 local_action: ansible.builtin.command /usr/bin/take_out_of_pool {{ inventory_hostname }} 49 50 # ... 51 52 - name: Add back to load balancer pool 53 local_action: ansible.builtin.command /usr/bin/add_back_to_pool {{ inventory_hostname }} 54 55You can use a local action to call 'rsync' to recursively copy files to the managed servers:: 56 57 --- 58 # ... 59 60 tasks: 61 - name: Recursively copy files from management server to target 62 local_action: ansible.builtin.command rsync -a /path/to/files {{ inventory_hostname }}:/path/to/target/ 63 64Note that you must have passphrase-less SSH keys or an ssh-agent configured for this to work, otherwise rsync asks for a passphrase. 65 66To specify more arguments, use the following syntax:: 67 68 --- 69 # ... 70 71 tasks: 72 - name: Send summary mail 73 local_action: 74 module: community.general.mail 75 subject: "Summary Mail" 76 to: "{{ mail_recipient }}" 77 body: "{{ mail_body }}" 78 run_once: True 79 80The `ansible_host` variable reflects the host a task is delegated to. 81 82.. _delegate_facts: 83 84Delegating facts 85---------------- 86 87Delegating Ansible tasks is like delegating tasks in the real world - your groceries belong to you, even if someone else delivers them to your home. Similarly, any facts gathered by a delegated task are assigned by default to the `inventory_hostname` (the current host), not to the host which produced the facts (the delegated to host). To assign gathered facts to the delegated host instead of the current host, set ``delegate_facts`` to ``true``:: 88 89 --- 90 - hosts: app_servers 91 92 tasks: 93 - name: Gather facts from db servers 94 ansible.builtin.setup: 95 delegate_to: "{{ item }}" 96 delegate_facts: true 97 loop: "{{ groups['dbservers'] }}" 98 99This task gathers facts for the machines in the dbservers group and assigns the facts to those machines, even though the play targets the app_servers group. This way you can lookup `hostvars['dbhost1']['ansible_default_ipv4']['address']` even though dbservers were not part of the play, or left out by using `--limit`. 100 101.. _local_playbooks: 102 103Local playbooks 104--------------- 105 106It may be useful to use a playbook locally on a remote host, rather than by connecting over SSH. This can be useful for assuring the configuration of a system by putting a playbook in a crontab. This may also be used 107to run a playbook inside an OS installer, such as an Anaconda kickstart. 108 109To run an entire playbook locally, just set the ``hosts:`` line to ``hosts: 127.0.0.1`` and then run the playbook like so:: 110 111 ansible-playbook playbook.yml --connection=local 112 113Alternatively, a local connection can be used in a single playbook play, even if other plays in the playbook 114use the default remote connection type:: 115 116 --- 117 - hosts: 127.0.0.1 118 connection: local 119 120.. note:: 121 If you set the connection to local and there is no ansible_python_interpreter set, modules will run under /usr/bin/python and not 122 under {{ ansible_playbook_python }}. Be sure to set ansible_python_interpreter: "{{ ansible_playbook_python }}" in 123 host_vars/localhost.yml, for example. You can avoid this issue by using ``local_action`` or ``delegate_to: localhost`` instead. 124 125.. seealso:: 126 127 :ref:`playbooks_intro` 128 An introduction to playbooks 129 :ref:`playbooks_strategies` 130 More ways to control how and where Ansible executes 131 `Ansible Examples on GitHub <https://github.com/ansible/ansible-examples>`_ 132 Many examples of full-stack deployments 133 `User Mailing List <https://groups.google.com/group/ansible-devel>`_ 134 Have a question? Stop by the google group! 135 `irc.libera.chat <https://libera.chat/>`_ 136 #ansible IRC chat channel 137