Введение

Это ознакомительная публикация, обзор некоторых функций платформы Foreman, касающейся IaC Puppet.

Foreman предоставляет спектр инструментов для контроля за ИТ-средой, однако в статье описаны отдельные возможности, такие как:

  • использование Puppet модулей

  • установка параметров для Puppet

  • процесс доставки модулей

  • написание скриптов сбора искомых фактов

  • использование шаблонов для выгрузки репортов

  • также затронуто использовании программного интерфейса и базы данных

Возможности Foreman описаны с точки зрения пользователя платформы. Техническая реализация демонстрационного стенда рассматриваться не будет.

Если вам интересно прочитать об установке Foreman, плагина Bare Metal Controls, настройке GIthub Actions для CI кода Puppet, использовании r10k, Puppet линтеров и автотестов Puppet кода, а также работы со Smart-proxy (PXE, DHCP, DNS), пожалуйста, напишите нам. Контакты указаны в заключении публикации.

Компоненты стенда:

Сервер

Установленные компоненты

foreman-main.example.com

Foreman, Puppet Server, PostgreSQL.

test-server.example.com

Puppet Agent

Используем операционную систему Ubuntu 20.04 LTS и версию Foreman 3.7 без дополнительных плагинов.

Puppet манифесты в Веб-Интерфейсе Foreman

Задача:
Установить Zabbix Agent, указать в конфиге агента адрес Server=8.8.8.8.

Возможный способ решения, используя интерфейс Foreman:

Шаг 1. Из списка hosts выбираем test-server, нажимаем Edit.
Шаг 1. Из списка hosts выбираем test-server, нажимаем Edit.
Шаг 2. Во вкладке Puppet ENC назначаем манифест Zabbix::agent.
Шаг 2. Во вкладке Puppet ENC назначаем манифест Zabbix::agent.
Шаг 3. Выставляем значение для параметра Server и нажимаем Submit.
Шаг 3. Выставляем значение для параметра Server и нажимаем Submit.
Шаг 4. После применения конфигурации Puppet Agent проверяем репорт об успешной установке.
Шаг 4. После применения конфигурации Puppet Agent проверяем репорт об успешной установке.

В последнем отчете отображаются графики применения манифеста.

Шаг 5. Для проверки применения конфигурации в консоли сервера выполним поиск пакета Zabbix Agent и найдем новое значение Server в файле zabbix_agentd.conf.
Шаг 5. Для проверки применения конфигурации в консоли сервера выполним поиск пакета Zabbix Agent и найдем новое значение Server в файле zabbix_agentd.conf.

Вот и все, задача выполнена! Дальше Puppet Agent будет проверять и поддерживать указанную конфигурацию при каждом обращении к Puppet Server.

В этом примере и дальше в статье используется замечательный Zabbix Модуль который взят с forge puppet, но вы можете создавать Puppet модули на ваше усмотрение и для своих идей.

В следующих главах рассмотрим переопределение параметров, используемых в Puppet code.

Puppet Code и Puppet ENC

Разработка кода для Puppet ничем не отличается от любой другой разработки и может настраиваться с использованием систем контроля версий и любимым IDE. В этой публикации используется Pycharm и GitHub. У нас уже настроен Pycharm и пайплайн на GitHub для доставки кода к Puppet Server.

Задача:

Переопределить дефолтный параметр, отвечающий за сетевой адрес Zabbix Server, в Puppet модуле Zabbix.

Шаг 1. В модуле Zabbix редактируем манифест params.pp, меняем значение $agent_server с “127.0.0.1” на “8.8.8.8” и любым известным для вас способом отправляем в репозиторий.
Шаг 1. В модуле Zabbix редактируем манифест params.pp, меняем значение $agent_server с “127.0.0.1” на “8.8.8.8” и любым известным для вас способом отправляем в репозиторий.
Шаг 2. Запускаем CI. Код доставляется на Puppet Server, он же Foreman.
Шаг 2. Запускаем CI. Код доставляется на Puppet Server, он же Foreman.

При необходимости в консоли сервера foreman-main проверяем, что модули доставились и параметр прописался корректно.

