Delegate_to connection overhead limits during loop execution
0 reputation · 23 Oct 2022, 08:57 UTC
0 reputation · 23 Oct 2022, 08:57 UTC
Evaluate the performance impact and connection behavior when combining the delegate_to keyword with task loops in Ansible.
While delegate_to allows task execution on a host other than the current target, executing this within a loop may trigger repeated connection overhead. It is unclear if the connection plugin maintains a persistent session for the delegated host across loop iterations or establishes a new connection for every item.
32775 reputation · 23 Oct 2022, 16:12 UTC
1. Connection reuse: When the same delegate_to host is used for every loop iteration, Ansible keeps a single SSH connection open for that host. The connection is established once, cached in the control‑master socket, and reused for each sub‑task in the loop. The connection is closed only when the play finishes or the ControlPersist timeout expires.
2. Limits & recommendations: The reuse is governed by the SSH multiplexing settings in ansible.cfg. If those options are disabled or the ControlPersist timeout is too short, a new connection will be opened for each item. The following settings control the behavior:
ssh_args = -o ControlMaster=auto -o ControlPersist=60s -o ControlPath=~/.ansible/cp-%h-%p-%rpipelining = True (reduces the number of SSH commands per task)forks (limits parallel SSH connections)ssh (default) or paramiko (does not support multiplexing)-vvv and look for lines like ssh: /usr/bin/ssh -o ControlMaster=auto …. The same ControlPath value should appear for all loop items.~/.ansible/cp-… socket file – it should exist during the entire loop.ss -ltnp | grep ssh while the play runs to see that only one SSH process is active for the delegate host.ControlPersist=300s or higher if the loop takes longer than the default 60 s.delegate_to to guarantee the same socket is reused.delegate_to: hostgroup with a static host name, then filtering inside the task.pipelining = True in ansible.cfg to reduce the number of SSH commands per loop iteration.forks low enough to avoid exhausting the SSH multiplexing limit (usually 5–10 per host).paramiko connection plugin – it does not support ControlPersist.delegate_to: "{{ item.host }}").To give a more precise recommendation, could you confirm which connection plugin you are using (default ssh or paramiko) and whether ControlPersist is enabled in your ansible.cfg? This will determine if the connection is truly reused or if a new SSH session is opened for each loop item.
Use comments to ask for clarification. Post a solution as an answer.
4,680 reputation · 23 Oct 2022, 12:07 UTC
To build on the discussion of SSH multiplexing, it is important to distinguish between connection reuse and command overhead. While ControlPersist keeps the socket open, each single item in a loop still triggers a separate SSH execution by default.
Enabling pipelining = True in ansible.cfg significantly reduces this overhead for delegated tasks. Without pipelining, Ansible typically wraps modules in a temporary script, transfers it, and executes it—requiring multiple SSH round-trips per loop item. With pipelining, the module is piped directly into the remote shell, reducing the number of operations per item to a single request.
To verify if pipelining is effectively reducing the overhead on your delegated host, you can monitor the process list on the target machine during the loop:
# Watch for the frequency of short-lived sshd or bash processes
watch -n 0.1 "ps aux | grep sshd"
A high frequency of new processes suggests pipelining is disabled, whereas a steady stream of activity on a single session indicates it is active.