Подтвердить что ты не робот

Почему копирование каталога с Ansible так медленно?

Я использую Ansible для копирования каталога (900 файлов, 136 Мбайт) с одного узла на другой:

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

Эта операция занимает 17 минут, а простой scp -r <src> <dest> занимает всего 7 секунд.

Я пробовал ускоренный режим, который согласно ansible docs "может быть где угодно от 2 до 6 раз быстрее, чем SSH с включенным ControlPersist, и в 10 раз быстрее, чем paramiko.", но безрезультатно.

4b9b3361

Ответ 1

TL;DR: используйте synchronize вместо copy.

Здесь команда copy, которую я использую:

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

Как я предполагаю, операции синхронизации медленны. Документация модуля также подразумевает это:

Модуль "копировать" рекурсивно копирует объект не масштабируется для большого количества ( > сотни) файлов. Для альтернативы см. Модуль синхронизации, который является оберткой вокруг rsync.

Копаем в исходный код каждый файл обрабатывается с помощью SHA1. Это реализовано с использованием hashlib.sha1. Локальный тест подразумевает, что требуется всего лишь 10 секунд для 900 файлов (которые занимают 400 мб пространства).

Итак, следующий путь. Копию обрабатывают с помощью module_utils/basic.py метода atom_move. Я не уверен, что ускоренный режим помогает (это в основном-устаревшая функция), но я попробовал pipelining, помещая его в локальный ansible.cfg:

[ssh_connection]
pipelining=True

Это не помогло; мой образец занял 24 минуты. Очевидно, что цикл, который проверяет файл, загружает его, исправляет разрешения, затем запускается в следующем файле. Это много команд, даже если ssh-соединение остается открытым. Я думаю, что чтение между строк имеет немного смысл - "передача файлов" не может быть выполнена при конвейерной обработке.

Итак, следуя подсказке с использованием команды synchronize:

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

Это заняло 18 секунд, даже с pipeline=False. Очевидно, что команда synchronize - это способ пойти в этом случае.

Имейте в виду, что synchronize использует rsync, который по умолчанию соответствует моменту времени и размеру файла. Если вы хотите или нуждаетесь в контрольных суммах, добавьте 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\" \"[email protected]:/tmp/testdata/\"", "msg": "", "rc": 0, "stdout_lines": []}

Ответ 2

synchronize конфигурация может сложная в средах с become_user. Для одноразовых развертываний вы можете архивировать исходный каталог и скопировать его с помощью модуля unarchive:

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