为什么用Ansible复制目录这么慢?

dok*_*par 54 scp ansible

我正在使用Ansible将目录(900个文件,136MBytes)从一个主机复制到另一个主机:

---
- name: copy a directory
  copy: src={{some_directory}} dest={{remote_directory}}
Run Code Online (Sandbox Code Playgroud)

这项操作耗时17分钟,而简单scp -r <src> <dest>只需7秒钟.

我已经尝试了加速模式,根据ansible 文档 "可以比启用ControlPersist的SSH快2-6倍,比paramiko快10倍.",但无济于事.

ted*_*r42 85

TLDR:使用synchronize而不是copy.

这是copy我正在使用的命令:

- copy: src=testdata dest=/tmp/testdata/
Run Code Online (Sandbox Code Playgroud)

作为一种猜测,我认为同步操作很慢.该文件模块文档说明了这点太:

递归复制工具的"复制"模块不能扩展到大量(>数百个)文件.有关替代方法,请参阅synchronize模块,它是rsync的包装器.

深入研究源显示每个文件都使用SHA1进行处理.这是使用hashlib.sha1实现的.本地测试意味着900个文件只需要10秒钟(恰好需要400mb的空间).

所以,下一个途径.该副本使用module_utils/basic.py的atomic_move方法处理.我不确定加速模式是否有帮助(这是一个大多数已被弃用的功能),但我尝试了流水线操作,将其置于本地ansible.cfg:

[ssh_connection]
pipelining=True
Run Code Online (Sandbox Code Playgroud)

它没有出现帮助; 我的样本需要24分钟才能运行.显然有一个循环可以检查文件,上传文件,修复权限,然后在下一个文件上启动.即使ssh连接处于打开状态,这也是很多命令.在线之间阅读它有点意义 - 我认为,"文件传输"无法在流水线中完成.

因此,按照提示使用synchronize命令:

- synchronize: src=testdata dest=/tmp/testdata/
Run Code Online (Sandbox Code Playgroud)

这花了18秒,即使是pipeline=False.显然,synchronize命令是这种情况下的方法.

请记住synchronize使用rsync,默认为mod-time和文件大小.如果您想要或需要校验和,请添加checksum=True到命令中.即使启用了校验和,时间也没有真正改变 - 仍然是15-18秒.我核实校验选项是在运行ansible-playbook-vvvv,可以在这里看到:

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": []}
Run Code Online (Sandbox Code Playgroud)

  • 很棒的答案. (3认同)
  • 复制模块没有办法更快吗?这似乎是副本中的一个错误,因为它太慢了? (2认同)
  • 一旦你通过`copy`切换到`synchronize`,你需要指定`rsync_opts`如果你使用rsync/ssh与不同的端口/用户/配置:https://hairycode.org/2016/02/22 /使用-A-定制SSH-配置与 - ansibles-同步模块/ (2认同)

voi*_*oid 10

synchronize在环境中配置可能很困难become_user.对于一次性部署,您可以归档源目录并使用unarchive模块进行复制:

- name: copy a directory
  unarchive:
    src: some_directory.tar.gz
    dest: {{remote_directory}}
    creates: {{remote_directory}}/indicator_file
Run Code Online (Sandbox Code Playgroud)

  • 以及如何归档本地目录?`archive` 似乎只支持远程文件夹。 (2认同)
  • 此答案不适合维护远程目录与不断变化的本地目录同步。它假设本地版本是一种不可变的镜像,只需要部署一次。在这种情况下,可以使用“tar -cvpzf”对其进行存档,然后将生成的存档放入剧本的“files/”子文件夹中,然后使用“unarchive”模块进行更快的部署,比问题中的“scp”更快。 (2认同)
  • 我知道了,谢谢。同步和不可变覆盖是两个不同的事情,我恰好需要后者。为了潜在读者的兴趣,我通过使用“delegate_to”解决了“archive”的问题。 (2认同)