为什么用安赛尔复制目录这么慢?

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

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

这个操作需要令人难以置信的17分钟,而一个简单的 scp -r <src> <dest>只需要7秒钟。

我试过加速模式,根据 可靠的文件,但没有用。

可以比启用 ControlPerst 的 SSH 快2-6倍,比 parmiko 快10倍。

39825 次浏览

TLDR: 使用 synchronize代替 copy

下面是我使用的 copy命令:

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

作为猜测,我假设同步操作很慢。 文件模块文档也暗示了这一点:

“复制”模块递归复制功能不能扩展到大量(> 数百)文件。有关替代方法,请参见 sync 模块,它是 rsync 的包装器。

深入挖掘源代码可以看到 用 SHA1处理每个文件。那是 使用 hashlib.sha1实现。本地测试意味着900个文件只需要10秒钟(正好占用400mb 的空间)。

那么,下一条大街。副本由 Module _ utils/basic.py 的 atom _ move 方法处理。我不确定加速模式是否有帮助(这是一个 被大多数人所反对的特性) ,但我尝试了 流水线,把它放在一个本地 ansible.cfg:

[ssh_connection]
pipelining=True

它没有 出现的帮助,我的样本运行了24分钟。显然有一个循环检查一个文件,上传它,修复权限,然后开始下一个文件。即使 ssh 连接保持打开状态,也需要执行很多命令。在行与行之间阅读有一点意义-“文件传输”不能在流水线中完成,我认为。

因此,遵循使用 synchronize命令的提示:

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

显然,在这种情况下,使用 synchronize命令只需要18秒。

请记住,synchronize使用 rsync,默认为 mod-time 和文件大小。如果需要校验和,请将 checksum=True添加到命令中。即使启用了校验求和,时间也没有真正改变——仍然是15-18秒。我通过使用 -vvvv运行 ansible-playbook来验证校验和选项是否打开,可以在这里看到:

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": []}

在有 become_user的环境中,synchronize配置可以是 很难。对于一次性部署,您可以存档源目录并用 unarchive模块复制它:

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

我找到的最好的解决方案是只压缩文件夹并使用 unarchive模块。

450 MB 的文件夹在1分钟内完成。


unarchive:
src: /home/user/folder1.tar.gz
dest: /opt

虽然在这种情况下 synchronizecopy更好,但它是由 rsync 烘烤的。这意味着 rsync (客户机-服务器体系结构)的缺点仍然存在: CPU 和磁盘边界,大文件的文件内增量计算速度慢等等。听起来速度对您来说是至关重要的,所以我建议您寻找一种基于对等架构的解决方案,这种架构对于许多机器来说是快速且易于扩展的。类似于基于 BitTorrent 的 Resilio Connect。

提供 main.yml任务约定

- name: "Copy Files"
synchronize:
src: <source>
dest: <destination>
rsync_opts:
- "--chmod=F755" # provide here give also permission