Теперь по умолчанию для всех вновь установленных агентов Zabbix будет выставлен адрес Server=8.8.8.8.

Переопределим значение параметра Server для одного хоста, используя Puppet ENC.

Шаг 1. У хоста test-server указываем новое значение параметра.
Шаг 1. У хоста test-server указываем новое значение параметра.
Шаг 2. После применения конфигурации Puppet Agent просматриваем изменения с использование кнопки “Show Diff”.
Шаг 2. После применения конфигурации Puppet Agent просматриваем изменения с использование кнопки “Show Diff”.
Где отображаются детали работы агента: изменение строчки конфига zabbix_agentd.conf.
Где отображаются детали работы агента: изменение строчки конфига zabbix_agentd.conf.

Замечательные возможности, так можно легко доставлять код к Puppet Server → Puppet Agent и использовать параметры по умолчанию в коде Puppet, а также переопределять их в Puppet ENC.

Ниже отобразим реализацию дефолтного и переопределенного значений параметров через Foreman в Puppet ENC.

В левой части IDE открыт манифест params.pp c дефолтным значением параметра $agent_server (он же server из интерфейса Foreman).

В нижней части IDE отображается подключение через ssh к test-server и значение параметра Server из файла zabbix_agentd.conf.

В правой части IDE - подключение к БД Foreman и содержимое таблиц lookup_keys и lookup_values.

Итоги:

  • Для всех серверов, где будет установлен агент Zabbix, параметр $agent_server равен ‘8.8.8.8’

  • Для test-server.example.com параметр $agent_server переопределен в БД и равен “7.7.7.7”. Приоритет будет отдан значению, заданому в БД.

Дальше рассмотрим абстракции Foreman: Группы хостов, Организации, Локации и параметры, которые можно им задать.

Foreman Group hosts, Organization, Location and Parameters

Система Foreman имеет гибкую логику группирования хостов и вложенность параметров. Благодаря этому можно контролировать конфигурацию в зависимости от функционального назначения сервера. Например, разделять хосты в зависимости от требуемого ПО, расположения серверов и их назначения.

Полностью не получится ее рассмотреть в одной публикации, но для примера рассмотрим самый простой вариант.

Задача:

Создание группы, которая при назначении серверам будет устанавливать Zabbix Agent c заданным параметром $agent_server, отличным от значения по умолчанию.

Шаги решения задачи:

  • создание группы хостов

  • переопределение параметра в Puppet ENC у созданной группы хостов

  • назначение группы на сервер test-server.example.com

Шаг 1. Переходим в Confugure и создаем группу
Шаг 1. Переходим в Confugure и создаем группу
Указываем обязательные поля и Puppet Environment. В данном случае это имя ветки production из репозитория. Окружений может быть столько, сколько есть веток в репозитории. Разным группам можно назначать разные окружения.
Указываем обязательные поля и Puppet Environment. В данном случае это имя ветки production из репозитория. Окружений может быть столько, сколько есть веток в репозитории. Разным группам можно назначать разные окружения.
Шаг 2. Назначаем группе манифест Zabbix::agent
Шаг 2. Назначаем группе манифест Zabbix::agent
Переопределение параметр Puppet ENC.
Переопределение параметр Puppet ENC.
Шаг 3. Очистим параметр, заданный ранее, и перенесем наш сервер в новую группу.
Шаг 3. Очистим параметр, заданный ранее, и перенесем наш сервер в новую группу.
Выбираем группу test_group и нажимаем Submit
Выбираем группу test_group и нажимаем Submit

После применения конфигурации Puppet Agent видим новый параметр в конфиге агента Zabbix, переопределенный для группы хостов test_group.

Теперь рассмотрим возможность создания параметров группы. Это отличные от Puppet ENC параметры, которые можно использовать в модулях Puppet.

Присваиваем группе test_group новый параметр группы “test_parameter_zabbix” с типом данных string и значением “5.5.5.5”.
Присваиваем группе test_group новый параметр группы “test_parameter_zabbix” с типом данных string и значением “5.5.5.5”.

Используем параметр группы test_parameter_zabbix как значение по умолчанию переменной $agent_server в манифесте Puppet.
Предварительно нужно обязательно убрать переопределение из вкладки Puppet ENC.

