Всем привет. Знакомство с паппетом у меня началось достаточно недавно, году в 2021, и на тот момент когда я решил, что в моем "хозяйстве" стоит попробовать его внедрить, я начал искать всевозможную информацию по нему. Информации только на хабре можно почерпнуть достаточно много, но к сожалению, в самом начале достаточно сложно уложить всё прочитанное в голове, особенно когда в одной статье говорится про использование паппета без ENC (которое тоже не сильно понятно для чего нужно в самом начале), в другой приводятся примеры использования с Hiera, а в третьей статье рассказывается про то, как написать свой собственный манифест, без привязки к пути, по которому выполняется управление хостами. Лично мне потребовалось достаточно много времени чтобы понять, как всё описанное связывается с конкретными компами, и как вообще я должен всем этим управлять. В итоге собрав свой зоопарк я всё же смог всё уложить в голове, и хочу оставить на хабре всё то, чего я хотел бы узнать в самом начале, когда только начинался мой путь постижения паппета. Если вы только начинаете изучать Puppet (в связке с Foreman с которым я всё это и изучал), то возможно я смогу под катом ответить на возникшие вопросы. Хочу предупредить - всё что я буду описывать является лишь упрощением того как есть на самом деле. В большинстве случаев опущены функции которые также могут выполняться описанным, или например связь одного со вторым может и будет двусторонней, но это должно быть осознано уже при непосредственном использовании, а чтобы непосредственно начать использовать, нужно понять как всё это хотя бы условно связано. Я по мере возможностей буду описывать, что ещё возможно в том или ином случае, но в самом начале всё будет максимально просто, чтобы уложить это в голове. Первым делом когда я только приступил к изучению паппета, я не мог понять, как в принципе взаимосвязаны Puppet, Foreman, группы хостов и параметры хостов и групп, и как вообще хосты определяют, что именно из написанного предназначается конкретно им, а не соседним хостам. Для ответа на этот вопрос я предложу следующую схему: Admin - условный админ компов, который будет решать, какие конкретно классы должны быть применены на каком компе. Он по сути решает, как делить хосты на группы, какие параметры хостам и группам должны задаваться. Также он "одобряет" подключение агента к серверу. Foreman - та web часть, с которой админ будет всё время работать. В формане хранится весь тот набор "одобренных" хостов, списка групп и принадлежность хостов группам, соответствие классов хостам и группам, а также значения параметров, необходимых для применения классов. Puppet Server - та самая "подкапотная" часть, которая обрабатывает соединения Puppet agent'ов установленных на управляемых хостах. Когда агент подключается к серверу, сервер "спрашивает" у Foreman'а, какие классы необходимо применить на этом самом хосте - форман в соответствии с тем, что настроил Admin уже подготавливает список, какие классы необходимо применять, выдает список значений параметров классов, которые должны использоваться, и сервер после этого выдаёт агенту ответ, что необходимо применить. Сами классы, которые доступны для применения на хостах хранятся именно на нём. Programmer - это в нашем случае будет тот же самый Admin в лице нас, который будет писать свои собственные классы, которые уже будут храниться на Puppet Server. В большинстве примеров предлагается установить уже существующий модуль, список которых вы можете посмотреть на сайте Puppet Forge, однако возможность написания своего класса для настройки всего что угодно является одной из важнейших во всей этой затее с использованием паппета. Puppet agent - та самая клиентская часть, которая устанавливается на хосте и работает в виде сервиса, и раз в 30 минут выполняет подключение к серверу, и каждый раз применяет классы, которые сервер передал агенту на исполнение. Установка вполне описана на офф сайте, всё что нужно это в соответствии со своим дистрибутивом (в моем случае debian 11) пройти по инструкции https://www.theforeman.org/manuals/3.8/quickstart_guide.html Всё что нужно будет после подготовки сделать, это выполнять инструкции команды foreman-installer (которая по сути установит всё что нужно, в том числе и сервер паппета, и агента паппета для управления этим сервером) до тех пор пока установка не пройдет успешно (с выводом сгенерированного пароля который понадобится для входа). Спойлер - для установки требуется: Задать имя хоста в формате fqdn - задать хотя бы домен чтобы имя хоста было puppet-test.local В файле /etc/hosts добавить строку вида 192.168.0.2 puppet-test.local puppet-test чтобы fqdn был первым в списке имен. Результирующий вывод, который скажет что всё в порядке, это В котором как раз и выведен нужный нам для входа пароль. Не забудьте первым делом после входа поменять пароль на нужный (правый верхний угол, через настройки профиля) или же хотя бы его скопипастить. Думаю прежде чем пойти объяснять что-то, что работает под капотом, было бы неплохо увидеть это в живую (хотя бы на скринах), чтобы осознавать о чём будет идти речь дальше. Первое что будет видно при входе это список хостов, и самый первый же хост - наш сервер. Сервер также управляется паппетом, потому можно использовать на нём уже существующие модули и классы. Я позволил себе чуть-чуть по создавать новых объектов и сразу добавить puppet-test.local в новую, только что созданную группу чтобы было чего показывать. По началу нам будут интересны списки групп: И списки классов Как, надеюсь, уже успели понять из прочитанного выше, основной смысл настройки хостов заключается в составлении соответствий между Host Groups и Classes (хотя можно настраивать соответствие классов с одиночными хостами, интерфейс при этом по сути один и тот же). Но всё же, прежде чем начинать настраивать эти соответствия, давайте немного углубимся в теорию. Foreman в нашем случае является ENC (external node classifier) для Puppet Server, и если вы читали статьи, в которых предлагается что-то настраивать с использованием Hiera (ей я не пользовался), то значит она заменяет Foreman на рисунке 1, и Admin должен будет уже не в вэбе делать всё то что я описал выше, а в текстовых конфигах хиеры, и принципиальная разница от этого не изменится - просто сервер будет запрашивать что применять не у формана а у неё. Ещё как вариант можно описывать хосты без использования ENC, в файлах паппета на сервере, он с этим вполне справится, но это уже другие случаи, которые к статье не относятся. Также для понимания стоит описать, что же такое класс - это файл который должен быть сохранен в определенном каталоге на сервере и должен быть импортирован в формана для его дальнейшего использования (об этом чуть ниже), который в определенном формате описывает, что должно быть этим классом настроено. Например у нас есть некая прога, которая должна быть установлена и настроена на подключение к определенному серверу в сети - в таком случае мы должны описать, что эта прога должна быть установлена (ресурс package), сервис должен быть добавлен в автозагрузку и запущен всегда (ресурс service), а в конфиге этого сервиса должны быть прописаны нужные нам параметры, которые могут отличаться от хоста к хосту или от группы к группе, что будет реализовано в виде параметров в формане, и потому мы должны будем сгенерировать файл конфига (ресурс file или ресурс ini_setting). Ресурсы это "объекты" которые доступны для использования в классах и являются независимыми от того какой это дистрибутив, они выполняют настройку - например ресурс package это "объект" который будет устанавливать указанный пакет через доступного в этой операционной системе пакетный менеджер. Весь набор который нам нужно настроить может быть полностью написан нами, тем самым мы создаем свой собственный модуль - один или несколько классов нужных для этого, либо, если это уже типовая задача, то скачиваем и устанавливаем готовый модуль с Puppet Forge. Просто чтобы хоть как то внести конкретики, чтобы это можно было уложить в голове, я приведу пример класса, который всё описанное из примера выше выполнит: ресурс package с помощью apt или yum (или даже chocolatey - менджер пакетов в винде, но с дополнительной установкой "зависимостей" при установке агента на винде) установит нужный пакет, ресурс service через команды systemctl (systemd) или service (system V) сделает enable и start (или в случае винды через виндовую команду service всё аналогичное), а file создаст файл с требуемым содержимым, и благодаря notify запросит рестарт сервиса famous_prog после изменения конфига (если файл поменялся). Итоговый класс будет под этим именем (Рисунок 4) присваиваться хосту или группе, и таким образом при следующем подключении агента данный класс применится, и на всех хостах входящих в хостгруппу (Рисунок 3) кому класс был присвоен программа будет установлена и настроена. То как именно правильно писать свои классы (модули) нужно будет читать и практиковаться отдельно, я же лишь хочу прояснить, что именно эти написанные или скачанные модули и будут тем самым, что Admin будет в Foreman привязывать хосту или группе хостов на исполнение. Давайте вернемся к примерам со скринами - допустим мы хотим хостгруппе repo-servers (Рисунок 3) присвоить класс install_and_configure_famous_prog, который будет выполнять установку нужной нам программы на всех хостах из этой группы - для этого нужно открыть хостгруппу на редактирование и на вкладке Puppet ENC просто выбрать нужный нам класс нажатием "+" - всё, после сохранения написанный нами класс будет применён в течении получаса (дефолтное время через которое агенты паппета на хостах синхронизируются с сервером) на всех хостах группы. Раз уж на примере уже посмотрели как происходит присвоение классов, пойдем дальше в теорию. Ко всему описанному ещё нужно добавить такое понятие как environment (окружение), создание которых также доступно и должно быть использовано, в дополнении к дефолтному под названием production, в которое все новые хосты добавляются. Основной функцией окружений я бы считал возможность установки или создания модулей для каждого окружения по отдельности. Как пример, к которму пришел я, могу привести создание доп окружения testing, в котором хранятся копии всех модулей, что хранятся в окружении production, и которые можно спокойно править не боясь сломать то, что сейчас уже работает, а после опробования взять и скопировать в прод. Пример файла с классом install_and_configure_famous_prog описанным выше, который будет доступен в окружении testing должен быть сохранен по пути: Паппет опирается на определенную иерархию папок, в которых названия имеют значения - прежде всего это папка где хранится по сути всё связанное с модулями и классами - каталог /etc/puppetlabs/code: В папке ./modules будут появляться все установленные "глобально" модули, т.е. доступные для любого environment. В папке ./environments содержатся каталоги с названиями окружений. Если требуется создать новое окружение, то оно будет создаваться новой папкой внутри ./environments с созданием иерархии аналогичной ./environments/production. Папка ./environments/production это по сути дефолтное окружение, которое будет присваиваться всем вновь добавленным хостам (это настраиваемо), и оно будет ограничивать список классов доступных для присвоения хостгруппам лишь теми, что лежат в этой папке (или из числа глобальных). Весь список мы рассматривать не будем (так как часть относится как вы догадались к Hiera - другой ENC которая также доступна для использования), потому обратим внимание лишь на два каталога: ./environments/production/manifests ./environments/production/modules Отличие первого от второго в том, что в modules можно хранить в одной "куче" всё что относится к нашему модулю, в то время как в manifests можно сразу создавать файлы с классами, которые также будут доступны для присвоения хостгруппам. В ./environments/production/modules/{module_name} как в примере с install_and_configure_famous_prog можно группировать связанные с нашим классом файлы и шаблоны, которые в этой статье не рассматривались, но можно было бы сделать иерархию вида и все файлы и шаблоны будут доступны для использования в коде нашего класса. В принципе создавать классы сразу в папке ./environments/production/manifests никто не запрещает, но и создавать всё в виде модулей с расчетом что в будущем может понадобиться расширение функционала тоже никто не запрещает - я лично создаю всё модулями. Самое главное, что как только добавляется новый класс или меняется его список переменных, то форману нужно сообщить об этих изменениях через импорт окружений, что заставляет его перечитать весь список классов с предложением подтвердить изменения - делается это через страницу Configure -> Puppet ENC -> Environments и нажать кнопку "Import environments from puppet-test.local". Повторный импорт класса не требуется при изменении внутренностей класса, а только лишь при изменении списка параметров. Под конец, для создания общей картины формана хотелось бы вкратце упомянуть о таких вещах как Location и Organization. Это достаточно мощные по функционалу объекты, которые при продвинутом использовании позволяют значительно упростить администрирование большого числа хостов, однако в случае нашей статьи, когда нужно лишь понять основы, локации и организации могут восприниматься как способы фильтрации списка хостов - в формане по дефолту идут уже созданные Default Location и Default Organization в которые вновь добавленные хосты прописываются, а новые можно создать соответственно в меню Administration -> Locations и Administration -> Organizations, после чего назначить хосты в эти самые локации и организации - в самом простом варианте это будет работать как отдельные "контейнеры" хостов, к которым можно регулировать доступ для разных ролей. В более сложном варианте для локаций и организаций можно прописывать ещё и параметры, которые будут доступны внутри кода классов, что с учетом наследования и переопределения параметров между организацией, локацией, хостгруппой и хостом может дать дополнительные возможности в коде классов, но это уже не относится к теме статьи. Думаю что описанного достаточно для того, чтобы начать свои собственные эксперименты с написанием собственных классов и применять их на тестовой виртуалке, которая будет выступать в качестве нашего подопытного - тем ни менее, подключение хоста к паппету это не самый лёгкий квест, и я постараюсь вкратце описать как это провернуть, чтобы наконец подопытный приступил к своим обязанностям. В принципе паппет сервер вполне способен работать с агентами разных веток, и лучше всего это описывает страница https://www.puppet.com/docs/puppet/7/primary_agent_compatibility.html Для примера я возьму в качестве подопытного всё тот же Debian 11, хотя никто не запрещает взять и другие дистрибутивы, даже RPM-based. В идеале даже я бы предложил использовать двух подопытных, DEB-based и RPM-based и одновременно на них проверять сотворенное. Первым делом нужно раздобыть пакет агента паппета - в моём случае я пойду в репо https://apt.puppet.com/pool/bullseye/puppet7/p/puppet-agent/index.html и скачаю последнюю версию пакета, который при соответствии релиза дебиана поставится одним пакетом без проблем. В идеале конечно стоит подключить репозиторий паппета, чтобы очередные обновления агента прилетали обычным apt upgrade, но для быстрого старта нам пойдет и разовая установка агента. После того как были выполнены команды wget и apt install нужно подготовить нашего подопытного для знакомства с сервером - во первых, в /etc/hosts нужно прописать соответствие адреса сервера и его ip - паппету важно работать по fqdn - прописываем ту же самую строку что мы прописывали на сервере в момент запуска foreman-installer. Агент паппета устанавливается не в /bin потому чтобы можно было вызывать его не по полному пути нужно обновить переменные окружения перелогинившись, либо использовать полный путь /opt/puppetlabs/bin/puppet. Далее нужно откорректировать конфиг агента, чтобы указать к какому серверу с какими параметрами нужно подключаться - для нашего простого случая будет достаточно в файле /etc/puppetlabs/puppet/puppet.conf прописать: И выполнить первую синхронизацию агента с сервером: Во время первой синхронизации будет создан сертификат для агента, который нужно будет подписать со стороны сервера, о чем будет сообщено: Подписать можно и через команду в консоли сервера, но давайте сделаем это через веб в формане - Infrastructure -> Smart Proxies -> puppet-test.local -> Puppet CA -> Certificates - там появится новый сертификат нашего подопытного, которого нужно подписать нажатием кнопки sign (на будущее - есть certificate autosign по маске сертификата): После того как мы со стороны сервера подписали сертификат на стороне агента нужно ещё раз выполнить синхронизацию: В этот раз синхронизация пойдет дальше а подтверждением того что всё прошло как нужно будут строки: После этого можно будет пойти в список хостов формана и удостовериться что новый хост там появился. После этого самое главное не забыть добавить в автозагрузку и запустить сервис паппета: Наш подопытный готов к исполнению своих обязанностей. Чтобы не гадать над моим абстрактным классом install_and_configure_famous_prog предлагаю сделать первые шаги на конкретном примере: После этого создаем новый файл /etc/puppetlabs/code/environments/production/modules/my_first_class/manifests/init.pp и указать его содержимое: После чего выполнить импорт нового класса нажатием кнопки "Import environments from puppet-test.local": Подтверждаем добавление нового класса После чего новый класс готов к использованию в хостгруппах. Всё, для того чтобы создать новую хостгруппу привязать к ней новый класс, назначить эту хостгруппу нашему подопытному, и выполнить принудительную синхронизацию для того чтобы пакет htop установился автоматически (что на дебиане, что на федоре) нашим тестовым классом вы уже должны были узнать из этой статьи - начинайте пробовать отредактировать класс my_first_class добавляя в него использование разных ресурсов (https://www.puppet.com/docs/puppet/7/cheatsheet_core_types#cheatsheet_core_types - встроенные, не требующие установки новых модулей), посмотрите что можно увидеть на странице Monitor -> Dashboard, зайдите на страницу с информацией о хосте и посмотрите отчеты о синхронизации, попробуйте установить первый понравившийся модуль с Puppet Forge - наш небольшой полигон для этого готов. Этой статьей я хотел рассказать всё то, что хотел бы знать когда только начинал изучать паппета. Сейчас для меня всё описанное очевидно, но на тот момент я просто установил паппет сервер, подключил к нему агента и не знал как мне быть дальше - информации можно найти много, но когда она не сливается один большой взаимосвязанный ком легче от найденного не становится. Надеюсь что на часть вопросов, ради которых вы зашли под кат я смог ответить, если нет - быть может смогу ответить в комментариях?