Найти тему

Расширяем Ansible LXC полигон

Оглавление

В предыдущей статье (Ansible полигон для отладки на LXC) мы создали на локальном lxc хосте несколько миньонов, чтобы отлаживать на них playbook.

В конце остался один вопрос: для чего в inventory включена переменная lxc_host? Она, в частности, использована для делегирования task на хост при создании миньона.

lxc_pg.yml
lxc_pg.yml

Наиболее пытливые умы обнаружили ее в условии when при настройке DHCP. Во всех этих местах можно просто указать localhost и все будет работать.

Но, при наличии переменной, легким движением руки, локальный полигон превращается в элегантный распределенный! Достаточно добавить в inventory еще один lxc хост.

playground.distributed.yml:

playground.purple.yml (тут затесались еще два фиолетовых - пока игнорируем)
playground.purple.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 хостом, когда он из него одного и состоит никак не ухудшает ситуацию.

lxc_pg.distributed.yml
lxc_pg.distributed.yml

Здесь фильтр сразу подсматривает в атрибуты списка и выбирает только принадлежащих хосту миньонов. Никаких раздражающих бессмысленных циановых строчек в отчете.

Превращаем словарь в список. Первый 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 возьмет из существующего описания полигона.

playground.distributed.yml расширение inventory для использования полигона
playground.distributed.yml расширение inventory для использования полигона

Код этого playbook для изучения вы можете скачать по ссылке https://gitflic.ru/project/wingedfox/dzen-ansible/file/?file=lxc_pg.distributed&branch=master из моего репозитория.