Puppet — зрелая система управления конфигурациями, которая описывает желаемое состояние серверов на собственном декларативном языке. В отличие от разовых скриптов, она проверяет фактическое состояние и повторяет сходимость при каждом запуске, поэтому подходит для парка машин, где ручные правки уже опасны. Ниже — рабочий маршрут от установки Puppet Server до ролей, Hiera и безопасного применения каталога без неожиданных перезапусков.
Как устроен Puppet и когда он оправдан
Архитектура классическая: Puppet Server компилирует каталог для каждого узла, агент на машине применяет ресурсы и отправляет отчёт. Каталог строится из манифестов, шаблонов и данных Hiera. Ресурс описывает тип объекта — пакет, файл, службу, пользователя — и его параметры. Порядок внутри каталога задаётся зависимостями, а не порядком строк, поэтому важно явно связывать ресурсы через require, before, notify и subscribe.
Puppet выгоден, когда серверов десятки и нужна единая точка правды, аудит и воспроизводимость. Для одной машины или пяти контейнеров обычно хватает Ansible: Puppet требует сервера, сертификатов и дисциплины в данных, зато в большом парке даёт централизованные отчёты.
Установка Puppet Server и агента
Для Debian 12 Puppet распространяет собственный репозиторий. Пакет puppet8-release-bookworm.deb подключает ветку Puppet 8; для другой ОС имя файла отличается, поэтому сверяйтесь с официальным репозиторием. Серверу нужны стабильное имя, точное время и открытый порт 8140.
wget https://apt.puppet.com/puppet8-release-bookworm.deb
sudo dpkg -i puppet8-release-bookworm.deb
sudo apt update
sudo apt install puppetserver puppet-agent
После установки создайте CA и запустите службу. Puppet Server использует память Java; на стенде лимит можно уменьшить в /etc/default/puppetserver, а для production — 4 ГБ и больше. Убедитесь, что порт слушается.
sudo /opt/puppetlabs/bin/puppetserver ca setup
sudo systemctl enable --now puppetserver
sudo /opt/puppetlabs/bin/puppet --version
sudo ss -ltnp | grep 8140
На управляемой машине установите агент и пропишите certname с адресом сервера в /etc/puppetlabs/puppet/puppet.conf. Имя certname должно совпадать с FQDN либо быть явно задано на сервере.
[main]
certname = web01.example.lan
server = puppet.example.lan
environment = production
runinterval = 30m
Первый запуск создаёт запрос на сертификат. На сервере подпишите нужный узел и повторите запуск. Не включайте автоподпись в сети с посторонними устройствами.
sudo /opt/puppetlabs/bin/puppet agent -t
sudo /opt/puppetlabs/bin/puppetserver ca list --all
sudo /opt/puppetlabs/bin/puppetserver ca sign --certname web01.example.lan
sudo systemctl enable --now puppet
Первый манифест: пакет, файл и служба
Начните с профиля, который ставит nginx, кладёт конфигурацию из шаблона и держит службу запущенной. Ключевая деталь — notify: изменение файла перезапускает службу только при реальном изменении содержимого. Шаблон EPP получает переменные явно.
class profile::nginx {
package { 'nginx':
ensure => installed,
}
file { '/etc/nginx/conf.d/site.conf':
ensure => file,
owner => 'root',
group => 'root',
mode => '0644',
content => epp('profile/nginx-site.epp', {
'server_name' => $facts['networking']['fqdn'],
}),
notify => Service['nginx'],
}
service { 'nginx':
ensure => running,
enable => true,
}
}
Проверка синтаксиса и пробный прогон обязательны. puppet apply --noop показывает будущие изменения, не трогая систему; на агенте используйте puppet agent -t --noop.
sudo /opt/puppetlabs/bin/puppet parser validate manifests/site.pp
sudo /opt/puppetlabs/bin/puppet epp validate templates/profile/nginx-site.epp
sudo /opt/puppetlabs/bin/puppet agent -t --noop
sudo /opt/puppetlabs/bin/puppet agent -t
Роли и профили вместо свалки в site.pp
Паттерн roles and profiles разделяет ответственность. Профиль описывает одну технологию, роль собирает профили для типа сервера, а узел в site.pp получает только роль. Это упрощает повторное использование и борьбу с копипастой.
class role::web {
include profile::base
include profile::nginx
include profile::php
}
node 'web01.example.lan' {
include role::web
}
Модули храните в отдельном репозитории с metadata.json. Для доставки окружений подойдёт r10k: он читает Puppetfile, скачивает модули из git и раскладывает по environments. Команда r10k deploy environment -p обновляет их перед запуском агента.
mod 'puppetlabs/stdlib', '9.6.0'
mod 'puppetlabs/nginx', '8.0.0'
mod 'our/profile', git: 'https://git.example.lan/puppet/profile.git'
sudo r10k deploy environment -p
Версии модулей фиксируйте: ветка main однажды принесёт несовместимое изменение. Собственные модули фиксируйте тегом или коммитом, обновляйте через отдельное окружение.
Hiera: данные отдельно от логики
Параметры, которые различаются между средами и узлами, выносите в Hiera 5. Иерархия включает общие данные, данные окружения и узла; приоритет идёт сверху вниз. Секреты не храните в git — используйте eyaml или внешнее хранилище.
version: 5
defaults:
datadir: data
data_hash: yaml_data
hierarchy:
- name: "Per-node data"
path: "nodes/%{facts.networking.hostname}.yaml"
- name: "Common data"
path: "common.yaml"
profile::base::admin_users:
- ops
- deploy
profile::nginx::worker_processes: 4
В манифесте значение читается функцией lookup с типом и значением по умолчанию: каталог не упадёт, если данных ещё нет.
$workers = lookup('profile::nginx::worker_processes', Integer, 'first', 2)
file { '/etc/nginx/nginx.conf':
ensure => file,
content => template('profile/nginx.conf.erb'),
notify => Service['nginx'],
}
Диагностика типичных сбоев
Большинство проблем связано с сертификатами, путями и порядком применения. Начните с конфигурации агента и журнала сервера, затем повторите запуск с отладкой.
- Агент не видит сервер: проверьте
puppet config print server, DNS иss -ltnp | grep 8140. - Ошибка проверки сертификата: чаще всего рассинхронизировано время; сверьте
timedatectlи перевыпустите сертификат. - Класс не найден: модуль отсутствует в
modulepathили повреждёнmetadata.json. - Файл обновился, служба не перезапустилась: нет
notifyлибо службой управляет другой ресурс. - Каталог не компилируется: смотрите
journalctl -u puppetserverи запускайте агент с--debug. - Запуск слишком долгий: ищите
execбезunlessиonlyif, а также лишние ресурсы.
sudo /opt/puppetlabs/bin/puppet config print server certname modulepath
sudo /opt/puppetlabs/bin/puppet agent -t --debug --verbose
sudo journalctl -u puppetserver -n 100 --no-pager
sudo /opt/puppetlabs/bin/puppetserver ca list --all
Чек-лист перед production
- Время синхронизировано на сервере и агентах, порт 8140 доступен только из доверенных сетей.
- CA и закрытые ключи лежат вне git, доступ к ним ограничен.
- Все модули зафиксированы по версиям, обновление проходит через отдельное окружение.
- Секреты вынесены в eyaml или внешнее хранилище, а не в common.yaml.
- Есть резервная копия
/etc/puppetlabsи план восстановления сервера.
Итог
Puppet оправдывает себя там, где важны повторяемость и контроль парка серверов. Начните с одного профиля и честного --noop, затем добавьте роли, Hiera и фиксированные версии модулей. Так вы сначала видите, что изменится, и только потом разрешаете применение. Главное — не превращать site.pp в свалку и хранить данные отдельно от логики.