Как управлять Ansible программно и параллельно?

Я хотел бы использовать Ansible для одновременного выполнения простого задания на нескольких удаленных узлах. Фактическая работа включает в себя поиск некоторых файлов журнала и последующую обработку результатов на моем локальном хосте (на котором есть программное обеспечение, недоступное на удаленных узлах).

Инструменты ansible из командной строки не кажутся подходящими для этого варианта использования, потому что они смешивают сгенерированное ansible форматирование с выводом удаленно выполняемой команды. API Python, похоже, должен быть способен на это, поскольку он предоставляет неизмененный вывод (кроме некоторого потенциального искажения юникода, которое здесь не должно иметь значения).

Упрощенная версия программы 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 через Python API, а не из командной строки.

Что здесь не так, из-за чего транспорт по умолчанию не занимает всего около десяти секунд, независимо от количества хостов в моем инвентаре?


person Jean-Paul Calderone    schedule 30.07.2013    source источник


Ответы (3)


Некоторое расследование показывает, что ansible ищет хосты в моем инвентаре в ~/.ssh/known_hosts. В моей конфигурации включен HashKnownHosts. ansible никогда не сможет найти записи хостов, которые он ищет, потому что он не понимает формат записи известных хостов.

Всякий раз, когда ssh-транспорт ansible не может найти запись об известных хостах, он получает глобальную блокировку на время выполнения модуля. Результатом этого слияния является то, что все выполнение эффективно сериализуется.

Временный обходной путь — отказаться от некоторой безопасности и отключить проверку ключа хоста, поместив host_key_checking = False в ~/.ansible.cfg. Другой обходной путь — использовать транспорт paramiko (но он невероятно медленный, по какой-то причине, возможно, в десятки или сотни раз медленнее, чем транспорт ssh). Другим обходным решением является добавление некоторых нехэшированных записей в файл known_hosts, чтобы их мог найти ssh-транспорт ansible.

person Jean-Paul Calderone    schedule 31.07.2013

Поскольку у вас включен HashKnownHosts, вам следует выполнить обновление до последней версии Ansible. В версии 1.3 добавлена ​​поддержка хеширования known_hosts, см. систему отслеживания ошибок и журнал изменений. Это должно решить вашу проблему без ущерба для безопасности (обходной путь с использованием host_key_checking=False) или потери скорости (ваш обходной путь с использованием paramiko).

person Jan Gondol    schedule 15.09.2013
comment
Это мой отчет об ошибке после обнаружения причины проблемы здесь. :) - person Jean-Paul Calderone; 15.09.2013
comment
О, я не знал, что вы сообщили об этом (проблема с GH была открыта mpdehaan и исправлена ​​jimi-c). Спасибо, что обратили на это внимание разработчиков! :) - person Jan Gondol; 17.09.2013

В Ansible 2.0 Python API я отключил StrictHostKeyChecking с помощью

import ansible.constants

ansible.constants.HOST_KEY_CHECKING = False

Мне удалось значительно ускорить Ansible, установив на управляемых компьютерах следующее. Я думаю, что у более новых sshd по умолчанию наоборот, поэтому в вашем случае это может не понадобиться.

/etc/ssh/sshd_config
----
UseDNS no
person user7610    schedule 23.04.2016