Puppet-сервер – 192.168.1.42-puppet-server.kamaok.org.ua — Centos7
Puppet-клиент — 192.168.1.43-puppet-client.kamaok.org.ua — Centos7
Настройка временной зоны и времени на сервере и на клиенте
1 |
# timedatectl set-timezone Europe/Kiev |
1 |
# yum install ntpdate |
1 |
# ntpdate 0.ua.pool.ntp.org |
1 |
# yum install ntp |
1 |
# systemctl enable ntpd |
Установка имени хоста
На сервере
1 |
# nano /etc/hosts |
1 2 |
127.0.0.1 localhost puppet-server 192.168.1.42 puppet-server.kamaok.org.ua puppet-server |
1 |
# hostname puppet-server.kamaok.org.ua |
На клиенте
1 |
# nano /etc/hosts |
1 2 3 |
127.0.0.1 localhost puppet-client 192.168.1.43 puppet-client.kamaok.org.ua puppet-client 192.168.1.42 puppet-server.kamaok.org.ua puppet-server |
1 |
# hostname puppet-client.kamaok.org.ua |
Установка Puppet-сервера
Установка Puppet-репозитария
1 |
# rpm -ihv http://yum.puppetlabs.com/puppetlabs-release-el-7.noarch.rpm |
1 |
# yum repolist enabled | grep puppet |
1 2 |
puppetlabs-deps/x86_64 Puppet Labs Dependencies El 7 - x86_64 17 puppetlabs-products/x86_64 Puppet Labs Products El 7 - x86_64 225 |
1 |
# yum install puppet-server |
1 |
# puppet --version |
1 |
3.8.7 |
1 |
# rpm -qa | grep puppet |
1 2 3 |
puppetlabs-release-22.0-2.noarch puppet-server-3.8.7-1.el7.noarch puppet-3.8.7-1.el7.noarch |
Установка Puppet-клиента
1 |
# rpm -ihv http://yum.puppetlabs.com/puppetlabs-release-el-7.noarch.rpm |
1 |
# yum install puppet |
1 |
# puppet --version |
1 |
3.8.7 |
1 |
# rpm -qa | grep puppet |
1 2 |
puppet-3.8.7-1.el7.noarch puppetlabs-release-22.0-2.noarch |
Просмотр списка файлов,установленных пакетом puppet-server на сервере
1 |
# rpm -ql puppet-server | less |
Просмотр списка файлов,установленных пакетом puppet на клиенте
1 |
# rpm -ql puppet | less |
Запуск Puppet-сервера, добавление его в авто загрузку и проверка его состояния
1 |
# systemctl start puppetmaster |
1 |
# systemctl enable puppetmaster |
1 |
# systemctl status puppetmaster |
1 2 3 4 5 6 |
● puppetmaster.service - Puppet master Loaded: loaded (/usr/lib/systemd/system/puppetmaster.service; disabled; vendor preset: disabled) Active: active (running) since Sun 2016-12-11 23:04:32 EET; 4s ago Main PID: 616 (puppet) CGroup: /user.slice/user-0.slice/session-1.scope/system.slice/puppetmaster.service └─616 /usr/bin/ruby /usr/bin/puppet master --no-daemonize |
Запустить и добавить в автозагрузку Puppet-сервер также можно с помощью команды
1 |
# puppet resource service puppetmaster ensure=running enable=true |
1 |
# netstat -nlpt | grep ruby |
1 |
tcp 0 0 0.0.0.0:8140 0.0.0.0:* LISTEN 616/ruby |
1 |
# ps ax | grep [p]uppet |
1 |
616 ? Ssl 0:04 /usr/bin/ruby /usr/bin/puppet master --no-daemoniz |
1 |
# ls -l /etc/puppet/ |
1 2 3 4 5 6 7 |
total 28 -rw-r--r-- 1 root root 4178 Apr 25 2016 auth.conf drwxr-xr-x 3 root root 4096 Dec 11 22:44 environments -rw-r--r-- 1 root root 1462 Apr 25 2016 fileserver.conf drwxr-xr-x 2 root root 4096 Apr 25 2016 manifests drwxr-xr-x 2 root root 4096 Apr 25 2016 modules -rw-r--r-- 1 root root 853 Apr 25 2016 puppet.conf |
Файлы и клиента и сервера хранятся в каталоге /etc/puppet/
Основной конфигурационный файл
/etc/puppet/puppet.conf
Файл разделяется на секции
1 2 3 |
[main] - общий для всех команд [agent] – для клиента(Puppet agent) [server] – для сервера (Puppet server) |
Символ # -используется для комментариев
Важные опции в настройках
1 2 3 |
[main] vardir – расположение динамической информации ssldir – расположение ssl-сертификатов |
1 2 3 4 5 |
[agent] server – имя Puppet-сервера(мастера)(по умолчанию puppet) certname – имя сертификата используемое клиентом (по умолчанию FQDN – fully qualified domain name) runinterval – интервал запуска ( в секундах) клиента(агента) для получения конфигурации с мастера. report – отправлять ли отчеты о выполнении на сервер отчетов(на мастер сервер)(по умолчанию - да) |
1 2 3 |
[master] autosign – включено ли автоподписывание сертификатов новых клиентов (по умолч. false) reports – как управлять отчетами клиентов (по умолч. Сохранять) |
Полный список настроек
https://docs.puppet.com/puppet/latest/configuration.html
Файлы fileserver.conf и auth.conf используются для настройки файлового сервера и аутентификации
Каталог manifests содержит в себе “манифесты”, которые являются файлами настройки для клиентов. Основной из них – файл site.pp, который будет считываться мастером всегда, и его настройки будут применяться ко всем клиентам (если другое не указано в самом манифесте)
Puppet использует собственный язык описания конечного состояния операционной системы, с помощью которого указывается то, к какому виду должны быть приведены компоненты ОС, чтобы она достигла желаемого состояния.
Применительно,как для сервера,так и для клиента:
Посмотреть все текущие настройки
1 |
# puppet apply --configprint all |
Посмотреть текущие настройки для отдельного параметра
1 |
# puppet master --configprint <имя_параметра> |
Например
1 |
# puppet master --configprint config |
1 |
/etc/puppet/puppet.conf |
1 |
# puppet apply --configprint puppetdlog |
1 |
/var/log/puppet/puppetd.log |
Переменные — один из неотъемлемых компонентов любого языка программирования, и в языке Puppet они тоже есть. Переменные начинаются со знака $ и могут содержать любое число, строку или булево значение (true, false)
Одним из мощнейших свойств языка Puppet, связанным с переменными, является интеграция с инструментом получения информации о машине facter. Эта утилита возвращает всю информацию, специфичную для машины, в виде пар «ключ-значение», которые в Puppet превращаются в одноименные ВСТРОЕННЫЕ переменные. Вкупе с условными инструкциями языка Puppet они могут быть использованы для альтерации атрибутов ресурса в зависимости от свойств машины.
Если набрать в командной строке facter, то можно получить полный список доступных переменных
Проверка корректности настройки имени сервера и клиента для Puppet с помощью facter
На сервере
1 |
# facter | grep hostname |
1 |
hostname => puppet-server |
1 |
# facter | grep fqdn |
1 |
fqdn => puppet-server.kamaok.org.ua |
На клиенте
1 |
# facter | grep hostname |
1 |
hostname => puppet-client |
1 |
# facter | grep fqdn |
1 |
fqdn => puppet-client.kamaok.org.ua |
Проверка доступных на подпись/подписанных/отозванных сертификатов
1 |
# puppet cert list --all |
1 |
+ "puppet-server.kamaok.org.ua" (SHA256) 2C:B1:0E:1E:64:22:BA:E1:DE:BF:F0:9D:22:32:AC:C0:71:96:B8:48:D3:F6:13:CA:54:A2:AF:0D:0F:38:5C:FD (alt names: "DNS:puppet", "DNS:puppet-server.kamaok.org.ua", "DNS:puppet.kamaok.org.ua") |
Настройка клиента
Добавляем имя Puppet-сервера
1 |
# nano /etc/puppet/puppet.conf |
1 2 3 4 |
……… [agent] ……… server = puppet-server.kamaok.org.ua |
1 |
# systemctl start puppet |
1 |
# systemctl enabled puppet |
1 |
# systemctl status puppet |
1 2 3 4 5 6 |
● puppet.service - Puppet agent Loaded: loaded (/usr/lib/systemd/system/puppet.service; disabled; vendor preset: disabled) Active: active (running) since Sun 2016-12-11 23:46:04 EET; 27s ago Main PID: 941 (puppet) CGroup: /user.slice/user-0.slice/session-1.scope/system.slice/puppet.service └─941 /usr/bin/ruby /usr/bin/puppet agent --no-daemonize |
1 |
# ps ax | grep [p]uppet |
1 |
941 ? Ssl 0:01 /usr/bin/ruby /usr/bin/puppet agent --no-daemonize |
Запустить и добавить в автозагрузку Puppet-клиент также можно с помощью команды
1 |
# puppet resource service puppet ensure=running enable=true |
После запуска клиента на puppet-сервере должен появиться клиентский сертификат с ожиданием на подпись
1 |
# puppet cert list --all |
1 2 |
"puppet-client.kamaok.org.ua" (SHA256) 57:43:A8:D2:9F:E9:9A:6C:ED:C9:65:2A:5E:D8:15:44:38:67:BA:FB:FF:A9:1A:5B:2B:35:1A:97:2E:B5:B4:12 + "puppet-server.kamaok.org.ua" (SHA256) 2C:B1:0E:1E:64:22:BA:E1:DE:BF:F0:9D:22:32:AC:C0:71:96:B8:48:D3:F6:13:CA:54:A2:AF:0D:0F:38:5C:FD (alt names: "DNS:puppet", "DNS:puppet-server.kamaok.org.ua", "DNS:puppet.kamaok.org.ua") |
Подпишим сертификат клиента(puppet-client.kamaok.org.ua)
1 |
# puppet cert sign puppet-client.kamaok.org.ua |
1 2 |
Notice: Signed certificate request for puppet-client.kamaok.org.ua Notice: Removing file Puppet::SSL::CertificateRequest puppet-client.kamaok.org.ua at '/var/lib/puppet/ssl/ca/requests/puppet-client.kamaok.org.ua.pem' |
1 2 3 |
# puppet cert list --all + "puppet-client.kamaok.org.ua" (SHA256) C4:0B:2F:3B:C2:DE:A1:36:F5:CC:99:2F:8A:ED:52:28:94:91:1A:F4:98:13:94:C6:F1:50:BD:A4:7B:C7:3B:96 + "puppet-server.kamaok.org.ua" (SHA256) 2C:B1:0E:1E:64:22:BA:E1:DE:BF:F0:9D:22:32:AC:C0:71:96:B8:48:D3:F6:13:CA:54:A2:AF:0D:0F:38:5C:FD (alt names: "DNS:puppet", "DNS:puppet-server.kamaok.org.ua", "DNS:puppet.kamaok.org.ua") |
Если необходимо удалить клиентский сертификат
1 |
# puppet cert clean <certname> |
Сервер сохраняет клиентские публичные сертификаты в $vardir/ssl/ca/
1 |
# puppet master --configprint all | grep vardir |
1 |
vardir = /var/lib/puppet |
Клиент сохраняет свои сертификаты и публичный сертификат сервера в $vardir/ssl/
1 |
# puppet master --configprint all | grep vardir |
1 |
vardir = /var/lib/puppet |
Если есть проблемы с сертификатами, то необходимо
— Очистить на клиенте клиентский сертификат
На клиенте выполняем
1 |
# mv /var/lib/puppet/ssl /var/lib/puppet/ssl.old |
— Очистить на мастере старый клиентский сертификат
1 |
# puppet cert clean <certname> |
Если необходимо включить автоподписывание сертификатов клиентов
На сервере добавляем
1 |
# nano /etc/puppet/puppet.conf |
1 2 |
[master] autosign = true |
Если необходимо отключить синхронизацию плагинов
На клиенте добавляем в секцию master
1 |
# nano /etc/puppet/puppet.conf |
1 2 |
[master] pluginsync = false |
Puppet agent получает конфигурацию клиента от Puppet-сервера и применяет ее к локальному хосту,на котором он запущен.
Клиент может быть запущен как
1.Служба
2.Запускаться периодически по крону
3. Запускаться вручную
При запуске Puppet-агента по умолчанию запрашиваются изменения у сервера каждые 30 минут (1800 секунд)
1 |
# puppet apply --configprint all | grep runinterval |
1 |
runinterval = 1800 |
Для изменения частоты запросов изменений с сервера на клиенте
можно изменить значение параметра runinterval в секции [agent]
1 |
# nano /etc/puppet/puppet.conf |
1 2 3 |
[agent] …… runinterval = 300 |
1 |
# systemctl restart puppet |
Также можно вручную перезапустить клиента:
1 |
# systemctl restart puppet |
Или вручную опросить мастер с помощью команды
1 |
# puppet agent --test |
1 2 3 4 5 |
Info: Retrieving pluginfacts Info: Retrieving plugin Info: Caching catalog for puppet-client.kamaok.org.ua Info: Applying configuration version '1481494540' Notice: Finished catalog run in 0.02 seconds |
Анатомия Puppet запуска –Часть 1 – Компиляция catalog
Execute Puppet on the client
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
Client shell # puppet agent -t If pluginsync = true (default from Puppet 3.0) the client retrieves all extra plugins (facts, types and providers) present in modules on the server's $modulepath Client output # Info: Retrieving plugin The client runs facter and send its facts to the server Client output # Info: Loading facts in /var/lib/puppet/lib/facter/... [...] The server looks for the client's hostname (or certname, if different from the hostname) and looks into its nodes list The server compiles the catalog for the client using also client's facts Server's logs # Compiled catalog for in environment production in 3.22 seconds If there are not syntax errors in the processed Puppet code, the server sends the catalog to the client, in PSON format. |
Анатомия Puppet запуска –Часть 2 – Применение catalog
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
Client output # Info: Caching catalog for The client receives the catalog and starts to apply it locally If there are dependency loops the catalog can't be applied and the whole tun fails. Client output # Info: Applying configuration version '1481494540' All changes to the system are shown here. If there are errors (in red or pink, according to Puppet versions) they are relevant to specific resources but do not block the application of the other resources (unless they depend on the failed ones). At the end ot the Puppet run the client sends to the server a report of what has been changed Client output # Finished catalog run in 0.02 seconds The server eventually sends the report to a Report Collector |
При этом в лог-файле на Puppet-сервере регистрируются сообщения о подключении клиента к серверу
1 |
# tail -f /var/log/puppet/masterhttp.log |
Как уже упоминалось, каталог manifests содержит в себе “манифесты”, которые являются файлами настройки для клиентов. Основной из них – файл site.pp, который будет считываться мастером всегда, и его настройки будут применяться ко всем клиентам (если другое не указано в самом манифесте)
Основной схемой для управления большим количеством конфигураций для разных клиентов является описание каждого из них в нодах (nodes).
С их помощью администратор может описать то, к каким машинам должны быть применены те или иные ресурсы и классы. Другими словами, это способ указать индивидуальную конфигурацию для каждой из машин, участвующих в сети Puppet
Содержимое ноды default будет применяться ко всем клиентам, описания для которых не было найдено
Помимо default в имени узла можно указывать сетевое имя машины (тогда все описанные в узле ресурсы будут сконфигурированы только на этой машине), либо произвольное имя (тогда этот узел может быть унаследован другим узлом).
Каждый блок, включающий в себя описание файлов, или действий, или программы, которую необходимо установить, в терминологии Puppet называется ресурсом
Ресурс идентифицируется именем (title), которое записывается в одиночных кавычках после открывающей фигурной скобки и сопровождается символом двоеточия. Далее с новой строки определяются атрибуты типа (attributes), причём некоторые атрибуты являются общими для всех типов, другие же присущи только данному конкретному типу ресурса. Каждый атрибут имеет значение (value), таким образом, записи атрибутов с соответствующими значениями имеют общую форму attribute => value.
Каждая строка определения атрибута заканчивается запятой, а закрывающая фигурная скобка сообщает о том, что описание ресурса завершено.
Описание всех существующих типов ресурсов
https://docs.puppet.com/puppet/latest/type.html
Например описание ресурса типа файл:
1 2 3 4 5 |
file { "/root/test.txt": owner => "root", group => "root", mode => 644, } |
Описание ресурса – сервиса sshd (установка,запуск,проверка)
1 2 3 4 5 6 7 8 9 |
package { 'openssh-server': ensure => installed, } service { 'sshd': enable => true, ensure => running, require => Package['openssh-server'], } |
Создание первого манифеста — файла site.pp с таким содержимым:
1 |
# nano /etc/puppet/manifests/site.pp |
1 2 3 4 5 6 7 |
node default { file { "/root/test.txt": owner => "root", group => "root", mode => 644, } } |
Каждый тип ресурсов обладает собственным набором доступных для модификации атрибутов, плюс есть специальные мета-атрибуты, которые можно использовать в любом ресурсе. Одним из важных качеств ресурсов является возможность ссылки на них. Это можно использовать для формирования цепочек зависимостей
Ресурсы могут быть сгруппированы в коллекции ресурсов, называемые классами.
Классы могут наследовать друг друга и переопределять атрибуты.
Также классы, в свою очередь, могут входить в состав модулей
Просмотр всех доступных ресурсов
1 |
# puppet resource --types |
Краткое описание всех типов ресурсов
1 |
# puppet describe --list |
Полное описание определенного типа ресурса
1 |
# puppet describe <type_of_resource> |
Например, ресурса типа файл
1 |
# puppet describe file |
Просмотр значения атрибутов существующего ресурса
1 |
# puppet resource <type> [name] |
Например, ресурса service с именем puppetmaster
1 |
# puppet resource service puppetmaster |
1 2 3 4 |
service { 'puppetmaster': ensure => 'running', enable => 'true', } |
Изменение атрибутов ресурса
1 |
# puppet resource <type> <name> [attribute=value] [attribute2=value2] |
Например, запуск службы puppetmaster и добавление ее автозапуск
1 |
# puppet resource service puppetmaster ensure=running enable=true |
Создадим на сервере и на клиенте файл с отличными от указанных в манифесте(специальный файл конфигурирования ресурсов) владельцем/группой и правами
Например
1 |
# touch /root/test.txt && chown root:bin /root/test.txt && chmod 400 /root/test.txt |
На Puppet-сервере применим конфигурацию – выполним манифест
1 |
# puppet apply /etc/puppet/manifests/site.pp |
1 2 3 4 |
Notice: Compiled catalog for puppet-server.kamaok.org.ua in environment production in 0.14 seconds Notice: /Stage[main]/Main/Node[default]/File[/root/test.txt]/group: group changed 'bin' to 'root' Notice: /Stage[main]/Main/Node[default]/File[/root/test.txt]/mode: mode changed '0400' to '0644' Notice: Finished catalog run in 0.03 seconds |
Проверяем,что владелец/группа/права совпадают с теми,что указаны в манифесте
1 |
# ls -l /root/ | grep test.txt |
1 |
-rw-r--r-- 1 root root 0 Dec 26 23:05 test.txt |
Применяем манифест для клиента
1 |
# puppet agent --test |
1 2 3 4 5 6 7 |
Info: Retrieving pluginfacts Info: Retrieving plugin Info: Caching catalog for puppet-client.kamaok.org.ua Info: Applying configuration version '1482786125' Notice: /Stage[main]/Main/Node[default]/File[/root/test.txt]/group: group changed 'bin' to 'root' Notice: /Stage[main]/Main/Node[default]/File[/root/test.txt]/mode: mode changed '0400' to '0644' Notice: Finished catalog run in 0.02 seconds |
1 |
# ls -l /root/ | grep test |
1 |
-rw-r--r-- 1 root root 0 Dec 26 23:06 test.txt |
При этом изменим права для на файл /root/test.txt для всех нод, описания которых не найдено и изменим владельца/группу на файл /root/test.txt для нашего клиента(ноды puppet-client)
1 |
# nano /etc/puppet/manifests/site.pp |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
node default { file { "/root/test.txt": owner => "root", group => "root", mode => 777, } } node puppet-client.kamaok.org.ua { file { "/root/test.txt": owner => "bin", group => "bin", mode => 644, } } |
Применяем манифест для сервера
1 |
# puppet apply /etc/puppet/manifests/site.pp |
1 2 3 |
Notice: Compiled catalog for puppet-server.kamaok.org.ua in environment production in 0.14 seconds Notice: /Stage[main]/Main/Node[default]/File[/root/test.txt]/mode: mode changed '0644' to '0777' Notice: Finished catalog run in 0.04 seconds |
1 |
# ls -l /root/ | grep test.txt |
1 |
-rwxrwxrwx 1 root root 0 Dec 26 23:05 test.txt |
Применяем манифест для клиента
1 |
# puppet agent --test |
1 2 3 4 5 6 7 |
Info: Retrieving pluginfacts Info: Retrieving plugin Info: Caching catalog for puppet-client.kamaok.org.ua Info: Applying configuration version '1482787422' Notice: /Stage[main]/Main/Node[puppet-client]/File[/root/test.txt]/owner: owner changed 'root' to 'bin' Notice: /Stage[main]/Main/Node[puppet-client]/File[/root/test.txt]/group: group changed 'root' to 'bin' Notice: Finished catalog run in 0.02 seconds |
1 |
# ls -l /root/ | grep test.txt |
1 |
-rw-r--r-- 1 bin bin 0 Dec 26 23:04 test.txt |
Создадим Puppet-модуль с именем accounts для создания привилегированного пользователя и отключения удаленного входа root-пользователя по SSH
Важно: имя каталога внутри /etc/puppet/modules должно быть таким же,к ак и имя модуля
Создаем необходимую структуру каталогов
1 |
# mkdir -p /etc/puppet/modules/accounts/{examples,files,manifests,templates} |
Назначение каталогов
1 2 3 4 |
example – позволяет тестировать модули локально files – содержит статические файлы, которые могут быть добавлены или отредактированы на клиенты manifest – содержит Puppet-код, с описанием самого модуля templates – содержит используемые шаблоны |
Переходим в каталог manifest и создаем первый класс с именем accounts (имя класса должно совпадать с именем модуля) в файле init.pp
Файл init.pp – является главным файлом, определяющим модуль.
Он содержит описание класса, с таким же именем(accounts),как и имя модуля(accounts)
1 |
# cd /etc/puppet/modules/accounts/manifests/ |
1 |
# nano /etc/puppet/modules/accounts/manifests/init.pp |
1 2 3 4 5 6 7 8 9 10 11 |
class accounts { user { 'myuser': ensure => present, home => '/home/myuser', shell => '/bin/bash', managehome => true, gid => 'myuser ', } } |
1 2 3 4 5 6 |
Имя пользователя - myuser ensure – проверить/убедиться, что такой пользователь существует home – домашний каталог пользователя shell – тип оболочки пользователя managehome - домашний каталог должен быть создан gid – первичная группа для пользователя |
Один модуль может содержать несколько классов.
Для того, что бы определить дополнительные классы – их необходимо перечислить в отдельных файлах в каталоге/etc/puppet/modules/имя_модуля/manifests
Создаем новый класс groups для создания группы пользователя (имя группы myuser)
В имени класса обязательно указывается имя модуля(accounts),который содержит этот класс
1 |
# nano /etc/puppet/modules/accounts/manifests/groups.pp |
1 2 3 4 5 6 7 |
class accounts::groups { group { 'myuser': ensure => present, } } |
Подключаем класс groups с созданием группы в основной класс модуля
1 |
# nano /etc/puppet/modules/accounts/manifests/init.pp |
1 2 3 4 |
class accounts { include groups … |
Добавляем пользователя в sudo группу при этом имя группы будет выбрано в зависимости от используемого дистрибутива
1 |
# nano /etc/puppet/modules/accounts/manifests/init.pp |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
class accounts { include groups $rootgroup = $osfamily ? { 'Debian' => 'sudo', 'RedHat' => 'wheel', default => warning('This distribution is not supported by the Accounts module'), } user { 'myuser ': ensure => present, home => '/home/myuser ', shell => '/bin/bash', managehome => true, gid => 'myuser ', groups => "$rootgroup", } } |
Задаем пароль пользователя и получаем SHA1-хеш пароля
Хешированный пароль должен быть заключен в одинарные кавычки и помещен в основной манифест init.pp
1 |
# openssl passwd -1 |
1 2 3 |
Password: Verifying - Password: $1$st9dVwlY$Mg6WDHhIL9z.WwzEcPsFH. |
1 |
# nano /etc/puppet/modules/accounts/manifests/init.pp |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
class accounts { include groups $rootgroup = $osfamily ? { 'Debian' => 'sudo', 'RedHat' => 'wheel', default => warning('This distribution is not supported by the Accounts module'), } user { 'myuser ': ensure => present, home => '/home/myuser ', shell => '/bin/bash', managehome => true, gid => 'myuser ', groups => "$rootgroup", password => '$1$st8dVwlY$Mg7WDHhIL9z.WwzEcPsFH.', } } |
Проверка синтаксиса кода манифеста
1 |
# puppet parser validate /etc/puppet/modules/accounts/manifests/init.pp |
Если в выводе команды ничего нет, то синтаксис корректен.
Перейдем в каталог examples и создадим init.pp файл с вызовом нашего созданного модуля accounts
1 |
# nano /etc/puppet/modules/accounts/examples/init.pp |
1 |
include accounts |
Тестируем модуль без применения изменений(—noop параметр предотвращает выполнение Puppet-ом фактического запуска модуля т.н. выполнение на сухую )
1 |
# puppet apply --noop /etc/puppet/modules/accounts/examples/init.pp |
1 2 3 4 5 6 7 |
Notice: Compiled catalog for puppet-server.kamaok.org.ua in environment production in 0.32 seconds Notice: /Stage[main]/Accounts::Groups/Group[myuser]/ensure: current_value absent, should be present (noop) Notice: /Stage[main]/Accounts/User[myuser]/ensure: current_value absent, should be present (noop) Notice: Class[Accounts]: Would have triggered 'refresh' from 1 events Notice: Class[Accounts::Groups]: Would have triggered 'refresh' from 1 events Notice: Stage[main]: Would have triggered 'refresh' from 2 events Notice: Finished catalog run in 0.04 seconds |
Добавим выполнения модуля accounts для Puppet-клиента (сервера puppet-client)
1 |
# nano /etc/puppet/manifests/site.pp |
1 2 3 |
node puppet-client { include accounts } |
С клиента проверим выполнение манифеста
1 |
# puppet agent --test |
1 2 3 4 5 6 7 |
Info: Retrieving pluginfacts Info: Retrieving plugin Info: Caching catalog for puppet-client.kamaok.org.ua Info: Applying configuration version '1482790779' Notice: /Stage[main]/Accounts::Groups/Group[myuser]/ensure: created Notice: /Stage[main]/Accounts/User[myuser]/ensure: created Notice: Finished catalog run in 0.27 seconds |
Проверяем на клиенте наличие пользователя и группы myuser, наличие его в группе wheel, домашний каталог пользователя, наличие заданного пароля.
1 |
# grep myuser /etc/passwd /etc/group |
1 2 3 |
/etc/passwd:myuser:x:1001:1001::/home/myuser:/bin/bash /etc/group:wheel:x:10:username,myuser /etc/group:myuser:x:1001: |
1 |
# ls -al /home/myuser/ |
1 2 3 4 5 6 |
total 20 drwx------ 2 myuser myuser 4096 Dec 27 00:19 . drwxr-xr-x 4 root root 4096 Dec 27 00:19 .. -rw-r--r-- 1 myuser myuser 18 Aug 2 19:00 .bash_logout -rw-r--r-- 1 myuser myuser 193 Aug 2 19:00 .bash_profile -rw-r--r-- 1 myuser myuser 231 Aug 2 19:00 .bashrc |
1 |
# grep myuser /etc/shadow |
1 |
myuser:$1$st8dVwlY$Mg7WDHhIL9z.WwzEcPsFH.:17161:0:99999:7::: |
Отключение удаленного входа root-пользователя по SSH
Копируем конф.файл SSH-сервера в каталог files модуля accounts и редактируем его, запрещая подключение по SSH пользователя root
1 |
# cp /etc/ssh/sshd_config /etc/puppet/modules/accounts/files/ |
1 |
# nano /etc/puppet/modules/accounts/files/sshd_config |
1 |
PermitRootLogin no |
Создаем новый класс ssh.pp
Параметр file заменяет дефолтный файл на сервере файлом, указанным в параметре source
(каталог files в параметре source опускается т.к. каталог files является дефолтным размещением файлов)
1 |
# nano /etc/puppet/modules/accounts/manifests/ssh.pp |
1 2 3 4 5 6 7 8 |
class accounts::ssh { file { '/etc/ssh/sshd_config': ensure => present, source => 'puppet:///modules/accounts/sshd_config', } } |
Перезапускаем SSH-службу в зависимости от дистрибутива операционной системы
1 |
# nano /etc/puppet/modules/accounts/manifests/ssh.pp |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
class accounts::ssh { $sshname = $osfamily ? { 'Debian' => 'ssh', 'RedHat' => 'sshd', default => warning('This distribution is not supported by the Accounts module'), } file { '/etc/ssh/sshd_config': ensure => present, source => 'puppet:///modules/accounts/sshd_config', notify => Service["$sshname"], } service { "$sshname": hasrestart => true, } } |
Подключаем класс ssh в файл init.pp
1 |
# nano /etc/puppet/modules/accounts/manifests/init.pp |
1 2 3 4 5 |
class accounts { include groups include ssh …… |
Проверяем синтаксис манифеста с ssh
1 |
# puppet parser validate /etc/puppet/modules/accounts/manifests/ssh.pp |
Запрашиваем с клиента выполение манифеста
1 |
# puppet agent --test |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
Info: Retrieving pluginfacts Info: Retrieving plugin Info: Caching catalog for puppet-client.kamaok.org.ua Info: Applying configuration version '1482791773' Notice: /Stage[main]/Accounts::Ssh/File[/etc/ssh/sshd_config]/content: --- /etc/ssh/sshd_config 2016-03-22 00:18:45.000000000 +0200 +++ /tmp/puppet-file20161227-1779-xvpsv3 2016-12-27 00:37:32.350950544 +0200 @@ -46,7 +46,7 @@ # Authentication: #LoginGraceTime 2m -#PermitRootLogin yes +PermitRootLogin no #StrictModes yes #MaxAuthTries 6 #MaxSessions 10 Info: Computing checksum on file /etc/ssh/sshd_config Info: /Stage[main]/Accounts::Ssh/File[/etc/ssh/sshd_config]: Filebucketed /etc/ssh/sshd_config to puppet with sum 0440a9608de01c4fa1c1dd6301b568ec Notice: /Stage[main]/Accounts::Ssh/File[/etc/ssh/sshd_config]/content: content changed '{md5}0440a9608de01c4fa1c1dd6301b568ec' to '{md5}4ffaa0befebc4ea61f5353b0a21cd7c7' Info: /Stage[main]/Accounts::Ssh/File[/etc/ssh/sshd_config]: Scheduling refresh of Service[sshd] Info: /Stage[main]/Accounts::Ssh/File[/etc/ssh/sshd_config]: Scheduling refresh of Service[sshd] Notice: /Stage[main]/Accounts::Ssh/Service[sshd]: Triggered 'refresh' from 2 events Notice: Finished catalog run in 0.28 seconds |
Проверяем наличие изменений на клиенте
1 |
# grep 'PermitRootLogin' /etc/ssh/sshd_config |
1 |
PermitRootLogin no |
Проверяем принцип идемпотентности
Puppet выполнил снова тот же манифест, при этом никаких изменений сделано не было т.к. все настройки на клиенте совпадают с теми, что указаны в манифесте
1 |
# puppet agent --test |
1 2 3 4 5 |
Info: Retrieving pluginfacts Info: Retrieving plugin Info: Caching catalog for puppet-client.kamaok.org.ua Info: Applying configuration version '1482793170' Notice: Finished catalog run in 0.05 seconds |
Полезные команды Puppet-агента
Все конфигурационные параметры в файле /etc/puppet/puppet.conf могут быть переопределены с помощью опций командной строки
1 |
# puppet agent --test |
— включение одновременно нескольких опций (verbose-подробного вывода,onetime-запуск конфигурации только один раз, no-daemonize – не запускать в фоне и т.д.)
1 |
# puppet agent --tags <name_tags> |
— выполнение определенной части конфигурации, а не всей конфигурации
Например, выполнение только класса с именем ssh
1 |
# puppet agent --tags ssh -t |
Проверка fingerprint сертификата
1 |
# puppet agent --fingerprint |
Проверяем fingerprint сертификата на клиенте
1 |
# puppet agent --fingerprint |
1 |
(SHA256) C4:0B:2F:3B:C2:DE:A1:36:F5:CC:99:2F:8A:ED:52:28:94:91:1A:F4:98:13:94:C6:F1:50:BD:A4:7B:C7:3B:96 |
Проверяем fingerprint сертификата клиента на Puppet-мастере(сервере)
1 |
# puppet cert list --all | grep puppet-client.kamaok.org.ua |
1 |
+ "puppet-client.kamaok.org.ua" (SHA256) C4:0B:2F:3B:C2:DE:A1:36:F5:CC:99:2F:8A:ED:52:28:94:91:1A:F4:98:13:94:C6:F1:50:BD:A4:7B:C7:3B:96 |
Вывод максимальной информации при выполнении конфигурации на клиенте
1 |
# puppet agent -t --debug |
# Выполнение конфигурации без записи изменений на диск(выполнение на сухую)
1 |
# puppet agent -t --noop |
Выполнение конфигурации в окружении, отличном от дефолтного
1 |
# puppet agent --test --environment testing |
Ожидать подписи мастером сертификата клиента ( полезно при первом запуске клиента и отключенной опции автоподписывания сертификатов на мастере)
1 |
# puppet agent --test --waitforcert 120 |
Полезные пути Puppet сервера-клиента
1 |
/var/log/puppet |
– содержание лог-файлов
1 |
/vat/lib/puppet |
– содержит данные, с которыми рабоатет Puppet (catalog, сертификаты, бекапы файлов и т.д.)
1 |
/vat/lib/puppet/ssl |
– расположение SSL-сертифкатов
1 |
/etc/puppet/manifests/site.pp |
(на мастере) – Основной(первый) манифест,который мастер выполняет при подключении клиента
1 |
/etc/puppet/environments/production/manifests/site.pp |
( на мастере) – аналогично вышеуказанному, но при использовании конкретного окружения
1 |
/etc/puppet/modules/ и /usr/share/puppet/modules/ |
(оба на мастере) – размещение модулей
1 |
/etc/puppet/environments/production/modules |
(на мастере) – размещение модулей для конкретного окружения
Модули в Puppet
Широкая коллекция уже существующих модулей представлена здесь
https://forge.puppet.com/
Поиск необходимого модуля
1 |
# puppet module search <search_string> |
Например, модуля mysql
1 |
# puppet module search mysql |
Установка модуля mysql с Puppetlabs
1 |
# puppet module install puppetlabs-mysql |
1 2 3 4 5 6 7 |
Notice: Preparing to install into /etc/puppet/modules ... Notice: Downloading from https://forgeapi.puppetlabs.com ... Notice: Installing -- do not interrupt ... /etc/puppet/modules └─┬ puppetlabs-mysql (v3.10.0) ├── puppet-staging (v2.1.0) └── puppetlabs-stdlib (v4.14.0) |
1 |
# nano /etc/puppet/manifests/site.pp |
1 2 3 4 5 6 7 |
node puppet-client { include accounts class { '::mysql::server': root_password => '123456789', override_options => { 'mysqld' => { 'max_connections' => '1024' } } } } |
Проверка синтаксиса манифеста и его выполнение
1 |
# puppet parser validate /etc/puppet/manifests/site.pp |
1 |
# puppet agent --test |
1 2 3 4 5 6 7 8 9 10 11 12 13 |
Info: Retrieving pluginfacts Info: Retrieving plugin Info: Loading facts Info: Caching catalog for puppet-client.kamaok.org.ua Info: Applying configuration version '1483050460' Notice: /Stage[main]/Mysql::Server::Config/File[mysql-config-file]/ensure: defined content as '{md5}15d890f0648fc49e43fcffc6ed7bd2d8' Notice: /Stage[main]/Mysql::Server::Install/Package[mysql-server]/ensure: created Notice: /Stage[main]/Mysql::Server::Installdb/Mysql_datadir[/var/lib/mysql]/ensure: created Notice: /Stage[main]/Mysql::Server::Service/Service[mysqld]/ensure: ensure changed 'stopped' to 'running' Info: /Stage[main]/Mysql::Server::Service/Service[mysqld]: Unscheduling refresh on Service[mysqld] Notice: /Stage[main]/Mysql::Server::Root_password/Mysql_user[root@localhost]/password_hash: defined 'password_hash' as '*CC67043C7BCFF5EEA5566BD9B1F3C74FD9A5CF5D' Notice: /Stage[main]/Mysql::Server::Root_password/File[/root/.my.cnf]/ensure: defined content as '{md5}ea36d570297b4fb03f784246ceef462c' Notice: Finished catalog run in 84.67 seconds |
Провереяем, что установился MySQL, пароль MySQL пользователя root установлен в 123456789, параметр max_connections установлен в 1024
1 |
# mysql -u root -p123456789 -e "show variables like 'max_connections'" |
1 2 3 4 5 |
+-----------------+-------+ | Variable_name | Value | +-----------------+-------+ | max_connections | 1024 | +-----------------+-------+ |
Просмотр установленных модулей
1 |
# puppet module list |
1 2 3 4 5 6 |
/etc/puppet/modules ├── accounts (???) ├── puppet-staging (v2.1.0) ├── puppetlabs-concat (v2.2.0) ├── puppetlabs-mysql (v3.10.0) └── puppetlabs-stdlib (v4.14.0) |
Проверка,что puppet-manifest соотвествует стилю Puppet
1 |
# yum install rubygem-puppet-lint |
1 |
# puppet-lint /etc/puppet/modules/accounts/manifests/ssh.pp |
Автоматическое исправление найденных различий в стиле
1 |
# puppet-lint --fix /etc/puppet/modules/accounts/manifests/ssh.pp |
Примеры описания некоторых ресурсов
Управление пакетами
1 2 3 4 5 |
package { 'apache': name => 'httpd', # (namevar) ensure => 'present' # Values: 'absent', 'latest', '2.2.1' provider => undef, # Force an explicit provider } |
Управление службами
1 2 3 4 5 6 7 8 |
service { 'apache': name => 'httpd', # (namevar) ensure => 'running' # Values: 'stopped', 'running' enable => true, # Define if to enable service at boot (true|false) hasstatus => true, # Whether to use the init script' status to check # if the service is running. pattern => 'httpd', # Name of the process to look for when hasstatus=false } |
Управление файлами
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
file { 'httpd.conf': # (namevar) The file path path => '/etc/httpd/conf/httpd.conf', # Define the file type and if it should exist: # 'present','absent','directory','link' ensure => 'present', # Url from where to retrieve the file content source => 'puppet://[puppetfileserver]/<share>/path', # Actual content of the file, alternative to source # Typically it contains a reference to the template function content => 'My content', # Typical file's attributes owner => 'root', group => 'root', mode => '0644', # The sylink target, when ensure => link target => '/etc/httpd/httpd.conf', # Whether to recursively manage a directory (when ensure => directory) recurse => true, } |
Управление пользователями
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
user { 'joe': # (namevar) The user name name => 'joe', # The user's status: 'present','absent','role' ensure => 'present', # The user's id uid => '1001', # The user's primary group id gid => '1001', # Eventual user's secondary groups (use array for many) groups => [ 'admins' , 'developers' ], # The user's password. As it appears in /etc/shadow # Use single quotes to avoid unanted evaluation of $* as variables password => '$6$ZFS5JFFRZc$FFDSvPZSSFGVdXDlHe�', # Typical users' attributes shell => '/bin/bash', home => '/home/joe', mode => '0644', } |
Выполнение команд
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
exec { 'get_my_file': # (namevar) The command to execute command => "wget http://mysite/myfile.tar.gz -O /tmp/myfile.tar.gz', #The search path for the command. Must exist when command is not absolute # Often set in Exec resource defaults path => '/sbin:/bin:/usr/sbin:/usr/bin', #A file created by the command. It if exists, the command is not executed creates => '/tmp/myfile.tar.gz', # A command or an array of commands, if any of them returns an error # the command is not executed onlyif => 'ls /tmp/myfile.tar.gz && false', # A command or an array of commands, if any of them returns an error # the command IS executed unless => 'ls /tmp/myfile.tar.gz', } |
Puppet предоставляет различные конструкции для управления условиями внутри манифеста
Selectors
1 2 3 4 5 |
$package_name = $osfamily ? { 'RedHat' => 'httpd', 'Debian' => 'apache2', default => undef, } |
Case
1 2 3 4 5 |
case $::osfamily { 'Debian': { $package_name = 'apache2' } 'RedHat': { $package_name = 'httpd' } default: { notify { "Operating system $::operatingsystem not supported" } } } |
If elsif else
1 2 3 4 5 6 7 |
if $::osfamily == 'Debian' { $package_name = 'apache2' } elsif $::osfamily == 'RedHat' { $package_name = 'httpd' } else { notify { "Operating system $::operatingsystem not supported" } } |
Операторы сравнения в Puppet
Puppet поддерживает некоторые общие операторы сравнения
1 |
== != < > <= >= =~ !~ |
1 2 3 4 |
if $::osfamily == 'Debian' { [ ... ] } if $::kernel != 'Linux' { [ ... ] } if $::uptime_days > 365 { [ ... ] } if $::operatingsystemrelease <= 6 { [ ... ] } |
А также оператор
1 |
in |
1 2 |
if '64' in $::architecture if $monitor_tool in [ 'nagios' , 'icinga' , 'sensu' ] |
Комбинация условий
1 2 3 4 |
if ($::osfamily == 'RedHat') and ($::operatingsystemrelease == '5') { [ ... ] } |
1 2 3 |
if ($::osfamily == 'Debian') or ($::osfamily == 'RedHat') { [ ...] } |
Источники:
http://www.example42.com/tutorials/PuppetTutorial/
https://docs.puppet.com/puppet/
https://rtfm.co.ua/centos-ustanovka-i-nastrojka-puppet-servera-i-puppet-agenta
https://www.linode.com/docs/applications/puppet/install-and-configure-puppet
https://www.linode.com/docs/applications/puppet/create-puppet-module
http://www.ibm.com/developerworks/ru/library/l-puppet_01/
https://xakep.ru/2011/05/14/55238/