Рассмотренный параметр можно увидеть в таблице parameters.
Рассмотренный параметр можно увидеть в таблице parameters.

После применения конфигурации Puppet Agent в отчете отображается значение, заданное с использованием параметра группы.

Аналогично можно управлять хостами с разделением на Организации и Локации, которые позволяют включать в себя Группы и отдельные хосты.

Сгруппируем сервера по двум филиалам: Север и Юг. Эти абстракции будут иметь разное значение параметра $agent_server.

Рассмотрим создание организации North Branch.

Шаг 1. В меню Organizations нажимаем кнопку “New Organizations”
Шаг 1. В меню Organizations нажимаем кнопку “New Organizations”
Указываем название.
Указываем название.
Шаг 2. Указываем использование Smart Proxies.
Шаг 2. Указываем использование Smart Proxies.
Шаг 3. Задаем новый параметр организации $branch_parameter_zabbix.
Шаг 3. Задаем новый параметр организации $branch_parameter_zabbix.
Добавляем сервер в организацию.
Добавляем сервер в организацию.

Указываем в манифесте params.pp созданный параметр организации $branch_parameter_zabbix, который можно просмотреть в таблице parameters.

После применения конфигурации Puppet Agent в отчете отображается значение, заданное с использованием параметра организации.

В этой главе мы рассмотрели возможность каталогизацией серверов и использования иерархии параметров.
Подробнее ознакомиться с иерархией параметров можно по ссылке.

Далее перейдем к Puppet фактам и их просмотру.

Просмотр Puppet facts в Foreman

В этой части узнаем, как просматривать факты Puppet в веб-интерфейсе и в БД.

С помощью Puppet собирается информация о серверах, которая хранится в виде абстракций под названием Puppet facts.

Есть дефолтные факты, например, название ОС и сетевой адрес. Также возможно собирать кастомные факты, такие как наличие смонтированных сетевых каталогов, версия установленного ПО и т.д.

Одним из способов просмотра собранных фактов является вкладка Monitor → Facts веб-интерфейса. Есть возможность поиска фактов по атрибутам хост, название факта и его значение, наличие факта.

Например, запросим все собранные факты для хоста test-server.

Перейдем Monitor -> Facts
Перейдем Monitor -> Facts
В поиске укажем host = test-server.example.com
В поиске укажем host = test-server.example.com

Также есть возможность доступа к фактам напрямую из БД.

select distinct hosts.name, fact_names.short_name, fact_values.value
from hosts
join fact_values on hosts.id=fact_values.host_id
join fact_names on fact_values.fact_name_id=fact_names.id
where hosts.name  = 'test-server.example.com';

На скриншоте видно выполнение запроса в БД Foreman и получение фактов test-server.

С помощью этой информации можно визуализировать данные, допустим используя Grafana, проводить анализ и находить закономерности.

Допустим у нас есть задача:

Получить данные о точках монтирования NFS на хосте для всего парка серверов и использовать в логике Puppet манифестов.

Эту задачу можно решить с использованием кастомных фактов.
Пример скрипта для сборки факта о точках монтирования. Этот скрипт будет выполняться на всех серверах, вывод будет получен Puppet Server и станет доступен в БД и в веб-интерфейсе.

# nfs_search.rb

awk = "/usr/bin/awk"

if File.exist?(awk)
    Facter.add('nfs_search') do
        setcode do
          Facter::Core::Execution.execute('\'awk\' \'$1 ~ /^([0-9]|\/\/)/ {print $1 ","}\' /proc/mounts')
        end
    end
end

В данной главе мы рассмотрели возможность сбора информации о серверах, используя Puppet facts. Эти значения могут быть использованы в логике манифестов и аудите системы.

Далее рассмотрим использование собранных фактов в Report Templates.

Report templates в Foreman

Report templates использует шаблонизатор ERB для создания отчетов, которые можно сгенерировать в виде файлов через веб-интерфейс или запросить с помощью API Foreman.
Рассмотрим использование такого отчета и получение его из веб-интерфейса. Отчеты используют могут использовать собранные факты.

