Привет всем.
В рамках данной заметки хотелось бы поделиться опытом использования кастомных, или как их еще называют внешних (external).
Перед каждым запросом к серверу, puppet-агент собирает все факты о системе при помощи улититы facter
. Далее эти факты будут переданы на puppet-мастер, который в свою очередь опираясь на полученные факты сгенерит и отправит puppet-агенту обновленный каталог.
В больших инфраструктурах бывает недостаточно использования стандартного набора фактов, и дефолтный список дополняют внешними. Мой случаи описывает ситуацию, в которой требуется расширить возможности hiera
, за счет логического разделения инфраструкруты по запущенным сервисам, путем добавления дополнительных фактов.
Ручное добавление фактов
Давайте представим такую ситуацию, что к нам пришла задача в которой требуется разбить хосты по группам - ServiceA
и ServiceB
.
В данном случаи, на основании дефолтных фактов мы можем группировать хосты только по семейству и версии операционки. Добавим группировку по типу запущенного сервиса.
Обновляем hiera.yaml
Идем в наше окружение, и обновляем файл hiera.yaml
.
[root@puppetmaster ~]# cd /etc/puppetlabs/code/environments/production/
[root@puppetmaster production]# vim hiera.yaml
---
version: 5
defaults:
datadir: data
data_hash: yaml_data
hierarchy:
- name: "Per-node data (yaml version)"
path: "nodes/%{::trusted.certname}.yaml"
- name: "Service data"
path: "services/%{::service}.yaml"
- name: "Other YAML hierarchy levels"
paths:
- "common.yaml"
В середину нашей иерархии мы добавили новый уровень:
- name: "Service data"
path: "services/%{::service}.yaml"
Данные для этого уровня будут расположены в каталоге ./data/services
. У каждого сервиса будет свой одноименный файл данных.
Обновляем файлы окружения
Далее обновим файловую структуру на основании обновленного hiera.yaml
. Сначада создаем каталог services
, затем наклепаем yaml-файлики:
[root@puppetmaster production]# mkdir data/services
[root@puppetmaster production]# touch data/services/service-a.yaml
[root@puppetmaster production]# touch data/services/service-b.yaml
Продолжаем модулировать ситуацию, и теперь представим что на нашей условной инфраструктуре у хостов service-a
должен в качестве беканда стоять postgresql, а у хостов service-b
соответвенно должен стоять mysql.
В hiera файлах зафиксируем этот момент, указав значения переменной:
[root@puppetmaster production]# vim data/services/service-a.yaml
---
default_database: postgresql
[root@puppetmaster production]# vim data/services/service-b.yaml
---
default_database: mysql
Пишем манифест
Для демонстрации, напишем простой манифест, который будет только устанавливать субд. Для будущего манифеста создаю вот такую файловую структуру:
[root@puppetmaster production]# mkdir modules/setup_database/manifests -p
Далее внутри нашего модуля инициирую новый класс именем - setup_database
:
[root@puppetmaster production]# vim modules/setup_database/manifests/init.pp
---
class setup_database (
String $database_package = lookup('default_database', default_value => 'mariadb'),
) {
package {"$database_package-server":
ensure => 'present',
}
}
В атрибутах класса определяется единственная переменная $database_package
, значение которой puppet найдет их данных hiera. Обратите внимание, что в вызове lookup()
по мимо указания ключа, указываем значение которое будем использовать по умолчанию. То есть, если puppet не найдет значение по этому ключу, то будет использоваться указанное по умолчанию значение - mariadb.
Далее уже в теле класса следует один единственный ресурс - package
, который просто установит пакет.
Проверить валидность манифеста можно командой:
[root@puppetmaster production]# /opt/puppetlabs/bin/puppet parser validate modules/setup_database/manifests/init.pp -v
Создаем кастомные факты
Для внешних фактов достаточно создать файлик в /opt/puppetlabs/facter/facts.d/
, с содержимым в формате - key = value
.
Например так:
[root@service-b ~]# echo "service=service-b" >> /opt/puppetlabs/facter/facts.d/facts.txt
Данный файлик создается на стороне хоста с агентом.
Далее что бы в проверочном формате получить значение, воспользуемся утилитой facter
. В качестве аргумента передаем ключ от значения:
[root@service-b ~]# /opt/puppetlabs/bin/facter service
service-b
На второй ноде аналогичным способом создаем кастомный факт:
[root@service-a ~]# echo "service=service-a" > /opt/puppetlabs/facter/facts.d/facts.txt
[root@service-a ~]# /opt/puppetlabs/bin/facter service
service-a
Подключаем hiera и определяем класс
Для подключения hiera, в манифесте site.pp
указываем импорт hiera-классов:
[root@puppetmaster production]# vim manifests/site.pp
---
hiera_include('classes')
Затем для всех хостов вешаем ранее созданный класс:
[root@puppetmaster production]# vim data/common.yaml
---
classes:
- setup_database
Если все сделали правильно, то в течении 3x минут на хостах уже будут поставлены пакеты.
Подключамся в серверу - service-a.nixhub.ru
, напомню там должен быть установлен postgresql
, и проверяем:
[root@service-a ~]# rpm -q mysql
package mysql is not installed
[root@service-a ~]# rpm -q postgresql-server
postgresql-server-10.23-2.module_el8.8.0+3599+77865fc6.x86_64
Отлично изменения доставились. На втором сервере service-b.nixhub.ru
должен был установится пакет с mysql. Аналогичным способом убеждаемся в этом:
[root@service-b ~]# rpm -q postgresql-server
package postgresql-server is not installed
[root@service-b ~]# rpm -q mysql-server
mysql-server-8.0.32-1.module_el8.8.0+3567+56a616e4.x86_64
На этом достаточно, так на простом примере мы научились создавать свои факты для хостов. С помошью которых, у нас получилось раскрыть возможности hiera
немного больше.