Как управлять Ansible программно и одновременно?
Я хотел бы использовать Ansible для выполнения простого задания на нескольких удаленных узлах одновременно. Фактическая работа включает в себя захват некоторых файлов журнала, а затем последующую обработку результатов на моем локальном хосте (который имеет программное обеспечение, недоступное на удаленных узлах).
инструменты командной строки ansible не подходят для этого варианта использования, поскольку они смешивают форматирование, сгенерированное ansible, с выводом удаленно выполняемой команды. Питон API кажется, как следует однако это возможно, поскольку он предоставляет вывод немодифицированным (кроме некоторых потенциальных искажений unicode, которые не должны быть актуальны здесь).
упрощенная версия программы Python, которую я придумал, выглядит так:
from sys import argv
import ansible.runner
runner = ansible.runner.Runner(
pattern='*', forks=10,
module_name="command",
module_args=(
"""
sleep 10
"""),
inventory=ansible.inventory.Inventory(argv[1]),
)
results = runner.run()
здесь sleep 10
означает фактическую команду захвата журнала-идея состоит в том, чтобы просто имитировать команду, которая не будет завершена немедленно.
однако, запустив это, я замечаю, что количество времени, которое требуется, кажется пропорционально количеству хостов в моем инвентаре. Вот результаты синхронизации против запасов с 2, 5 и 9 хостами соответственно:
exarkun@top:/tmp$ time python howlong.py two-hosts.inventory
real 0m24.285s
user 0m0.216s
sys 0m0.120s
exarkun@top:/tmp$ time python howlong.py five-hosts.inventory
real 0m55.120s
user 0m0.224s
sys 0m0.160s
exarkun@top:/tmp$ time python howlong.py nine-hosts.inventory
real 1m57.272s
user 0m0.360s
sys 0m0.284s
exarkun@top:/tmp$
некоторые другие случайные наблюдения:
-
ansible all --forks=10 -i five-hosts.inventory -m command -a "sleep 10"
показывает такое же поведение -
ansible all -c local --forks=10 -i five-hosts.inventory -m command -a "sleep 10"
кажется, что выполняет вещи одновременно (но работает только для локальных соединений, конечно) -
ansible all -c paramiko --forks=10 -i five-hosts.inventory -m command -a "sleep 10"
, кажется, выполнять вещи одновременно
возможно, это предполагает, что проблема связана с транспортом ssh и не имеет ничего общего с использованием ansible через API Python, а не из строки comand.
что здесь не так, что предотвращает транспорт по умолчанию занимает всего около десяти секунд независимо от количества хостов в моем инвентаре?
3 ответов
некоторые исследования показывают, что ansible ищет хосты в моем инвентаре в ~/.СШ/если вы. В моей конфигурации включены HashKnownHosts. ansible никогда не может найти записи хоста, которые он ищет, потому что он не понимает хэш-известный формат записи хостов.
всякий раз, когда SSH-транспорт ansible не может найти запись известных хостов, он получает глобальную блокировку на время выполнения модуля. Результатом этого слияния является то, что все выполнение эффективно сериализуется.
временная работа-это отказаться от некоторой проверки безопасности и отключенного ключа хоста, поставив host_key_checking = False
на ~/.ansible.cfg
. Другая работа - использовать транспорт paramiko (но это невероятно медленно, возможно, в десятки или сотни раз медленнее, чем транспорт ssh, по какой-то причине). Еще одна работа - позволить некоторым необработанным записям добавляться в файл known_hosts для ssh-транспорта ansible.
поскольку у вас включен HashKnownHosts, вы должны обновить до последней версии Ansible. Версия 1.3 добавлена поддержка hashed known_hosts
см. багтреккере и изменений. Это должно решить вашу проблему без ущерба для безопасности (обходной путь с помощью host_key_checking=False
) или жертвуя скоростью (ваш обходной путь с помощью paramiko).
С Ansible 2.0 Python API я отключил StrictHostKeyChecking с помощью
import ansible.constants
ansible.constants.HOST_KEY_CHECKING = False
мне удалось значительно ускорить Ansible, установив следующее на управляемых компьютерах. Новые sshd имеют значение по умолчанию наоборот, я думаю, поэтому в вашем случае это может не понадобиться.
/etc/ssh/sshd_config
----
UseDNS no