В предыдущей статье (Ansible полигон для отладки на LXC) мы создали на локальном lxc хосте несколько миньонов, чтобы отлаживать на них playbook.
В конце остался один вопрос: для чего в inventory включена переменная lxc_host? Она, в частности, использована для делегирования task на хост при создании миньона.
Наиболее пытливые умы обнаружили ее в условии when при настройке DHCP. Во всех этих местах можно просто указать localhost и все будет работать.
Но, при наличии переменной, легким движением руки, локальный полигон превращается в элегантный распределенный! Достаточно добавить в inventory еще один lxc хост.
playground.distributed.yml:
Здесь применяется магия: для доступа к миньонам на secondhost (которые, заметьте, обладают теми же ip адресами), используется техника ssh jump host. Все еще никаких модулей и иных «оберток над оберткой» - работаем строго с минимально необходимым.
Фактически, ssh клиент подключается не напрямую к миньону второго созыва (туда просто нет маршрута), а к secondhost. Который, в свою очередь, прозрачно, без участия ansible и безвозмездно (то есть, из коробки) подключается к собственному миньону. Когда будете воспроизводить такой полигон у себя, не забудьте в параметрах заменить sshjump@secondhost на имя существующего пользователя и реальное имя (или адрес) secondhost.
«Позвольте, как это? Из коробки?!» Да, увы. Очередной SSH подарок безопасности. Точнее, от безопасности.
Но есть и ложка дегтя, которую добавляют совпадающие ip адреса миньонов. Внимательный читатель заметит на втором хосте отключение StrictHostKeyChecking. Здесь пришлось прибегнуть к темной магии, так как утилита ssh-keyscan не умеет jump host. Обязательный дисклеймер - никогда не делайте так на production. Но мы и не на production, а на полигоне.
Конечно, можно с помощью «lxc-attach cat /etc/ssh/host_*_key.pub» выкачивать в stdout ключи свежерожденного миньона, и добавлять их в цикле в собственный known_hosts. В качестве побочного эффекта это приведет к удвоению записей для совпадающих ip. Оставим это в качестве домашнего задания (комментарии приветствуются).
Наводим красоту
Ничто так не раздражает, как лежащий без дела task. Точнее, выведенный от него в отчете skip. При детальном изучении генератора таблицы статичных DHCP адресов выясняется, что для каждого lxc хоста просматриваются и миньоны всех остальных. И, закономерно, skip, так как условие when не выполнилось. Если для настройки миньона skip как раз информативны (как бы намекают, что нам не пришлось ничего делать), то в этом task это просто шумовая нагрузка, которая портит среднюю температуру по отчету.
TASK [Configure DHCP] **************************
skipping: [secondhost] => (item=minion101)
skipping: [secondhost] => (item=minion102)
skipping: [secondhost] => (item=minion103)
changed: [secondhost] => (item=minion201)
ok: [localhost] => (item=minion101)
ok: [localhost] => (item=minion102)
changed: [secondhost] => (item=minion202)
ok: [localhost] => (item=minion103)
skipping: [localhost] => (item=minion201)
skipping: [localhost] => (item=minion202)
skipping: [localhost] => (item=minion203)
changed: [secondhost] => (item=minion203)
Откладываем в сторону палочку с пером феникса и достаем бузинную. Все наши магические переменные, а в частности, groups — всего лишь списки и словари. А значит, мы можем к ним применять фильтры. И наш цикл настройки DHCP вполне можно сразу на этапе with_items ограничить только требуемым lxc хостом. When тут вообще становится лишним — я его вставил в предыдущую версию как подсказку. Это будет первое на сегодня изменение самого playbook, и оно никак не повлияет на его работу в предыдущем сценарии. Действительно, попытка ограничить список одним lxc хостом, когда он из него одного и состоит никак не ухудшает ситуацию.
Здесь фильтр сразу подсматривает в атрибуты списка и выбирает только принадлежащих хосту миньонов. Никаких раздражающих бессмысленных циановых строчек в отчете.
Превращаем словарь в список. Первый selectattr выбирает только те контейнеры, у которых определено свойство lxc_host (действительно, зачем нам сами lxc хосты, а, тем более, localhost). Второй selectattr оставляет только принадлежащих текущему обрабатываемому lxc хосту. А вот третий selectattr убеждается, что мы имеем дело только с легитимными желтыми миньонами. Потому что, среди них могли затесаться фиолетовые, и раздражать их совершенно не надо.
Использование словаря hostvars (и всех других магических словарей и списков) с фильтрами является очень сильной магией и позволяет организовать гораздо более сложную логику обработки хостов (с проверкой неожиданных и динамических условий, например, на основе собранных фактов), чем доступна через штатную группировку и hosts.
Запускаем.
$ ansible-playbook lxc_pg.distributed.yml -i playground.distributed.yml
Теперь у нас есть второй lxc хост, и миньоны на нем. По традиции, удаляем вторых миньонов на обоих хостах и запускаем повторно. И еще раз.
Вместо заключения
Как вы могли догадаться, этот же inventory можно нужно использовать при отладке своих playbook на полигоне. Или подключать его как вторичный inventory.
Достаточно добавить в него необходимые вам группы, назначив им соответствующих миньонов. Адреса и способы доступа playbook возьмет из существующего описания полигона.
Код этого playbook для изучения вы можете скачать по ссылке https://gitflic.ru/project/wingedfox/dzen-ansible/file/?file=lxc_pg.distributed&branch=master из моего репозитория.