scp - will - synchronize ansible
¿Por qué copiar un directorio con Ansible es tan lento? (4)
Estoy usando Ansible para copiar un directorio (900 archivos, 136MBytes) de un host a otro:
---
- name: copy a directory
copy: src={{some_directory}} dest={{remote_directory}}
Esta operación dura unos increíbles 17 minutos, mientras que un simple scp -r <src> <dest>
tarda solo 7 segundos.
He probado el modo acelerado, que de acuerdo con los documentos ansible "puede ser desde 2-6 veces más rápido que SSH con ControlPersist habilitado, y 10 veces más rápido que paramiko", pero fue en vano.
La mejor solución que he encontrado es simplemente comprimir la carpeta y usar el módulo ansible ''desarchivar''.
Carpeta de 450 MB terminada en solo 1 minuto
unarchive:
src: /home/user/folder1.tar.gz
dest: /opt
Si bien la synchronize
es más preferible en este caso que la copy
, está horneada por rsync. Significa que los inconvenientes de rsync (arquitectura cliente-servidor) también se mantienen: límites de CPU y disco, cálculos delta en el archivo lentos para archivos de gran tamaño, etc. Suena como que la velocidad es crítica, por lo que le sugiero que busque un solución basada en la arquitectura peer-to-peer, que es rápida y fácilmente escalable para muchas máquinas. Algo parecido a Bittorrent, Resilio Connect.
TLDR: utilice la synchronize
lugar de la copy
.
Aquí está el comando de copy
que estoy usando:
- copy: src=testdata dest=/tmp/testdata/
Como una suposición, supongo que las operaciones de sincronización son lentas. La documentación del módulo de archivos implica esto también:
El recurso de copia recursiva del módulo "copiar" no se escala a lotes (> cientos) de archivos. Para una alternativa, vea sincronizar módulo, que es un contenedor alrededor de rsync.
Al profundizar en la fuente, se muestra que cada archivo se procesa con SHA1 . Eso se implementa usando hashlib.sha1 . Una prueba local implica que solo lleva 10 segundos para 900 archivos (que toman 400 MB de espacio).
Entonces, la próxima avenida. La copia se maneja con el método module_utils / basic.py''s atomic_move . No estoy seguro de si el modo acelerado ayuda (es una característica en gran parte obsoleta ), pero probé la pipelining , poniéndolo en un ansible.cfg
local:
[ssh_connection]
pipelining=True
No pareció ayudar; mi muestra tardó 24 minutos en ejecutarse. Obviamente, hay un bucle que verifica un archivo, lo sube, arregla los permisos y luego comienza en el siguiente archivo. Eso es una gran cantidad de comandos, incluso si la conexión ssh se deja abierta. Leer entre líneas tiene un poco de sentido, la "transferencia de archivos" no se puede hacer en la canalización, creo.
Entonces, siguiendo la sugerencia de usar el comando de synchronize
:
- synchronize: src=testdata dest=/tmp/testdata/
Eso llevó 18 segundos, incluso con pipeline=False
. Claramente, el comando de synchronize
es el camino a seguir en este caso.
Tenga en cuenta que la synchronize
utiliza rsync, que por defecto es el tiempo de modificación y el tamaño del archivo. Si desea o necesita sumarios, agregue checksum=True
al comando. Incluso con el checksum habilitado, el tiempo realmente no cambió, aún 15-18 segundos. -vvvv
que la opción de suma de comprobación estaba activada al ejecutar ansible-playbook
con -vvvv
, que se puede ver aquí:
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": []}
synchronize
configuración de synchronize
puede ser difficult en entornos con become_user
. Para implementaciones únicas, puede archivar el directorio de origen y copiarlo con el módulo de unarchive
:
- name: copy a directory
unarchive:
src: some_directory.tar.gz
dest: {{remote_directory}}
creates: {{remote_directory}}/indicator_file