2015-01-16 14 views
39

Sto usando Ansible per copiare una cartella (900 file, 136MBytes) da un host all'altro:Perché copiare una directory con Ansible è così lento?

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

Questa operazione richiede un incredibile 17 minuti, mentre un semplice scp -r <src> <dest> richiede solo 7 secondi.

Ho provato la modalità Accelerated, che secondo lo ansible docs "può essere ovunque 2-6 volte più veloce di SSH con ControlPersist abilitato e 10 volte più veloce di paramiko.", Ma senza successo.

+0

Sono consapevole che lo fa un hash MD5 e convalida, ma che il tempo si sta vedendo vedrebbe molto grande. –

+0

@CatManDo esegue sha1, in realtà, e questo non è responsabile (anche se era la mia prima ipotesi). – tedder42

risposta

63

TLDR: utilizzare synchronize anziché copy.

Ecco il comando copy sto usando:

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

Come una supposizione, presumo le operazioni di sincronizzazione sono lenti. Lo files module documentation implica anche questo:

Il modulo di copia ricorsivamente in copia non è scalabile in quantità (> centinaia) di file. In alternativa, vedi sincronizzare il modulo, che è un wrapper su rsync.

Scavando nella sorgente viene visualizzato each file is processed with SHA1. Quello è implemented using hashlib.sha1. Un test locale implica che ci vogliono solo 10 secondi per 900 file (che capita di prendere 400mb di spazio).

Quindi, la prossima strada. La copia viene gestita con module_utils/basic.py's atomic_move method. Non sono sicuro se la modalità accelerata aiuta (è un mostly-deprecated feature), ma ho provato pipelining, mettendo questo in un locale ansible.cfg:

[ssh_connection] 
pipelining=True 

Essa non ha sembrano per aiutare; il mio campione ha impiegato 24 minuti per funzionare. C'è ovviamente un ciclo che controlla un file, lo carica, corregge le autorizzazioni, quindi inizia nel file successivo. Sono molti comandi, anche se la connessione ssh è lasciata aperta. Leggere tra le righe ha un po 'di buon senso - il "trasferimento di file" non può essere fatto nel pipelining, credo.

Così, seguendo il suggerimento di utilizzare il comando synchronize:

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

che ha preso 18 secondi, anche con pipeline=False. Chiaramente, il comando synchronize è la strada da percorrere in questo caso.

Ricordare che synchronize utilizza rsync, che per impostazione predefinita è mod-time e dimensione del file. Se si desidera o si richiede il checksum, aggiungere checksum=True al comando. Anche con il checksum abilitato, il tempo non cambiava davvero - ancora 15-18 secondi. Ho verificato l'opzione checksum era eseguendo ansible-playbook con -vvvv, che può essere visto qui:

configurazione
ok: [testhost] => {"changed": false, "cmd": "rsync --delay-updates -FF --compress --checksum --archive --rsh 'ssh -o StrictHostKeyChecking=no' --out-format='<<CHANGED>>%i %n%L' \"testdata\" \"[email protected]:/tmp/testdata/\"", "msg": "", "rc": 0, "stdout_lines": []} 
+3

Risposta stupenda. –

+1

Non c'è modo per il modulo di copia di essere più veloce? Questo sembra un bug in copia per essere così lento? –

+0

Hai letto la risposta? Ci sono modi. – tedder42

5

synchronize può essere difficult in ambienti con become_user.Per le distribuzioni di una volta è possibile archiviare directory dei sorgenti e copiarlo con modulo unarchive:

- name: copy a directory 
    unarchive: 
    src: some_directory.tar.gz 
    dest: {{remote_directory}} 
    creates: {{remote_directory}}/indicator_file 
Problemi correlati