Pourquoi copier un répertoire avec Ansible est-il si lent?

j'utilise Ansible pour copier un répertoire (900 fichiers, 136mytes) d'un hôte à un autre:

---
- name: copy a directory
  copy: src={{some_directory}} dest={{remote_directory}}

cette opération prend un incroyable 17 minutes, alors qu'un simple scp -r <src> <dest> prend seulement 7 secondes.

j'ai essayé le mode Accéléré, qui, selon l' ansible docs " peut être n'importe où à partir de 2-6x plus rapide que SSH avec ControlPersist activé, et 10x plus rapide que paramiko.", mais en vain.

45
demandé sur dokaspar 2015-01-16 16:45:23

4 réponses

TLDR: use synchronize au lieu de copy.

Voici le copy la commande que j'utilise:

- copy: src=testdata dest=/tmp/testdata/

à mon avis, les opérations de synchronisation sont lentes. fichiers module documentation implique ceci:

le module" copier " recursively copier la fonction ne passe pas en lots (>des centaines) de fichiers. Pour l'alternative, voir module synchroniser, qui est un enveloppeur autour de rsync.

Creuser dans le source montre chaque fichier est traité avec SHA1. C'est implémenté avec hashlib.sha1. Un test local implique que cela ne prend que 10 secondes pour 900 fichiers (qui prennent 400 Mo d'espace).

Donc, la prochaine avenue. La copie est traitée avec module_utils/basic.py méthode atomic_move. Je ne suis pas sûr que le mode accéléré aide (c'est un la plupart fonctionnalité obsolète), mais j'ai essayé pipelining, en mettant cette dans un local ansible.cfg:

[ssh_connection]
pipelining=True

Il n'a pas semble pour aider; mon échantillon a pris 24 minutes à courir . Il y a évidemment une boucle qui vérifie un fichier, le télécharge, corrige les permissions, puis commence sur le fichier suivant. C'est beaucoup de commandes, même si la connexion ssh est laissé ouvert. La lecture entre les lignes fait un peu de sens - le "transfert de fichier" ne peut pas être fait dans pipelining, je pense.

donc, en suivant l'indication d'utiliser le synchronize commande:

- synchronize: src=testdata dest=/tmp/testdata/

cela a pris 18 secondes, même avec pipeline=False. Clairement, le synchronize la commande est la voie à suivre dans ce cas.

Gardez à l'esprit synchronize utilise rsync, qui par défaut est mod-time et la taille du fichier. Si vous voulez ou avez besoin de checksumming, ajouter checksum=True à la commande. Même avec checksumming activé le temps n'a pas vraiment changé - encore 15-18 secondes. J'ai vérifié que l'option checksum était activée en exécutant ansible-playbook-vvvv, qui peut être vu ici:

ok: [testhost] => {"changed": false, "cmd": "rsync --delay-updates -FF --compress --checksum --archive --rsh 'ssh  -o StrictHostKeyChecking=no' --out-format='<<CHANGED>>%i %n%L' \"testdata\" \"user@testhost:/tmp/testdata/\"", "msg": "", "rc": 0, "stdout_lines": []}
71
répondu tedder42 2015-01-17 01:52:43

synchronize la configuration peut être difficile dans les environnements avec become_user. Pour les déploiements vous pouvez archiver le répertoire source et le copier avec unarchive module:

- name: copy a directory
  unarchive:
    src: some_directory.tar.gz
    dest: {{remote_directory}}
    creates: {{remote_directory}}/indicator_file
6
répondu void 2017-06-19 15:36:09

la meilleure solution que j'ai trouvée est de simplement zip le dossier et d'utiliser le unarchive module.

450 Mo dossier terminé en 1 minute.


unarchive:
   src: /home/user/folder1.tar.gz
   dest: /opt
2
répondu Rinu K V 2018-09-10 18:52:24

synchronize est plus préférable dans ce cas que copy, c'est cuit par rsync. Cela signifie que les inconvénients de rsync (architecture client-serveur) sont également conservés: limites du CPU et du disque, calculs delta lents dans le fichier pour les gros fichiers, etc. On dirait que pour vous la vitesse est critique, donc je vous suggère de chercher une solution basée sur l'architecture peer-to-peer, qui est rapide et facilement extensible à de nombreuses machines. Quelque chose comme BitTorrent-based, Resilio Connect.

0
répondu Victoria 2018-08-07 15:35:09