SSH pipelining
is an Ansible feature to reduce the number of connections to a host.
Ansible will normally create a temporary directory under
~/.ansible (via ssh), then for each task, copy the module
source to the directory (using sftp or scp) and execute the module (ssh
again).
With pipelining enabled, Ansible will connect only once per task using
ssh to execute python, and write the module source to its stdin. Even
with persistent ssh connections enabled, it's a noticeable improvement
to make only one ssh connection per task.
Unfortunately, pipelining is disabled by default because it is
incompatible with sudo's
requiretty setting (or su, which always requires a tty). This
is because of
a quirk of the Python interpreter,
which enters interactive mode automatically when you pipe in data from a
(pseudo) tty.
Update 2015-11-18: I've submitted a pull request to
make pipelining work with requiretty.
The rest of this post still remains true, but if the PR is merged, the
underlying problem will just go away.
Pipelining can be enabled globally by setting “pipelining=True”
in the ssh section of ansible.cfg, or setting
“ANSIBLE_SSH_PIPELINING=1” in the environment.
With Ansible 2 (not yet released), you can also
set ansible_ssh_pipelining in the inventory or in a playbook.
You can leave it enabled in ansible.cfg, but turn it off for
some hosts (where requiretty must remain enabled), or even
write a play with pipelining disabled in order to remove
requiretty from /etc/sudoers.
- lineinfile:
dest: /etc/sudoers
line: 'Defaults requiretty'
state: absent
sudo_user: root
vars:
ansible_ssh_pipelining: no
The above lineinfile recipe is simplistic, but it shows that
it's now possible to disable requiretty, even if it's by
replacing /etc/sudoers altogether.
Note the use of another Ansible 2 feature above: vars can also
be set for individual tasks (and
blocks),
not only plays.