Задача: Получить список всех хостов, их сетевой адрес и название операционной системы.

Почмотрим на реализацию:

Шаг 1. В меню выберем Report Templates и используем заготовленный ранее шаблон.
Шаг 1. В меню выберем Report Templates и используем заготовленный ранее шаблон.
Нажимаем Generate
Нажимаем Generate
Шаг 2. При выборе шаблона по усмотрению можно указать выражение поиска. По умолчанию в выборку попадут все зарегистрированные в Foreman хосты. Выбираем формат файла.  После нажатия на кнопку “Generate” отчет будет доступен для загрузки и просмотра.
Шаг 2. При выборе шаблона по усмотрению можно указать выражение поиска. По умолчанию в выборку попадут все зарегистрированные в Foreman хосты. Выбираем формат файла. После нажатия на кнопку “Generate” отчет будет доступен для загрузки и просмотра.
Шаг 3. В полученном файле отчета отображаются 2 сервера, включая столбцы с сетевыми адресами и названием ОС.
Шаг 3. В полученном файле отчета отображаются 2 сервера, включая столбцы с сетевыми адресами и названием ОС.

Для генерации данных использовался шаблон:

<%#
name: test - status
snippet: false
template_inputs:
- name: hosts
  required: false
  input_type: user
  advanced: false
  value_type: search
  resource_type: Host
model: ReportTemplate
-%>

<%- load_hosts(search: input('hosts')).each_record do |host| -%>
<%-   report_row({
        'server_name': host.name,
        'network_address': host.facts['ipaddress'],
        'OS': host.facts['os::name'],
              }) -%>
<%- end -%>
<%= report_render -%>

Отчеты можно использовать в решении разных задач, таких как аудит инфраструктуры.

Все отчеты, доступные из веб-интерфейса, можно запросить с использование API Foreman, что будет рассмотрено далее

API Foreman

В этой главе рассмотрим использовании API Foreman.

Задача:
Получить данные отчета через http запрос.

Пример решения задачи с использованием Postman:

Шаг 1. Укажем метод POST, логин и пароль для типа авторизации Basic Auth (Foreman может использовать токены для авторизации).
Шаг 1. Укажем метод POST, логин и пароль для типа авторизации Basic Auth (Foreman может использовать токены для авторизации).
Шаг 2. Указываем тип данных JSON и тело запроса: { “report_format”: “json” }
Шаг 2. Указываем тип данных JSON и тело запроса: { “report_format”: “json” }
Шаг 3. В ответе сервера получен сгенерированный отчет в формате json на основе шаблона test_template.
Шаг 3. В ответе сервера получен сгенерированный отчет в формате json на основе шаблона test_template.

Такая возможность может пригодитьcя в реализации автоматизации или интеграции.

Решим ту же задачу с использованием Python класса.

#!/usr/bin/python3
import requests
from pprint import pprint
import urllib3

urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)


class ReportGenerator:
    def __init__(self, api_url, auth):
        self.api_url = api_url
        self.auth = auth

    def generate_report(self):
        json_data = {
            "report_format": "json"
        }

        response = requests.post(self.api_url,
                                 auth=(self.auth['user'], self.auth['pass']),
                                 json=json_data,
                                 verify=False)

        return response.json()


if __name__ == "__main__":
    auth_credentials = {'user': 'your_login', 'pass': 'your_pass'}
    api_url = 'https://foreman-main.example.com/api/report_templates/148/generate'

    report_generator = ReportGenerator(api_url, auth_credentials)
    api_response = report_generator.generate_report()
    pprint(api_response)

Результат выполнения скрипта:

API Foreman очень функционален и поможет в автоматизации.
В публикации рассмотрен простой пример выгрузки Report Template.

Среди возможностей API:

  • создание/удаление хостов

  • отзыв сертификатов

  • переопределение параметров любого уровня

  • назначение Puppet манифестов, групп, организаций и многое другое

Обо всех возможностях API вы можете узнать на официальном сайте Foreman.

Заключение

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

Благодарим, что вы дочитали до этого пункта. Эта публикация - попытка передать пользовательский опыт. Мы кратко коснулись функционала, который связан с подходом IaC, стараясь не перегружать текст техническими подробностями.

