Search code examples
sshansiblepipelinesession-reuse

How can I make ansible reuse SSH sessions instead of creating a new one for each task?


My corporate firewall policy allows only 20 connections per minute 60 seconds between the same source and destinations.

Owing to this the ansible play hangs after a while.

I would like multiple tasks to use the same ssh session rather than creating new sessions. For this purpose i set the below pipelining = True in the local folder ansible.cfg as well as in the command line.

cat /opt/automation/startservices/ansible.cfg

[defaults]
host_key_checking = False
gathering = smart
[ssh_connection]
ssh_args = -o ControlMaster=auto -o ControlPersist=600s
control_path = %(directory)s/%%h-%%r
pipelining = True

ANSIBLE_SSH_PIPELINING=0 ansible-playbook -i /opt/automation/startservices/finalallmw.hosts /opt/automation/startservices/va_action.yml -e '{ dest_host: myremotehost7 }' -e dest_user=oracle

The playbook is too big to be shared here but it is this task which loops and this is where it hangs due to more than 20 ssh connections in 60 seconds.

 - name: Copying from "{{ inventory_hostname }}" to this ansible server.
   synchronize:
     src: "{{ item.path }}"
     dest: "{{ playbook_dir }}/homedirbackup/{{ inventory_hostname }}/{{ dtime }}/"
     mode: pull
     copy_links: yes
   with_items:
     - "{{ to_copy.files }}"

With the pipelining settings set, my play still hangs after 20 connections.

Below are the playbook settings:

   hosts: "{{ groups['dest_nodes'] | default(groups['all']) }}"
   user: "{{ USER | default(dest_user) }}"
   any_errors_fatal: True
   gather_facts: false
   tags: always

   vars:
     ansible_host_key_checking: false
     ansible_ssh_extra_args: -o StrictHostKeyChecking=no  -o ConnectionAttempts=5

Post suggestions this far on this thread the issue persists. Below is my local directory ansible.cfg

$ cat /opt/automation/startservices/ansible.cfg
# config file for ansible -- http://ansible.com/
# ==============================================

# nearly all parameters can be overridden in ansible-playbook
# or with command line flags. ansible will read ANSIBLE_CONFIG,
# ansible.cfg in the current working directory, .ansible.cfg in
# the home directory or /etc/ansible/ansible.cfg, whichever it
# finds first

[defaults]
host_key_checking = False
roles_path = roles/
gathering = smart
[ssh_connection]
pipelining = True
ssh_args = -o ControlMaster=auto -o ControlPersist=1200s  -o ControlPath=~/.ansible/cp/%r@%h:%p

[persistent_connection]
control_path_dir = ~/.ansible/cp
$

Can you please suggest any solution to the issue on the ansible side where all tasks use the same ssh session and is pipelining not working here?


Solution

  • The problem is not with ansible controller running the module(s) (i.e. copying the necessary temporary AnsibleZ files to your target and execute them - you already have the correct options for that in ansible.cfg to use master sessions) but with the synchronize module itself which needs to spawn its own ssh connections to transfer files between relevant servers while it is running on the target.

    The latest synchronize module version is now part of the ansible.posix collection and has recently gained 2 options that will help you work around your problem to apply the use of master sessions to the module itself while using rsync.

    Although it is possible to install this collection in ansible 2.9 to override the older stock module version (which does not have those options), I strongly suggest you use ansible version 2.10 or 2.11. My personal preferred installation method for ansible is through pip as it will let you install any ansible version on any OS for any user in any number of (virtual) environment.

    Regarding pip, the versioning has changed (and is quite a mess IMO...)

    • ansible is now a meta package with its own independent versioning.
    • the usual ansible binaries (ansible, ansible-playbook, ....) are packaged in ansible-core which has the version the corresponding to what you get when running ansible -v
    • the meta ansible package installs a set of collections by default (including the ansible.posix one if I'm not wrong)

    => To get ansible -v => 2.10 you want to install ansible pip package 3.x

    => To get ansible -v => 2.11 you want to install ansible pip package 4.x

    You will have to remove any previous version installed via pip in your current environment before proceeding.