Не стесняйтесь использовать комментарии к этой статье и наши контакты, нам действительно интересна обратная связь. Планируется начать цикл публикаций про Foreman и его компоненты.

Контакты:
Почтовый адрес george.article.feedback@gmail.com

Авторы публикации:
Минашвили Георгий, Воля Яна, Чердаков Игорь.

Комментарии (3)


  1. inchARAkoreicivpered
    26.09.2023 14:54
    -1

    Отличная статья. Удачи в будущих проектах!


  1. looofi
    26.09.2023 14:54

    Здарова, отец


  1. GrimAnEye
    26.09.2023 14:54
    +1

    Работаю во внутренней техподдержке и у наших пользователей зоопарк разных линуксов и windows. При обновление основного образа debian или внесении неких локальных изменений постоянно возникала проблема обновления уже имеющихся систем. До этого использовался ansible, но его проблема - если пк нет в сети, обновления не будет, а чем больше не полученных изменений - тем хуже и проще перезалить пк с нуля.

    Задался вопросом централизации конфигурации - все настройки лежат на сервере, агент с пк должен подключаться к нему, выгружать и применять их. Были рассмотрены и опробованы:

    • ansible-pull - жирно по весу, отсутствие контроля за состоянием системы (никаких данных по умолчанию не присылает). Для пользовательского пк не подходит

    • Puppet - была установка сервера с foreman и агенты на пк. С первого взгляда устраивало всё, функционал работал, но возникли первые проблемы:

      • Puppet шифрует соединение выпуском ssl сертификатов в своём личном центре сертификации. Его же использует для web-интефейса, а следовательно подключение к web интерфейсу изначально недоверенное. Замена его на корпоративный wildcard сертификат, с последующим обновлением, оборачивается долгими развлечениями с тонкими настройками сервиса, который представляет из себя мутанта из apache и perl (? не помню точно), так, чтобы и web-интерфейс работал и агенты имели возможность подключения к сервису по старому серту. При обновлении сервиса все настройки конечно могут успешно отвалиться и начинать можно с нуля.

      • Всё тот же ЦС используется для выпуска ssl-сертификатов для агентов на пк. Но есть нюанс - у нас есть пк внутри сети с DNS-сервером и "удаленщики" подключающиеся по vpn без dns, только с DHCP. SSL-сертификаты на IP-адрес не выпускаются. Делать костыль - резервировать для сети vpn dns имена? Проблем станет еще больше - либо обновляй ключи при подключении клиента, либо регистрируй каждый MAC в белом списке. Опять таки проблема.

      • Pupper DSL - после yaml, jinja2 от ansible puppet dsl смотрится необычно и придется учить его с нуля. По сути не проблема, но компетенция других членов команды расти будет медленно (я же не для себя сервис поднимаю, его еще поддерживать потомкам)

      • Итог - Puppet конечно хорошо если используется внутри сети с DNS, нет проблем с подменой SSL-сертификата для web-панели или iptables ограничение доступа с определенных хостов, есть навыки работы с ruby. В плане работы отзыв оставить не могу, отказался от него еще на этапе настройки сервиса, по причинам выше.

    • Chef - не попробовал, но в обзорах он шел под руку с puppet. Причина - сначала деньги, потом - тапки.

    • SaltStack - начинаю строить систему сейчас на нём. Плюшки и нюансы которые уже удалось выявить:

      • В отличии от puppet, для безопасного подключения агент-сервер используется AES ключи. Нет страданиям с SSL для web и меж агентами на ПК. Успешная работа при наличии только ip-адреса и nat.

      • Структура sls-файлов в yaml-формате и адаптация после ansible проходит гораздо проще (в основной части)

      • Minion может работать без сервера, используя локальные файлы состояний. Пробую схему заливки пк через salt-minion, чтобы структура образа была одинакова и в момент установки и при использовании.

      • Для web-интерфейса использую https://github.com/erwindon/SaltGUI . Пока идет только подготовка системы про его функциональность ничего не скажу - можно подтвердить ключ агента, посмотреть состояние подключенных агентов и запустить обновление состояний. Вроде бы ОК.