puppet

Thank you for reading this post, don't forget to subscribe!

Puppet — крос­сплат­фор­мен­ное кли­ент-сер­вер­ное ПО, кото­рое поз­во­ля­ет цен­тра­ли­зо­ван­но управ­лять кон­фи­гу­ра­ци­ей ОС и ути­лит, кото­рые уста­нов­ле­ны на раз­ных сер­ве­рах. Мно­гие боль­шие ком­па­нии исполь­зу­ют puppet для сво­их целей.

Узлы сети, управ­ля­е­мые с помо­щью Puppet, пери­о­ди­че­ски опра­ши­ва­ют сер­вер, полу­ча­ют и при­ме­ня­ют вне­сён­ные адми­ни­стра­то­ром изме­не­ния в кон­фи­гу­ра­цию. Кон­фи­гу­ра­ция опи­сы­ва­ет­ся на спе­ци­аль­ном декла­ра­тив­ном пред­мет­но-ори­ен­ти­ро­ван­ном языке

Паппет терминология.

  • Facts: Пап­пет агент на каж­дом узле отправ­ля­ет дан­ные о состо­я­нии ноды ( кото­рые назы­ва­ют­ся фак­та­ми) на сер­вер с puppet-master-ом.
  • Catalog: Сер­вер с пап­пет-масте­ром исполь­зу­ет факт что­бы ском­пи­ли­ро­вать подроб­ные дан­ные о том, как дол­жен быть скон­фи­гу­ри­ро­ван узел ( это так зва­ный ката­лог) и отпра­вить его обрат­но на пап­пет-агент. Пап­пет-агент вно­сит любые изме­не­ния в catalog. Puppet-agent может симу­ли­ро­вать дан­ные изме­не­ния (име­ет­ся опция — ‘—noop’) для того, что­бы про­ве­сти тесты.
  • Report: Каж­дый пап­пет-агент отправ­ля­ет отчет на пап­пет-масте с ука­за­ни­ем любых изме­не­ний, вне­сен­ных в конфигурацию.
  • Report Collection: Откры­тое puppet API кото­ре может быть исполь­зо­ва­но для отправ­ки дан­ных. Таким обра­зом, инфра­струк­ту­ра может исполь­зо­вать­ся сов­мест­но с дру­ги­ми командами.

Особенности Puppet

  • Раз­ра­бо­тан таким обра­зом, что он предот­вра­ща­ет дуб­ли­ро­ва­ние выпол­не­ние запу­щен­ных манифестов.
  • Гото­вый к исполь­зо­ва­нию инструмент.
  • Мощ­ный Framework.
  • Упро­ща­е­те выпол­не­ние рутин­ных задач систем­но­го администратора.
  • Помо­га­ет в управ­ле­нии физи­че­ски­ми и вир­ту­аль­ны­ми устрой­ства­ми, а так­же облаками.

У меня имеется:

  • 192.168.1.150 puppet-server
  • 192.168.1.16 puppet-agent

Puppet в репо­зи­то­ри­ях состо­ит из несколь­ких паке­тов, puppet-сер­вер и puppet-кли­ент — это 2 основ­ных паке­та кото­рые потребуются.

Пап­пет под­дер­жи­ва­ет 2 режи­ма использования:

  • Standalone Mode — это когда уста­нав­ли­ва­ет­ся на каж­дую из машин puppet-server и puppet-agent и он про­ви­же­нит все дело на одной толь­ко ноде. Все мани­фе­сты, все настрой­ки будет толь­ко на одном сер­ве­ре. Мож­но запус­кать по cron.
  • Master-Agent — это когда у вас име­ет­ся puppet-server и уста­нов­лен­ные puppet-agent-ы на дру­гих маши­нах. Puppet-агент пери­о­ди­че­ски отправ­ля­ет фак­ты на puppetmaster и запра­ши­ва­ет ката­лог. Puppetmaster ком­пи­ли­ру­ет и воз­вра­ща­ет ката­лог кон­крет­но­го узла, исполь­зуя источ­ни­ки инфор­ма­ции, к кото­рым он име­ет доступ.

Установка Puppet в Unix/Linux

Мож­но под­клю­чить репо­зи­то­рий EPEL — вклю­чить EPEL репо­зи­то­рий на CentOS и потом, выпол­ним поиск пакетов:

 # yum list puppet*
 Но луч­ше все­го, исполь­зо­вать уже гото­вый репо­зи­то­рий с офи­ци­аль­но­го сайта.

Смот­рим какой тип ОС име­ет­ся в систе­ме, для это­го мож­но выполнить:

# uname -m
x86_64

И потом выби­ра­ем вер­сию ОС….

CentOS 6:

rpm -ivh http://yum.puppetlabs.com/puppetlabs-release-el-6.noarch.rpm

 CentOS 7:
 # rpm -ivh http://yum.puppetlabs.com/el/7/products/x86_64/puppetlabs-release-22.0-2.noarch.rpm
 И добавим:
#·rpm -ivh https://yum.puppetlabs.com/puppetlabs-release-pc1-el-7.noarch.rpm
 Проверяем:
# yum repolist | grep puppet
 Получаем:
puppetlabs-deps/x86_64 Puppet Labs Dependencies El 7 - x86_64 17
puppetlabs-products/x86_64 Puppet Labs Products El 7 - x86_64 225
 Уста­нов­ка puppet-server в CentOS/Fedora/RedHat

Уста­нав­ли­ва­ем сам puppet-server:

yum -y install puppet-server

 

/etc/sysconfig/puppet — мик­ро­кон­фиг. Реко­мен­ду­ет­ся рас­ком­мен­ти­ро­вать для полу­че­ния отдель­ных логов строчку

/etc/puppet/environments — может исполь­зо­вать­ся для деле­ния кли­ен­тов на груп­пы, весь­ма неод­но­знач­ная тех­но­ло­гия, нуж­на, если узлов не мень­ше 30 и зача­стую заме­ня­ет­ся экзо­ти­че­ской над­строй­кой R10K.

/etc/puppet/hieradata — исполь­зу­ет­ся для хра­не­ния, доволь­но инте­рес­ная тех­но­ло­гия, тре­бу­ет отдель­ной статьи.

/etc/puppet/manifests/site.pp — основ­ной кон­фиг запус­ка клас­сов из моду­лей настрой­ки клиентов.

/etc/puppet/modules — соб­ствен­но сюда скачиваются/пишутся_свои моду­ли для настрой­ки кли­ен­тов, кото­рые по сути пред­став­ля­ют из себя набор клас­сов (мани­фе­стов), напи­са­ных на DSL, похо­жем на Ruby. При жела­нии мож­но даже делать встав­ки на чистом Ruby.

/var/lib/puppet — пока сюда не лезем, будет нуж­но для сертификатов.

/etc/puppet/puppet.conf — основ­ной кон­фиг настрой­ки сервера.

Добав­ля­ем в /etc/puppet/puppet.conf сек­ция [main]:

dns_alt_names — здесь про­пи­сы­ва­ют­ся узлы, кото­рые могут рабо­тать с сер­ве­ром через сер­ти­фи­ка­ты. Тем у кого сер­ве­ра сидят за прок­сёй и они хотят тянуть моду­ли с forgeapi.puppetlabs.com, полез­но будет знать, что puppet пофиг на ваши систем­ные http_proxy=proxy01.int:8080 и https_proxy=proxy02.int:8080 и при­дёт­ся забить в кон­фиг доп секцию.

Для про­вер­ки всех теку­щих пара­мет­ров сер­ве­ра есть полез­ная команда:

При­чём даже демон пере­за­гру­жать не надо, он всё вре­мя пере­чи­ты­ва­ет свои конфиги.

Выста­вим огра­ни­че­ние по исполь­зо­ва­нию RAM в puppet:

vim /etc/sysconfig/puppetmaster

Затем най­ди­те стро­ку JAVA_ARGS и исполь­зуй­те -Xms и -Xmx пара­мет­ры , что­бы уста­но­вить рас­пре­де­ле­ние памя­ти. Напри­мер, если вы хоти­те исполь­зо­вать 4 ГБ памя­ти, стро­ка долж­на выгля­деть так:

 JAVA_ARGS="-Xms4g -Xmx4g"
 PS: У меня, нет сколь­ко RAM (т.к я исполь­зую пап­пет для тестов) и по это­му, я выде­лю 512Мб:
JAVA_ARGS="-Xms512m -Xmx512m"

ЭТО НУЖНО ДЛЯ PUPPET 4 (насчет 5-го я не уве­рен), Т.К ИСПОЛЬЗУЕТСЯ JAVA ВНУТРИ PUPPET.

Дан­ный сер­вер, напи­сан на рубене, по это­му — он тоже поста­вит­ся (вме­сте с зависимостями).

Если вы не пред­по­ла­га­е­те исполь­зо­вать DNS, вы може­те доба­вить запи­си в файл на сер­ве­ре и кли­ен­те. Откры­ва­ем файл:

vim /etc/hosts

В фай­ле /etc/hosts добав­ля­ем запись (это важ­но – имя хоста долж­но быть доступ­но и назна­че­но и сер­ве­ру, и клиенту):

 # cat /etc/hosts
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.1.150 centos6 puppet-server pmaster.centos6
192.168.1.16 centos62 puppet-agent pagent.centos62
 Смот­рим какой хостнейм:
# hostname
centos6
ИЛИ:
 facter | grep hostname
hostname => centos6
 facter | grep fqdn
fqdn => centos6
Запус­ка­ем сер­вер с паппетом:
# service puppetmaster start
 Или:
 #systemctl start puppetserver
или
service puppetserver start
Убе­дим­ся что он работает:
 # netstat -natpl | grep 8140
tcp 0 0 0.0.0.0:8140 0.0.0.0:* LISTEN 20870/ruby
Так же, мож­но запу­стить puppetmaster без демона:
 ·puppet master --mkusers --verbose --no-daemonize
 Если исполь­зу­е­те puppet 4, сто­ит про­пи­сать нуж­ный PATH, для это­го открываем:
# vim ·~/.bash_profile
И про­пи­сы­ва­ем:
export PUPPET_HOME=/opt/puppetlabs/
PATH=$PATH:$HOME/bin:$PUPPET_HOME/bin
export PATH

Что­бы изме­не­ния всту­пи­ли в силу, выполните:

 # .·~/.bash_profile
После чего, мож­но исполь­зо­вать пап­пет. Напри­мер, мож­но посмот­реть вер­сию puppet-server мож­но вот так:
 # puppet -V
3.8.7

Так же, мож­но про­гнать тест:

# puppet agent --test --server=`hostname`

Info: Using configured environment 'production'
Info: Retrieving pluginfacts
Info: Retrieving plugin
Info: Caching catalog for puppet-server
Info: Applying configuration version '1503439536'
Info: Creating state file /opt/puppetlabs/puppet/cache/state/state.yaml
Notice: Applied catalog in 0.04 seconds
Для обнов­ле­ния сер­ве­ра, исполь­зуй­те сле­ду­ю­щую команду:
# puppet resource package puppet-server ensure=latest

Добав­ля­ем в автозапуск:

1 # chkconfig puppetmaster on

Про­ве­ря­ем:

1 # chkconfig --list | grep puppetmaster
2 puppetmaster 0:off 1:off 2:on 3:on 4:on 5:on 6:off

Как-то так.

Фай­лы и кли­ен­та и сер­ве­ра хра­нят­ся в ката­ло­ге /etc/puppet:

1 # ls -l /etc/puppet
2 total 28
3 -rw-r--r--. 1 root root 4178 Jun 10 00:09 auth.conf
4 drwxr-xr-x. 3 root root 4096 Jul 2 12:18 environments
5 -rw-r--r--. 1 root root 1462 Jun 10 00:08 fileserver.conf
6 drwxr-xr-x. 2 root root 4096 Jun 10 00:09 manifests
7 drwxr-xr-x. 2 root root 4096 Jun 10 00:09 modules
8 -rw-r--r--. 1 root root 853 Jun 10 00:08 puppet.conf

Фай­лы fileserver.conf и auth.conf исполь­зу­ют­ся для настрой­ки фай­ло­во­го сер­ве­ра и аутен­ти­фи­ка­ции – мы их пока тро­гать не будем.

Ката­лог manifests содер­жит в себе “мани­фе­сты”, кото­рые явля­ют­ся фай­ла­ми настрой­ки для кли­ен­тов. Основ­ной из них – файл site.pp, кото­рый будет счи­ты­вать­ся масте­ром все­гда, и его настрой­ки будут при­ме­нять­ся ко всем кли­ен­там (если дру­гое не ука­за­но в самом манифесте).

 

 

Добавляем правило  iptables

Если исполь­зу­е­те iptables, то про­пи­шем правило:

 # iptables -I INPUT 2 -p tcp --dport 8140 -j ACCEPT
И еще одно (если его нет):
 # iptables -I -INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
 После чего, выпол­ня­ем сохранение:
# service iptables save

Добав­ля­ем в автозапуск:

# chkconfig puppetmaster on
 И что­бы про­ве­рить, выполните:
# chkconfig --list | grep puppetmaster
ИЛИ:
#·systemctl enable puppetserver
# systemctl start puppetserver

Добав­ля­ем пра­ви­ло systemd

 # firewall-cmd --permanent --zone=public --add-port=8140/tcp
# firewall-cmd --reload

Посмот­реть все теку­щие настрой­ки мож­но выпол­нив сле­ду­ю­щую команду

puppet apply --configprint all

Для каж­дой опции, мож­но выво­дить зна­че­ние — это мож­но исполь­зо­вать сле­ду­ю­щим образом:

 # puppet master --configprint syslogfacility
 Пока что сер­вер настро­и­ли и пере­хо­дим к уста­нов­ке агентов.

Установка puppet-agent в CentOS/Fedora/RedHat

Puppet-agent дол­жен быть уста­нов­лен на сер­вер, кото­рым будет управ­лять puppet-master (puppet-server).

Уста­нав­ли­ва­ем puppet-agent:

yum -y install puppet

или

yum -y install puppet-agent

На каж­дом кли­ен­те Puppet добавь­те запись о сер­ве­ре + хост­нейм для нод с клиентом:

 # cat /etc/hosts
127.0.0.1 localhost
192.168.1.150 centos6 puppet-server pmaster.centos6
192.168.1.16 centos62 puppet-agent pagent.centos62

Про­ве­ря­ем на puppet-ане­те имя хоста:

 # hostname
centos62
Так же, если исполь­зу­е­те puppet 4, сто­ит про­пи­сать нуж­ный PATH, для это­го открываем:
 # vim ·~/.bash_profile
И про­пи­сы­ва­ем:
  export PUPPET_HOME=/opt/puppetlabs/
PATH=$PATH:$HOME/bin:$PUPPET_HOME/bin
export PATH
Что­бы изме­не­ния всту­пи­ли в силу, выполните:
  # .·~/.bash_profile
 После чего, мож­но исполь­зо­вать пап­пет. Напри­мер, мож­но посмот­реть вер­сию puppet-server мож­но вот так:
# puppet -V
3.8.7

/etc/puppet/puppet.conf — основ­ной конфиг.

На кли­ен­те редак­ти­ру­ем файл /etc/puppet/puppet.conf и в блок [agent] добавляем :

1 server = pmaster.centos6

Тут важ­но заме­ча­ние – во мно­гих ману­а­лах гово­рит­ся про puppetccapuppetd и т.п. – но в вер­сии 3.0 они отсут­ству­ют (пер­вая колон­ка – ста­рая коман­да, во вто­рой – новая):

puppetmasterd puppet master
puppetd puppet agent
puppet puppet apply
puppetca puppet cert
ralsh puppet resource
puppetrun puppet kick
puppetqd puppet queue
filebucket puppet filebucket
puppetdoc puppet doc
pi puppet describe

/etc/init.d/puppet — демон кли­ен­та для авто­про­ве­рок, не изме­ни­лось ли что на сер­ве­ре. Мы будем поль­зо­вать­ся ком строкой.

/etc/sysconfig/puppet — мик­ро­кон­фиг. При­во­дим его к виду вроде:

 # chkconfig puppet on
Для обнов­ле­ния кли­ен­та, исполь­зуй­те команду:
# puppet resource package puppet ensure=latest
 Теперь про­ве­рим как всё работает.

Следующий шаг – создание сертификата клиента, выполняем:

На сер­ве­ре будет само­под­пис­ной и сге­не­ри­ру­ет­ся при запус­ке сер­ве­ра. На кли­ен­те дела­ем запрос на верификацию:

Здесь нас может под­жи­дать пер­вый камень типа «забы­ли про порт или сер­вис на сер­ве­ре». Неяв­но вы уви­ди­те ошибку:

Исполь­зо­вав ключ –debug, полу­чи­те более подробное:

Ну а если всё нор­маль­но то нечто вроде:

На сер­ве­ре про­ве­ря­ем при­шёл ли запрос от кли­ен­та (нода, или node в тер­ми­но­ло­гии Puppet):
puppet cert list
puppet cert list --all
"centos62" (SHA256) 0C:80:58:DD:BF:12:1C:10:22:89:FD:D3:99:8D:C9:08:F0:D8:AC:90:CE:44:AF:05:D4:09:2F:E7:6D:DE:A2:4E
+ "pmaster.centos6" (SHA256) F7:F3:AD:FC:42:C4:CE:C3:2E:70:08:07:0E:BE:1A:66:80:2A:51:41:85:86:C5:FB:A6:FB:85:F1:C8:E9:0D:0A (alt names: "DNS:pagent.centos6.2", "DNS:pmaster.centos6")Если он без плю­са, зна­чит его надо подписать
Обра­ти­те вни­ма­ние на имя хоста во вре­мя гене­ра­ции сер­тиф­ка­та – вот поче­му важ­но их вез­де уста­но­вить вер­но. Под­пи­сы­ва­ем клиента:

puppet cert sign centos62

Итог дол­жен появить­ся в /var/lib/puppet/ssl. Если что то пошло не так всё там сти­ра­ем и повто­ря­ем зано­во. Соб­ствен­но теперь у нас гото­вая кон­фи­гу­ра­ция и мож­но посмот­реть доступ­ное народ­ное твор­че­ство, или поис­кать что то для себя напря­мую из команд­ной строки:

 

Если необходимо удалить данный сертификат то 

на кли­ен­те:

rm -rf /var/lib/puppet/ssl
puppet node clean centos62
на масте­ре
puppet cert clean centos62

Проверим как работает:

Редак­ти­ру­ем файл /etc/puppet/manifests/site.pp на сер­ве­ре и изме­ним права:

1 file { "/etc/passwd":
2 owner => "root",
3 group => "bin",
4 mode => 644,
5 }

на:

1 file { "/etc/passwd":
2 owner => "root",
3 group => "bin",
4 mode => 777,
5 }

Сна­ча­ла посмот­рим на файл на кли­ен­те сейчас:

1 # ls -l /etc/passwd
2 -rw-r--r--. 1 root bin 1390 Jul 2 13:10 /etc/passwd

Теперь – мож­но либо подо­ждать 30 минут, пока агент сам запро­сит изме­не­ния, либо пере­за­пу­стить его, либо настро­ить не мень­ший интер­вал запро­сов изме­не­ний от мастера.

Выбе­рем послед­ний вари­ант – редак­ти­ру­ем файл puppet.conf на кли­ен­те, и уста­нав­ли­ва­ем в бло­ке [agent] опцию:

1 runinterval = 10

Где 10 – коли­че­ство секунд меду запросами.

Сохра­ня­ем, выхо­дим, и видим на сер­ве­ре в логе каж­дые 10 секунд сообщение:

[2018-05-23 12:03:36] 192.168.1.16 - - [23/May/2018:12:03:36 EDT] "GET /production/node/centos62?fail_on_404=true&transaction_uuid=e75152b3-b524-4f0a-9e44-1daf332a2827 HTTP/1.1" 200 3695
[2018-05-23 12:03:36] - -> /production/node/centos62?fail_on_404=true&transaction_uuid=e75152b3-b524-4f0a-9e44-1daf332a2827
[2018-05-23 12:03:36] 192.168.1.16 - - [23/May/2018:12:03:36 EDT] "GET /production/file_metadatas/pluginfacts?ignore=.svn&ignore=CVS&ignore=.git&checksum_type=md5&recurse=true&links=manage HTTP/1.1" 200 283
[2018-05-23 12:03:36] - -> /production/file_metadatas/pluginfacts?ignore=.svn&ignore=CVS&ignore=.git&checksum_type=md5&recurse=true&links=manage
[2018-05-23 12:03:36] 192.168.1.16 - - [23/May/2018:12:03:36 EDT] "GET /production/file_metadatas/plugins?ignore=.svn&ignore=CVS&ignore=.git&checksum_type=md5&recurse=true&links=manage HTTP/1.1" 200 283
[2018-05-23 12:03:36] - -> /production/file_metadatas/plugins?ignore=.svn&ignore=CVS&ignore=.git&checksum_type=md5&recurse=true&links=manage
[2018-05-23 12:03:37] 192.168.1.16 - - [23/May/2018:12:03:37 EDT] "POST /production/catalog/centos62 HTTP/1.1" 200 807
[2018-05-23 12:03:37] - -> /production/catalog/centos62
[2018-05-23 12:03:38] 192.168.1.16 - - [23/May/2018:12:03:38 EDT] "PUT /production/report/centos62 HTTP/1.1" 200 9
[2018-05-23 12:03:38] - -> /production/report/centos62

на кли­ен­те в логе:

Wed May 23 12:01:38 -0400 2018 /Stage[main]/Main/File[/etc/passwd]/group (notice): group changed 'root' to 'bin'
Wed May 23 12:01:38 -0400 2018 /Stage[main]/Main/File[/etc/passwd]/mode (notice): mode changed '0644' to '0777'
Wed May 23 12:01:38 -0400 2018 Puppet (notice): Finished catalog run in 0.05 seconds

Про­ве­ря­ем файл на клиенте:

ls -lah /etc/passwd
-rwxrwxrwx 1 root bin 1.1K May 23 05:54 /etc/passwd

Всё рабо­та­ет.

Не забы­ва­ем вер­нуть зна­че­ние 644.

 

------------------------

Теория

-----------------------

puppet.conf

Может содер­жать сле­ду­ю­щие настройки:

  • node_name — опре­де­ля­ет, как мастер будет иден­ти­фи­ци­ро­вать кли­ен­та для исполь­зо­ва­ния в мани­фе­стах, а так­же опре­де­ля­ет пере­мен­ные hostnamefqdn и domain. Воз­мож­ные зна­че­ния cert (исполь­зу­ет зна­че­ние certname) и facter (исполь­зу­ет hostname кли­ен­та). По умол­ча­нию : cert.
  • manifest — вход­ной мани­фест кото­рый откры­ва­ет puppet. По умол­ча­нию: $manifestdir/site.pp.
  • manifestdir — пап­ка, где мастер ищет мани­фе­сты. По умол­ча­нию: $confdir/manifests.
  • runinterval — коли­че­ство секунд, через кото­рое кли­ент будет опра­ши­вать масте­ра. По умол­ча­нию: 1800 (30 минут).
  • puppetport — порт, по кото­ро­му про­ис­хо­дит обмен. По умол­ча­нию: 8139.
  • puppetdlockfile — адрес, по кото­ро­му раз­ме­ща­ет­ся lock — файл, запре­ща­ю­щий запуск несколь­ких копий puppet на кли­ен­те. По умол­ча­нию: $statedir/puppetdlock.
  • templatedir — пап­ка, где мастер ищет шаблоны.
  • modulepath — пап­ка, где мастер ищет модули.

Консольные команды

  • puppet apply --configprint modulepath — выво­дит зна­че­ние кон­крет­ной настрой­ки puppet.conf (в дан­ном слу­чае modulepath), если вве­сти --configprint all мож­но полу­чить пол­ный теку­щий кон­фиг. (И сохра­нить перед тем как начать что-то править…)
  • puppet resource <type> <id> — поз­во­ля­ет полу­чить опи­са­ние ресур­са опре­де­лён­но­го типа <type> с иден­ти­фи­ка­то­ром <id> сра­зу на декла­ра­тив­ном язы­ке puppet. Напри­мер puppet resource user root. Тип ресур­са user а его иден­ти­фи­ка­тор (адрес) root
  • puppet describe -s <type> — поз­во­ля­ет полу­чить опи­са­ние типа, име­ю­щих­ся для него команд.
  • puppet apply <my_test_manifest.pp> — выпол­ня­ет ука­зан­ный манифест.
  • puppet apply -e «include undeclaredclass» — выпол­нит неза­де­кла­ри­ро­ван­ный класс undeclaredclass, нахо­дя­щий­ся в одном из напи­сан­ных вами моду­лей (есте­ствен­но, рас­по­ло­жен­ном в пап­ке $modulepath).

Манифесты

Их ино­гда назы­ва­ют рецеп­та­ми, пред­став­ля­ют собой тек­сто­вые фай­лы с рас­ши­ре­ни­ем .pp (По умол­ча­нию выпол­ня­ет­ся $confdir/manifests/site.pp). В мани­фе­сте могут и долж­ны содержаться:

  • Клас­сы (class)
  • Узлы (node)
  • Ресур­сы (то есть типы file, user и др.)
  • Ссыл­ки на дру­гие мани­фе­сты (import)

Встроенные переменные

Встро­ен­ные пере­мен­ные ста­но­вят­ся доступ­ны­ми бла­го­да­ря ути­ли­те facter, уста­нав­ли­ва­е­мой вме­сте с puppet, кото­рая берёт инфор­ма­цию из систе­мы. Если набрать в команд­ной стро­ке facter, то мож­но полу­чить пол­ный спи­сок доступ­ных пере­мен­ных. Вот неко­то­рые из них:

  • $operatingsystem — опе­ра­ци­он­ная система.
  • $fqdn — пол­ное домен­ное имя.
  • $hostname — имя хоста.
  • $ipaddress — IP адрес.
  • $osfamily — семей­ство опе­ра­ци­он­ных систем.
  • $is_virtual — запу­ще­на ли ОС в вир­ту­аль­ной машине.

Гид по языку

  • Усло­вие
  • Пере­чис­ле­ние
  • Выбор
  • Атри­бу­ты по умолчанию

Классы

  • Насле­до­ва­ние классов

При вызо­ве клас­са freebsd для фай­лов атри­бут group изме­нит­ся на wheel, а вот атри­бут owner не будет про­ве­рять­ся вооб­ще. Зна­че­ние атри­бу­тов мож­но не заме­нять а добавлять:

  • Зави­си­мо­сти меж­ду классами

Но таких кон­струк­ций луч­ше избе­гать, так как это может при­ве­сти к цик­лам. Сле­ду­ю­щий при­мер поз­во­ля­ет это­го избе­жать и сохра­ня­ет пра­ви­ло, когда один ресурс объ­яв­ля­ет­ся толь­ко один раз:

  • Пара­мет­ри­зи­ро­ван­ные классы

Основные типы

Общие атрибуты

  • before — опре­де­ля­ет, что дан­ный ресурс дол­жен отра­бо­тать до како­го-то дру­го­го. Зада­ёт­ся в виде мета­па­ра­мет­раType['title']. Мож­но зада­вать мас­сив мета­па­ра­мет­ров [Type1['title1'],Type2['title2']]. В мета­па­ра­мет­рах (или ссыл­ках на ресур­сы) тип ресур­са обя­за­тель­но ука­зы­ва­ет­ся с боль­шой буквы.
  • notify — созда­ёт отно­ше­ние, ана­ло­гич­ное before, но опре­де­ля­ет, что сле­ду­ю­щий ресурс отра­бо­та­ет толь­ко после того, как дан­ный изме­нит­ся. Зада­ёт­ся метапараметром.
  • require — опре­де­ля­ет, что дан­ный ресурс дол­жен отра­бо­тать толь­ко после дру­го­го. Зада­ёт­ся метапараметром.
  • subscribe — созда­ёт отно­ше­ние, ана­ло­гич­ное require, но опре­де­ля­ет, что дан­ный ресурс дол­жен отра­бо­тать толь­ко после того, как ресурс на кото­рый под­пи­са­лись изме­нит­ся. Зада­ёт­ся метапараметром.
  • schedule — опре­де­ля­ет рас­пи­са­ние (интер­вал) для запус­ка дан­но­го ресур­са. См. тип shedule.
  • noop — опре­де­ля­ет, дол­жен ли отра­бо­тать дан­ный ресурс. Рав­но true (по умол­ча­нию) или false.

notify

Запи­сы­ва­ет опре­де­лён­ное сооб­ще­ние в лог. Не выво­дит ника­кой инфор­ма­ции пользователю.

  • name — Тэг на Ваше усмот­ре­ние, зада­ёт имя сообщения.
  • message — Текст, кото­рый будет отправ­лен в лог. Если не задан, puppet по умол­ча­нию счи­ты­ва­ет из заго­лов­ка ресурса.
  • withpath — Пока­зы­вать или нет пол­ный путь к объ­ек­ту, если вклю­че­но, то в логе будет 2 стро­ки: само сооб­ще­ние и ещё пол­ный путь по вло­же­ни­ям отку­да оно запус­ка­лось. Рав­но true или false (в ману­а­лах пишут что по умол­ча­нию рав­но false, но на прак­ти­ке наблю­да­ет­ся обратное).

file

Поз­во­ля­ет управ­лять фай­ла­ми и директориями.

  • ensure — про­вер­ка на суще­ство­ва­ние фай­ла и его тип. Име­ет зна­че­ния present (суще­ству­ет), absent (отсут­ству­ет), file (явля­ет­ся фай­лом), directory (явля­ет­ся дирек­то­ри­ей), link (явля­ет­ся ссылкой).
  • path — Пол­ный адрес к фай­лу. Если не задан, puppet по умол­ча­нию счи­ты­ва­ет из заго­лов­ка ресурса.
  • source — Отку­да качать файл. Это адрес на масте­ре puppet:/// или локальный.
  • mode — Пра­ва на файл (напри­мер, 0740). Долж­ны зада­вать­ся чис­ло­вым зна­че­ни­ем. Рабо­та­ет так же и с директориями.
  • target — Сим­воль­ная ссыл­ка (когда зада­но ensure => link).
  • recurse — Опре­де­ля­ет, обра­ба­ты­вать дирек­то­рию рекур­сив­но с под­ка­та­ло­га­ми и всем содер­жи­мым (когда зада­но ensure => directory). Рав­но truefalse или remoteRemote — ука­зы­ва­ет, что надо пере­брать рекур­сив­но ката­лог на сер­ве­ре и обра­бо­тать на кли­ен­те все най­ден­ные на сер­ве­ре фай­лы. Рекур­сив­но на кли­ен­те ката­лог обра­ба­ты­вать­ся не будет.
  • recurselimit — Опре­де­ля­ет, как глу­бо­ко ухо­дить в под­ка­та­ло­ги. Может при­ни­мать зна­че­ния /^[0-9]+$/ (нату­раль­ные числа).
  • owner — Поль­зо­ва­тель-вла­де­лец фай­ла, зада­ёт­ся по име­ни или UID.
  • group — Груп­па-вла­де­лец фай­ла, зада­ёт­ся по име­ни или GID.
  • content — Зада­ёт стро­ку, уста­нав­ли­ва­е­мую в каче­стве содер­жи­мо­го фай­ла. Наи­бо­лее полез­ны в рабо­те с шаб­ло­на­ми, но вы так­же може­те исполь­зо­вать функ­ции фай­ло­во­го выво­да (кон­соль­ные команды).
  • purge — Уда­лять ли фай­лы из дирек­то­рии кото­рых нет на масте­ре у кли­ен­та (рабо­та­ет когда recurse => true). Рав­но true (в дирек­то­рии будут толь­ко те фай­лы что есть на масте­ре, осталь­ные уда­лят­ся) или false (син­хро­ни­зи­ру­ют­ся те фай­лы, что есть на сер­ве­ре, осталь­ные оста­нут­ся без изменений).
  • mtime — про­вер­ка на вре­мя послед­не­го изме­не­ния файла.
  • ctime — про­вер­ка на вре­мя послед­не­го изме­не­ния вла­дель­ца или прав досту­па к файлу.
  • backup — Нуж­но ли делать бэкап фай­ла перед его заме­ной. Рав­но false (не надо делать резерв­ной копии), .ваш_текст_начинающийся_с_точки (сде­ла­ет резерв­ную копию в том же месте где и был файл добав­ле­ни­ем к нему суф­фик­са .ваш_текст_начинающийся_с_точки), ваш_текст_без_точки_вначале (сар­хи­ви­ру­ет в filebucket с име­нем ваш_текст_без_точки_вначале).
  • force — поз­во­ля­ет выпол­нить опе­ра­цию даже если она уни­что­жит одну или несколь­ко дирек­то­рий. Тре­бу­ет­ся исполь­зо­вать: сов­мест­но с пара­мет­ром purge (будут так­же уда­лять­ся и под­ди­рек­то­рии), когда необ­хо­ди­мо заме­нить дирек­то­рию фай­лом или ссыл­кой, и когда уда­ля­ет­ся дирек­то­рия (ensure => absent). Рав­но true или false.
  • checksum — Алго­ритм под­сче­та кон­троль­ной сум­мы при опре­де­ле­нии изме­не­ния содер­жи­мо­го файла.
    Зна­че­ние по умол­ча­нию: md5.
    Воз­мож­ные зна­че­ния: md5md5litemtimectimenone.
  • ignore — Пара­метр опре­де­ля­ю­щий игно­ри­ру­е­мые фай­лы при рекур­сив­ной обра­бот­ке каталога.
    Исполь­зу­ет­ся стан­дарт­ный встро­ен­ный дви­жок ruby. К при­ме­ру пол­но­стью под­дер­жи­ва­ют­ся мета­сим­во­лы вро­де [a-z]*.
    Сов­па­де­ния испол­зу­ю­щие вхож­де­ние в под­ка­та­ло­ги, вро­де */*, игно­ри­ру­ют­ся (**в ори­ги­на­ле: Matches that would descend into the directory structure are ignored, e.g., */*).
  • links — Как обра­ба­ты­вать сим­во­ли­че­ские ссыл­ки во вре­мя обра­бот­ки файлов.
    Воз­мож­ные значения:
    • follow — будет ско­пи­ро­ван ука­зан­ный по ссыл­ке файл
    • manage — будет ско­пи­ро­ва­на сама ссылка
    • ignore — ссыл­ка будет проигнорирована
  • provider — Кон­крет­ный бэкенд исполь­зу­е­мый этим ресур­сом. Ско­рее все­го вам не при­дет­ся исполь­зо­вать этот пара­метр, т.к. puppet опре­де­лит этот пара­метр в соот­вет­ствии с платформой
    Воз­мож­ные зна­че­ния: posixwindows
  • replace — Заме­нить ли файл или сим­во­ли­че­скую ссыл­ку, кото­рая уже суще­ству­ет в локаль­ной систе­ме, но содер­жа­ние кото­ро­го не соот­вет­ству­ет тому, что источ­ник или содер­жа­ние атри­бут определяет.
    Уста­нов­ка это­го зна­че­ния в false поз­во­ля­ет ини­ци­а­ли­зи­ро­вать фай­ло­вые ресур­сы без пере­за­пи­си при изме­не­ни­ях в будущем.
    Обра­ти­те вни­ма­ние, что это вли­я­ет толь­ко на содер­жи­мое; Puppet будет по-преж­не­му управ­лять вла­дель­ца и права.
    Зна­че­ние по умол­ча­нию true.
    Воз­мож­ные зна­че­ния truefalseyesno.
  • selinux_ignore_defaults — If this is set then Puppet will not ask SELinux (via matchpathcon) to supply defaults for the SELinux attributes (seluser, selrole, seltype, and selrange). In general, you should leave this set at its default and only set it to true when you need Puppet to not try to fix SELinux labels automatically. Valid values are truefalse.
  • selrange — (Property: This attribute represents concrete state on the target system.) What the SELinux range component of the context of the file should be. Any valid SELinux range component is accepted. For example s0 or SystemHigh. If not specified it defaults to the value returned by matchpathcon for the file, if any exists. Only valid on systems with SELinux support enabled and that have support for MCS (Multi-Category Security).
  • selrole — (Property: This attribute represents concrete state on the target system.) What the SELinux role component of the context of the file should be. Any valid SELinux role component is accepted. For example role_r. If not specified it defaults to the value returned by matchpathcon for the file, if any exists. Only valid on systems with SELinux support enabled.
  • seltype — (Property: This attribute represents concrete state on the target system.) What the SELinux type component of the context of the file should be. Any valid SELinux type component is accepted. For example tmp_t. If not specified it defaults to the value returned by matchpathcon for the file, if any exists. Only valid on systems with SELinux support enabled.
  • seluser — (Property: This attribute represents concrete state on the target system.) What the SELinux user component of the context of the file should be. Any valid SELinux user component is accepted. For example user_u. If not specified it defaults to the value returned by matchpathcon for the file, if any exists. Only valid on systems with SELinux support enabled.
  • show_diff — Отоб­ра­жать ли раз­ли­чия при изме­не­нии фай­ла. Зна­че­ние по умол­ча­нию true. Этот пара­метр поле­зен для фай­лов вклю­ча­ю­щих паро­ли, и дру­гие сек­рет­ные дан­ные, кото­рые в про­тив­ном слу­чае были бы вклю­че­ны в логи Puppet, и дру­гие небез­опас­ные выводы.
    Если гло­баль­ный пара­метр `show_diff` равен false, то раз­ли­чия не будут отоб­ра­жать­ся даже если далее он будет объ­яв­лен как true.
    Воз­мож­ные зна­че­ния truefalseyesno.
  • source — Источ­ник, из кото­ро­го будут копи­ро­вать­ся дан­ные в локаль­ную систе­му. Зна­че­ни­ем могут быть как URI к уда­лен­ным фай­лам, так и пол­ные пути в локаль­ной систе­ме (в т.ч. и в под­клю­чен­ных NFS и Samba шарах)
    Этот атри­бут явля­ет­ся вза­и­мо­ис­клю­ча­ю­щим с content и target.
    Доступ­ные URI могут быть puppet and file.
    Puppet URI будут брать фай­лы из встро­ен­но­го в puppet фай­ло­во­го сер­ве­ра, и как пра­ви­ло име­ют формат:
    puppet:///modules/name_of_module/filename
    При этом будут взя­ты фай­лы из моду­ля на puppet-master-е(или локаль­но­го моду­ля, при исполь­зо­ва­нии pupper apply).
    Пред­по­ло­жив, что modulepath ссы­ла­ет­ся на /etc/puppetlabs/puppet/modules, в при­ве­ден­ном выше при­ме­ре полу­чим пол­ный адрес
    /etc/puppetlabs/puppet/modules/name_of_module/files/filename.
    В отли­чие от content, атри­бут source может быть исполь­зо­ван для рекур­сив­но­го копи­ро­ва­ния дирек­то­рии, если атри­бут recurse выстав­лен как true или remote.
    Если дирек­то­рия-источ­ник сдер­жит сим­во­ли­че­скую ссыл­ку, исполь­зуй­те атри­бут links чтоб ука­зать - нуж­но ли вос­со­здать ссыл­ку, или сле­до­вать за ней.
    Воз­мож­но ука­зать несколь­ко источ­ни­ков в виде мас­си­ва. В этом слу­чае puppet будет исполь­зо­вать пер­вый суще­ству­ю­щий источ­ник. Подоб­ное может пона­до­бить­ся для исполь­зо­ва­ния раз­лич­ных фай­лов на раз­ных системах :

  • source_permissions — Как puppet дол­жен ско­пи­ро­вать пра­ва, вла­дель­ца и груп­пу, ори­ги­наль­но­го source целе­во­му file, когда эти зна­че­ния явно не ука­за­ны соот­вет­ству­ю­щи­ми атри­бу­та­ми. (Во всех слу­ча­ях явные раз­ре­ше­ния будут иметь приоритет.)
    Воз­мож­ные значения:
    • use (the default) застав­ля­ет Puppet при­ме­нять вла­дель­ца, груп­пу и раз­ре­ше­ния source на все обра­ба­ты­ва­е­мые файлы.
    • use_when_creating зада­вать раз­ре­ше­ния в соот­вет­ствии с sourceтоль­ко при созда­нии фай­лов; пра­ва уже суще­ству­ю­щих фай­лов изме­нять­ся не будут.
    • ignore не насле­до­вать пра­ва от source при обра­бот­ке фай­лов. При созда­нии новых фай­лов без явных раз­ре­ше­ний, пове­де­ние при полу­че­нии раз­ре­ше­ний будут зави­сеть от кон­крет­ной плат­фор­мы. На POSIX, Puppet будет исполь­зо­вать зна­че­ние umask поль­зо­ва­те­ля, от кото­ро­го он запус­ка­ет­ся. На Windows, Puppet будет исполь­зо­вать DACL по умол­ча­нию ассо­ци­и­ро­ван­ный с поль­зо­ва­те­лем от кото­ро­го он запускается.
  • sourceselect — Зна­че­ние по умол­ча­нию - first.
    При рекур­сив­ном копи­ро­ва­нии дирек­то­рий, в слу­чае если источ­ни­ков несколь­ко - по умол­ча­нию копи­ру­ют­ся фай­ли из пер­во­го доступ­но­го источ­ни­ка. Если это­му пара­мет­ру задать зна­че­ние all, то копи­ро­вать­ся будут фай­лы из всех доступ­ных источников.
    Если ука­зан­ный файл суще­ству­ет в более чем одно­го источ­ни­ка, будет исполь­зо­вать­ся вер­сия из само­го ран­не­го источ­ни­ка в списке.
    Доступ­ные зна­че­ния firstall.
  • type — (Property: This attribute represents concrete state on the target system.)
    A read-only state to check the file type.

package

В зави­си­мо­сти от систе­мы кли­ен­та, уста­нов­щик паке­тов выби­ра­ет­ся авто­ма­ти­че­ски и име­ет опре­де­лён­ные свой­ства, пол­ное опи­са­ние на сай­те docs.puppetlabs.com(англ.).

  • name — имя паке­та. Если не задан, puppet по умол­ча­нию счи­ты­ва­ет из заго­лов­ка ресурса.
  • ensure — состо­я­ние дан­но­го паке­та, рав­но present (или installed, то есть пакет уста­нов­лен), absent (отсут­ству­ет), latest (уста­нов­лен и явля­ет­ся послед­ней вер­си­ей), purgedheld (толь­ко для неко­то­рых уста­нов­щи­ков пакетов).
  • provider — мож­но вруч­ную ука­зать уста­нов­щи­ка паке­тов из воз­мож­ных aix, appdmg, apple, apt, aptitude, aptrpm, blastwave, dpkg, fink, freebsd, gem, hpux, macports, msi, nim, openbsd, pacman, pip, pkg, pkgdmg, pkgutil, portage, ports, portupgrade, rpm, rug, sun, sunfreeware, up2date, urpmi, yum (по умол­ча­нию для operatingsystem == fedora, centos, redhat), zypper.
  • source — допол­ни­тель­но мож­но ука­зать где взять пакет, это может быть URL или как в управ­ле­нии фай­ла­ми адрес puppet:///.

yumrepo

Поз­во­ля­ет управ­лять под­клю­чен­ны­ми репо­зи­то­ри­я­ми, посред­ством изме­не­ния /etc/yum.conf. Боль­шин­ство пара­мет­ров ана­ло­гич­ны man yum.conf.

  • baseurl — URL дан­но­го репо­зи­то­рия. Зна­че­ние absent уда­лит дан­ные репо­зи­то­рий из фай­ла пол­но­стью. Воз­мож­ные зна­че­ния absent и по мас­ке /.*/.
  • cost — cто­и­мость дан­но­го репо­зи­то­рия. Зна­че­ние absent уда­лит дан­ные репо­зи­то­рий из фай­ла пол­но­стью. Воз­мож­ные зна­че­ния absent и по мас­ке /\d+/.
  • descr
  • enabled
  • enablegroups
  • exclude
  • failovermethod
  • gpgcheck
  • gpgkey
  • http_caching
  • include
  • includepkgs
  • keepalive
  • metadata_expire
  • mirrorlist
  • name
  • priority
  • protect
  • proxy
  • proxy_password
  • proxy_username
  • timeout

service

Поз­во­ля­ет управ­лять систем­ны­ми службами.

  • enable — вклю­че­на ли служ­ба на авто­за­груз­ку, рав­но truefalsemanual.
  • ensure — теку­щее состо­я­ние, рав­но stopped (или false), running (или true).
  • start, stop, restart, status — поз­во­ля­ет задать соот­вет­ствен­но коман­ды на старт, оста­нов­ку, пере­за­пуск и про­вер­ку ста­ту­са вруч­ную. Задан­ные коман­ды будут исполь­зо­вать­ся при изме­не­нии ста­ту­са с помо­щью коман­ды ensure. Для атри­бу­та statusкоман­да долж­на воз­вра­щать 0 если служ­ба запу­ще­на и рабо­та­ет без оши­бок, и воз­вра­щать нену­ле­вое зна­че­ние в осталь­ных случаях.
  • binary — путь к служ­бе (демо­ну). Исполь­зу­ет­ся толь­ко в систе­мах, кото­рые не под­дер­жи­ва­ют init скрипт.

exec

Поз­во­ля­ет выпол­нять кон­соль­ные коман­ды, скрип­ты непо­сред­ствен­но при запус­ке puppet.

  • command — коман­да для запус­ка. Если опу­ще­на, рав­на заго­лов­ку. Адрес команд дол­жен быть задан пол­но­стью, если не про­пи­са­ны пути для поис­ка в атри­бу­те path.
  • path — пути для поис­ка команд. Мож­но задать сра­зу несколь­ко раз­де­ляя их двое­то­чи­ем ':'. Что­бы не ука­зы­вать этот пара­метр у каж­до­го ресур­са exec, мож­но задать этот пара­метр по умол­ча­нию в самом нача­ле мани­фе­ста, напри­мер, так: Exec { path => '/usr/bin:/bin:/usr/sbin:/sbin' }.
  • cwd — теку­щая дирек­то­рия (пере­мен­ная окру­же­ния $PWD в bash). Если дирек­то­рия не суще­ству­ет, коман­да не запустится.
  • creates — файл, кото­рый созда­ёт коман­да. Если атри­бут задан, то коман­да не запу­стит­ся, если файл существует.
  • environment — любые дру­гие пере­мен­ные окру­же­ния, кото­рые необ­хо­ди­мя для запус­ка коман­ды. Име­ет пре­иму­ще­ство над ари­бу­том path, то есть дан­ную пере­мен­ную мож­но переопределить.
  • group, user — груп­па и поль­зо­ва­тель с пра­ва­ми кото­рых выпол­нять дан­ную команду.
  • logoutput — вклю­чать ли вывод коман­ды в лог, рав­но truefalse и on_failure (толь­ко в слу­чае выхо­да с ошибкой).
  • onlyif — зада­ёт про­ве­роч­ную коман­ду. Основ­ная коман­да (атри­бут command) будет выпол­не­на, толь­ко если эта коман­да выпол­нит­ся без оши­бок (код выхо­да будет 0), например:

При этом onlyif может про­ве­рять мас­сив команд и выпол­нить основ­ную коман­ду толь­ко тогда, когда все коман­ды мас­си­ва выполнятся:

cron

Поз­во­ля­ет управ­лять пла­ни­ров­щи­ком cron в Linux. К сожа­ле­нию, уда­лить или изме­нить создан­ные вами вруч­ную зада­ния не смо­жет, так как опре­де­ля­ет свои зада­ния по встав­ля­е­мо­му перед ними комментарию.

  • command — коман­да, кото­рую будет выпол­нять cron.
  • ensure — управ­ля­ет нали­чи­ем зада­ния, рав­но present или absent.
  • hour — час, рав­но от 0 до 23. Вре­мя здесь и далее в типе cron может быть зада­но как '2', ['2-4'], ['2,4']'*/2' (послед­нее если толь­ко ваш cron под­дер­жи­ва­ет подоб­ное ука­за­ние). По умол­ча­нию рав­но *.
  • minute — мину­та, рав­но от 0 до 59.
  • month — месяц, рав­но от 1 до 12 или от january до december.
  • weekday — день неде­ли, рав­но от 0 до 7 (0 и 7 — это вос­кре­се­нье) или от monday до sunday.
  • name — имя зада­ния. Если не задан, puppet по умол­ча­нию счи­ты­ва­ет из заго­лов­ка ресурса.
  • user — поль­зо­ва­тель, в зада­ния кото­ро­го оно будет включено.

schedule

Опре­де­ля­ет рас­пи­са­ния отра­бот­ки ресур­сов. К ресур­су рас­пи­са­ние может быть при­сво­е­но с помо­щью одно­имен­но­го пара­мет­ра (schedule) В насто­я­щее вре­мя, рас­пи­са­ния могут исполь­зо­вать­ся толь­ко для того, что­бы предот­вра­тить при­ме­не­ние ресур­са. Они не поз­во­ля­ют выпол­нять­ся ресур­су вне задан­ных рамок и не могут назна­чить вре­мя когда ресурс будет запу­щен (для это­го необ­хо­ди­мо иполь­зо­вать scheduled_task или cron).
Каж­дый раз, когда puppet отра­ба­ты­ва­ет мани­фе­сты, она про­ве­ря­ет, попа­да­ет ли теку­щий момент вре­ме­ни в ука­зан­ное рас­пи­са­ние. Если попа­да­ет, то ресурс отра­бо­та­ет, ина­че будет про­сто про­пу­щен. При этом puppet НЕ создаст себе ника­ко­го зада­ния отра­бо­тать ресурс в буду­щем. То есть если создать рас­пи­са­ние «Х» ска­жем еже­днев­но с 12:20 до 12:30, а по умол­ча­нию puppet при­ме­ня­ет кон­фи­гу­ра­цию раз в 30 минут, а ком­пью­тер был вклю­чен в 12:10… то сле­ду­ю­щий раз puppet отра­бо­та­ет в 12:40 и все ресур­сы, кото­рым было назна­че­но рас­пи­са­ние «Х», про­сто не сра­бо­та­ют. Или puppet будет отра­ба­ты­вать какой-нибудь ресурс про­дол­жи­тель­ное вре­мя (загру­жать фай­лы или т. п.) с 12:15 по 12:35, и дан­ное рас­пи­са­ние тоже «выпа­дет» и может вооб­ще нико­гда не сработает.
Поэто­му, луч­ше исполь­зо­вать широ­кие рас­пи­са­ния… (с интер­ва­лом в несколь­ко часов). Напри­мер, что­бы запус­кать зада­ние 1 раз в сут­ки меж­ду 2 и 4 часа­ми утра надо задать сле­ду­ю­щее расписание:

  • period — Пери­од повто­ре­ния. Рав­но hourly, daily, weekly, monthly, never (нико­гда, то есть пара­метр repeat задаст сколь­ко все­го раз выпол­нит­ся дан­ный ресурс).
  • periodmatch — Кон­кре­ти­зи­ру­ет пара­метр period. Рав­но number (когда учи­ты­ва­ют­ся коли­че­ство сра­ба­ты­ва­ний в тече­ние опре­де­лён­но­го пери­од, напри­мер, в час) или distance (когда учи­ты­ва­ет­ся сра­ба­ты­ва­ние через опре­де­лён­ный период).
  • range — Интер­вал вре­ме­ни суток, в кото­рый дей­ству­ет рас­пи­са­ние. Зада­ёт­ся как «HH:MM:SS — HH:MM:SS» (кавыч­ки тоже нуж­ны), мину­ты и секун­ды могут быть опущены.
  • repeat — Как часто сра­ба­ты­вать в ука­зан­ный пери­од. Долж­но зада­вать­ся целым чис­лом. По умол­ча­нию: 1.

user

Поз­во­ля­ет управ­лять пользователями.

  • name — Если не задан, puppet по умол­ча­нию счи­ты­ва­ет из заго­лов­ка ресурса.
  • uid — UID поль­зо­ва­те­ля. Дол­жен зада­вать­ся циф­рой, если опу­ще­но, то зада­ёт­ся авто­ма­ти­че­ски (или оста­ёт­ся без изме­не­ний, если поль­зо­ва­тель уже существует).
  • ensure — про­вер­ка ста­ту­са поль­зо­ва­те­ля, рав­но present (суще­ству­ет), absent (отсут­ству­ет), role.
  • gid — Основ­ная груп­па поль­зо­ва­те­ля. Зада­ёт­ся по име­ни или GID.
  • groups — Мас­сив допол­ни­тель­ных групп поль­зо­ва­те­ля, через запя­тую. !!!Не надо вклю­чать груп­пу, задан­ную как gid.
  • home — Домаш­няя дирек­то­рия пользователя.
  • shell — Обо­лоч­ка поль­зо­ва­те­ля (напри­мер, /bin/bash)
  • managehome — Созда­вать ли домаш­нюю дирек­то­рию при созда­нии поль­зо­ва­те­ля; Если не ука­за­но true - вам при­дет­ся созда­вать ее вруч­ную. true или false

group

Поз­во­ля­ет управ­лять груп­па­ми пользователей.

  • name — Если не задан, puppet по умол­ча­нию счи­ты­ва­ет из заго­лов­ка ресурса.
  • gid — GID груп­пы. Дол­жен зада­вать­ся циф­рой, если опу­ще­но, то зада­ёт­ся авто­ма­ти­че­ски (или оста­ёт­ся без изме­не­ний, если груп­па уже существует).
  • ensure — про­вер­ка ста­ту­са груп­пы, рав­но present (суще­ству­ет), absent (отсут­ству­ет).

Модули

Моду­ли — это воз­мож­ность исполь­зо­вать клас­сы и функ­ции в puppet. Модуль — это все­го лишь дирек­то­рия с пред­опре­де­нён­ной струк­ту­рой ката­ло­гов и фай­лов. Выгля­дит струк­ту­ра моду­ля при­мер­но так: {имя_модуля}/

Обра­ще­ние в коде puppet к клас­сам будет выгля­деть как:

Для того, что­бы модуль вооб­ще зара­бо­тал доста­точ­но иметь пап­ку с име­нем моду­ля, пап­ку с мани­фе­ста­ми и началь­ным мани­фе­стом init.pp.
По ана­ло­гии выстра­и­ва­ем под_под_классы и под_под_…под_классы, пока не надоест.
Тре­бу­ет­ся, что­бы в каж­дом из фай­лов «класс1» … «под_класс1» был один и толь­ко один класс с соот­вет­ству­ю­щим име­нем: «имя_модуля::класс1» … «имя_модуля::класс1::под_класс1». При этом файл init.pp дол­жен содер­жать класс с име­нем «имя_модуля».
Полу­чить доступ к фай­лам моду­ля мож­но, напри­мер, по адре­су puppet:///modules/имя_модуля/.
Из дирек­то­рии lib мож­но запус­кать испол­ня­е­мые фай­лы с Ruby-кодом, что­бы рас­ши­рить воз­мож­но­сти Puppet и Facter (постав­щи­ка переменных).

Environments

Окру­же­ния (environments) нуж­ны для пол­но­го раз­де­ле­ния кон­фи­гу­ра­ций. У каж­до­го окру­же­ния свои моду­ли и мани­фе­сты. Это мож­но срав­нить с исполь­зо­ва­ни­ем раз­ных сер­ве­ров puppet master.

История

  • До вер­сии 3.5 для ука­за­ния окру­же­ний исполь­зо­ва­лись толь­ко пере­мен­ные manifest и modulepath («config file environments», в про­ти­во­по­лож­ность «directory environments», кото­рые появи­лись в вер­сии 3.5) 
  • С вер­сии 3.6 «config file environments» устарели 
  • В вер­сии 3.7 «directory environments» вклю­че­ны по умол­ча­нию в Puppet Enterprise, но не в Open Source
  • С вер­сии 4.0 в слу­чае неис­поль­зо­ва­ния окру­же­ний будет выда­вать­ся предупреждение.

Если не ука­за­но, с вер­сии 4.0 будет исполь­зо­вать­ся окру­же­ние production.

Именование

Имя окру­же­ния долж­но состо­ять из строч­ных букв, цифр и под­чёр­ки­ва­ния, начи­нать­ся с бук­вы. Нель­зя исполь­зо­вать main, master, agent, user . При­мер имён окру­же­ний: production и testing.

Подключение

В вер­си­ях 3.5, 3.6, 3.7 Open Source, 3.8 для исполь­зо­ва­ния «directory environments» про­пи­сы­ва­ем в сек­цию [main] или [master] фай­ла /etc/puppet/puppet.conf:

В более новых вер­си­ях ука­зы­вать ниче­го не нужно.

В кон­фи­гу­ра­ции аген­та (сек­ция [agent] в фай­ле /etc/puppet/puppet.conf) надо ука­зать, какое окру­же­ние он будет исполь­зо­вать, например:

Использование

После под­клю­че­ния, исполь­зу­ют­ся мани­фе­сты из ката­ло­га окру­же­ния, напри­мер, /etc/puppet/environments/production/manifests/.

В мани­фе­стах мож­но исполь­зо­вать пере­мен­ную $environment с име­нем теку­ще­го окружения.

___________________________________________________________

 

-----------------------------------------------------------------------------------------------------

Настройка Puppet в Unix/Linux

Настрой­ка puppet-agent-а в CentOS/Fedora/RedHat

Так же, настра­и­ва­ем puppet-agent-ы:

# cat /etc/puppetlabs/puppet/puppet.conf

# This file can be used to override the default puppet settings.
# See the following links for more details on what settings are available:
# - https://docs.puppetlabs.com/puppet/latest/reference/config_important_settings.html
# - https://docs.puppetlabs.com/puppet/latest/reference/config_about_settings.html
# - https://docs.puppetlabs.com/puppet/latest/reference/config_file_main.html
# - https://docs.puppetlabs.com/puppet/latest/reference/configuration.html
#
[main]
logdir=/var/log/puppet
vardir=/var/lib/puppet
ssldir=/var/lib/puppet/ssl
rundir=/var/run/puppet
factpath=$vardir/lib/facter
#templatedir=$confdir/templates
#
certname = puppet-agent
server = puppet-server
#environment = production
#runinterval = 5m
#1h
[agent]
environment = production
show_diff = true
runinterval = 5m

 

Вы може­те изме­нить зна­че­ние runinterval в зави­си­мо­сти от тре­бо­ва­ния, вы може­те уста­но­вить зна­че­ние в секун­дах; Это опре­де­ля­ет, как дол­го агент дол­жен ждать меж­ду дву­мя catalog запросами.

Пере­за­пус­ка­ем клиент:

 #·service puppet restart
В пер­вый раз, когда puppet-agent запус­ка­ет­ся, он отпра­вит запрос на под­пись сер­ти­фи­ка­та в puppet-server. Преж­де чем Puppet-server смо­жет вза­и­мо­дей­ство­вать с puppet-agent-ом и управ­лять им, он дол­жен под­пи­сать сер­ти­фи­кат кон­крет­но­го агента.

Мож­но посмот­реть неко­то­рые пути к кон­фи­гам сле­ду­ю­щим образом:

# puppet agent --configprint rundir
/var/run/puppet
# puppet agent --configprint pidfile
/var/run/puppet/agent.pid

Настрой­ка puppet-server в CentOS/Fedora/RedHat

Теперь как уже име­ет­ся puppet-server (он же, puppetmaster) и ноды с puppet-agent-ами, мож­но кое-что настро­ить еще.

vim /etc/puppetlabs/puppet/puppet.conf

# This file can be used to override the default puppet settings.
# See the following links for more details on what settings are available:
# - https://docs.puppetlabs.com/puppet/latest/reference/config_important_settings.html
# - https://docs.puppetlabs.com/puppet/latest/reference/config_about_settings.html
# - https://docs.puppetlabs.com/puppet/latest/reference/config_file_main.html
# - https://docs.puppetlabs.com/puppet/latest/reference/configuration.html
[master]
vardir = /opt/puppetlabs/server/data/puppetserver
logdir = /var/log/puppetlabs/puppetserver
rundir = /var/run/puppetlabs/puppetserver
pidfile = /var/run/puppetlabs/puppetserver/puppetserver.pid
codedir = /etc/puppetlabs/code
dns_alt_names = puppet-server

[main]
certname = puppet-server
server = puppet-server
environment = production
runinterval = 5m

Пере­за­пус­ка­ем puppetmaster:

# service puppetserver restart
И так, что­бы про­смот­реть все непод­пи­сан­ные запро­сы сер­ти­фи­ка­та, выпол­ни­те на puppet-server-е, сле­ду­ю­щую команду:
# puppet cert list
 Если вы настро­и­ли свой puppet-agent, вы уви­ди­те один запрос. Он будет выгля­деть при­мер­но так:
"puppet-agent" (SHA256) B2:47:29:88:7F:94:EA:CC:12:D5:E2:DB:A0:D1:C3:E8:DA:2A:0F:49:DB:08:7A:DC:14:89:27:EA:5D:D7:19:57
Что­бы под­пи­сать сер­ти­фи­кат, исполь­зуй­те команду:
# puppet cert sign puppet-agent
Signing Certificate Request for:
"puppet-agent.localdomain" (SHA256) B2:47:29:88:7F:94:EA:CC:12:D5:E2:DB:A0:D1:C3:E8:DA:2A:0F:49:DB:08:7A:DC:14:89:27:EA:5D:D7:19:57
Notice: Signed certificate request for puppet-agent.localdomain
Notice: Removing file Puppet::SSL::CertificateRequest puppet-agent.localdomain at '/etc/puppetlabs/puppet/ssl/ca/requests/puppet-agent.localdomain.pem'

Где, puppet-agent-  это назва­ние ноды.

Puppet-master теперь может свя­зы­вать­ся и управ­лять узлом, кото­ро­му при­над­ле­жит под­пи­сан­ный сертификат.

Если вы хоти­те под­пи­сать все теку­щие запро­сы, исполь­зуй­те опцию -all, напри­мер:

  # puppet cert sign --all
 Вы може­те уда­лить хост из Puppet или пере­стро­ить хост, а затем доба­вить его обрат­но в Puppet. В этом слу­чае вы долж­ны уда­лить сер­ти­фи­кат хоста с Puppet-а. Для это­го вы може­те использовать:
#·puppet cert clean your_hostname
 Где, your_hostname — Хост­нейм ноды puppet-agent-а.

PS:  Когда сер­вер уда­ля­ет уже под­пи­сан­ный сер­ти­фи­кат для аген­та, вы долж­ны уда­лить сер­ти­фи­ка­ты из пап­пет-аген­та сле­ду­ю­щим образом:

 # rm -rf /var/lib/puppet/ssl/*

Что­бы про­смот­реть все запро­сы, под­пи­сан­ные и непод­пи­сан­ные, выпол­ни­те сле­ду­ю­щую команду:

#·puppet cert list --all
+ "puppet-agent" (SHA256) 32:D4:E0:D6:0C:23:C3:62:07:BE:25:23:83:A0:79:E7:A8:7F:D0:AD:ED:1E:12:BE:2A:7E:AF:39:58:A7:D4:26
+ "puppet-agent.localdomain" (SHA256) 67:47:08:E1:44:23:FC:EA:D1:89:A1:DD:95:28:27:85:3A:EB:9B:EB:7B:48:1D:C3:27:A9:4B:C7:92:D2:EE:C8
+ "puppet-server" (SHA256) 8C:73:D1:FC:74:CA:96:B3:4B:92:7A:A1:7D:5A:3F:06:1B:83:F9:84:12:ED:83:0A:B1:94:A9:D2:14:22:7F:AE (alt names: "DNS:puppet", "DNS:puppet-server")

Про­смот­ри­те отпе­ча­ток серт­фи­ка­та клиента

# puppet agent --fingerprint

Мож­но посмот­реть неко­то­рые пути к кон­фи­гам сле­ду­ю­щим образом:

# puppet master --configprint rundir
/var/run/puppet
# puppet master --configprint pidfile
/var/run/puppet/master.pid
Каж­дый раз добав­лять сер­ти­фи­ка­ты для новых нод — это не труъ! Мож­но сде­лать так, что­бы сер­вер авто­ма­ти­че­ски добав­лял новые ноды в себе в листинг добав­лял их сер­ти­фи­кат себе на сер­вер. Для это­го, смот­рим где хра­нит­ся конфиг:
$ puppet config print --section master confdir
 Обыч­но, этот путь находится:
/etc/puppet

или

/etc/puppetlabs/puppet/

У меня  — /etc/puppetlabs/puppet/ и в этой дирек­то­рии, откры­ва­ем (созда­ем) файл:

# vim·/etc/puppetlabs/puppet/autosign.conf
В него про­пи­сы­ва­ем домен­ные име­на кото­рые будут добав­лять­ся авто­ма­ти­че­ски, например:
www.test.t
*.test.t
*

И после чего, все будет выпол­нят­ся в авто­ма­ти­че­ском режиме.

 

Настройка hiera на puppet-server-е

Преж­де все­го, я бы реко­мен­до­вал, — настро­ить хиеру (нуж­на что­бы опре­де­лять пере­мен­ные), для это­го, — открываем:

# vim·/etc/puppetlabs/puppet/hiera.yaml
Или
# vim /etc/puppet/hiera.yaml
И при­во­дим его к сле­ду­ю­ще­му виду:
 ---
:backends:
- yaml
- json
#:yaml:
# datadir is empty here, so hiera uses its defaults:
#- /etc/puppetlabs/code/environments/%{environment}/hieradata on *nix
# - %CommonAppData%\PuppetLabs\code\environments\%{environment}\hieradata on Windows
# When specifying a datadir, make sure the directory exists.
# :datadir:
:yaml:
#:datadir: "/etc/puppetlabs/code/environments/%{::environment}/hieradata"
:datadir: "/etc/puppetlabs/code/environments/production/hieradata"
:json:
:datadir: "/etc/puppetlabs/code/environments/%{::environment}/hieradata"
:hierarchy:
- "node/%{::trusted.certname}"
- "nodes/%{::fqdn}"
- "roles/%{::role}"
- "osfamily/%{::osfamily}"
- "virtual/%{::virtual}"
#- "default"
:logger: console
:merge_behavior: native
:deep_merge_options: {}

Созда­ем сим­во­ли­че­скую ссылку:

# ln -s /etc/puppetlabs/puppet/hiera.yaml /etc/hiera.yaml
 Создам для при­ме­ра хиеру-файл:
vim /etc/puppetlabs/code/environments/production/hieradata/nodes/puppet-server.yaml

и про­пи­сы­ва­ем:

zabbix::host: 'hiera_host.com'
zabbix::agent::hostname:
- test.machine-hiera.com
zabbix_ip: 'hiera.com'

И смот­рим что вышло:

#·hiera -d zabbix::agent::hostname ::fqdn=puppet-server
DEBUG: 2017-10-13 02:49:41 +0100: Hiera YAML backend starting
DEBUG: 2017-10-13 02:49:41 +0100: Looking up zabbix::agent::hostname in YAML backend
DEBUG: 2017-10-13 02:49:41 +0100: Looking for data source nodes/puppet-server
DEBUG: 2017-10-13 02:49:41 +0100: Found zabbix::agent::hostname in nodes/puppet-server
["test.machine-hiera.com"]

 

Или:

# hiera -d zabbix_ip ::fqdn=puppet-server
DEBUG: 2017-10-13 02:50:15 +0100: Hiera YAML backend starting
DEBUG: 2017-10-13 02:50:15 +0100: Looking up zabbix_ip in YAML backend
DEBUG: 2017-10-13 02:50:15 +0100: Looking for data source nodes/puppet-server
DEBUG: 2017-10-13 02:50:15 +0100: Found zabbix_ip in nodes/puppet-server
hiera.com

Видим что рабо­та­ет все.

 

Работа с Puppet в Unix/Linux

Для нача­ла, мож­но создать про­стой мани­фест, для это­го созда­ем файл (на сто­роне сер­ве­ра с паппет):

 #·touch /etc/puppetlabs/code/environments/production/manifests/site.pp
 Откры­ва­ем создан­ный файл и прописываем:
file {'/tmp/example-ip': # resource type file and filename
ensure => present, # make sure it exists
mode => '0644', # file permissions
content => "Here is my Public IP Address: ${ipaddress_eth0}.\n", # note the ipaddress_eth0 fact
}

Теперь сохра­ни­те и вый­ди­те.  Вы може­те либо дождать­ся, когда агент авто­ма­ти­че­ски про­ве­дет про­вер­ку с масте­ром, либо вы може­те запу­стить коман­ду (на сто­роне клиента):

# puppet agent --test
Info: Using configured environment 'production'
Info: Retrieving pluginfacts
Info: Retrieving plugin
Info: Caching catalog for puppet-agent.localdomain
Info: Applying configuration version '1503447019'
Notice: /Stage[main]/Main/File[/tmp/example-ip]/ensure: defined content as '{md5}3984f4d8223482bb14254a625988f1f3'
Notice: Applied catalog in 0.02 seconds

Видим что пап­пет-агент отра­бо­тал мани­фест кото­рый создали.

PS: Для деба­га, исполь­зуй­те «--debug» опцию:

# puppet agent --test --debug
 Но давай­те про­ве­рим что получилось:
#·cat /tmp/example-ip

И вывод у меня будет следующим:

 Here is my Public IP Address: 192.168.13.207.

Если вы хоти­те запус­кать мани­фест толь­ко для неко­то­рых нод, то сто­ит опре­де­лить узел в мани­фе­сте. Открываем:

vim /etc/puppetlabs/code/environments/production/manifests/site.pp

и про­пи­сы­ва­ем:

node 'your_node_1', 'your_node_2', 'puppet-agent.localdomain' { # applies to ns1 and ns2 nodes
file {'/tmp/dns': # resource type file and filename
ensure => present, # make sure it exists
mode => '0644',
content => "Only DNS servers get this file.\n",
}
}
node default {} # applies to nodes that aren't explicitly defined
И тогда толь­ко для ука­зан­но­го спис­ка, будет выпол­нят­ся манифест.

 

Так же, мож­но выпол­нить мани­фест рука­ми, для это­го слу­жит команда:

 #·puppet apply /path_to_manifest/your_manifest_name.pp

Добавление модулей

ПРИМЕР 1 — Добав­ле­ние огра­ни­чен­но­го пользователя 

Мож­но огра­ни­чить исполь­зо­ва­ния puppet по поль­зо­ва­те­лю, для это­го на puppetmaster-е (пап­пет сер­ве­ре), созда­дим пап­ку для моду­ля и перей­дем в нее:

# ·mkdir /etc/puppetlabs/code/modules/accounts && cd $_

Создай­те сле­ду­ю­щие ката­ло­ги, кото­рые необ­хо­ди­мы для функ­ци­о­ни­ро­ва­ния модуля:

#·mkdir {examples,files,manifests,templates}

Где:

  • examples — Дирек­то­рия для тести­ро­ва­ния моду­ля локально.
  • files — Пап­ка, кото­рая содер­жит любые ста­ти­че­ские фай­лы, кото­рые могут потре­бо­вать­ся для отре­дак­ти­ро­ва­ния или добавления.
  • manifests — Фол­дер, в кото­ром содер­жит­ся фак­ти­че­ский puppet код для моду­ля (т.е мани­фест действий).
  • templates — Содер­жит любые не ста­ти­че­ские фай­лы, кото­рые могут потребоваться.

Перей­ди­те в ката­лог manifests и создай­те свой пер­вый класс под назва­ни­ем init.pp. Все моду­ли тре­бу­ют, что­бы файл init.pp исполь­зо­вал­ся в каче­стве основ­но­го фай­ла опре­де­ле­ния модуля:

#·cd manifests && vim·/etc/puppetlabs/code/modules/accounts/manifests/init.pp

И встав­ля­ем в него:

class accounts {
include accounts::groups
$rootgroup = $osfamily ? {
'Debian' => 'sudo',
'RedHat' => 'wheel',
default => warning('This distro not supported by Accounts module'),
}
user { 'vagrant':
ensure => present,
home => '/home/vagrant',
shell => '/bin/bash',
managehome => true,
gid => 'vagrant',
groups => "$rootgroup",
password => '$1$TkCXLpmE$9flKgFkEQLmSauT94f4Ph0'
}
}

При­ми­те во вни­ма­ние, vagrant — это поль­зо­ва­тель на puppet-server-е, кото­рый уже име­ет­ся в систе­ме. И, password — это хеш от паро­ля (для поль­зо­ва­те­ля vagrant) и его мож­но полу­чить, выполнив:

#·openssl passwd -1
Password:
Verifying - Password:
$1$TkCXLpmE$9flKgFkEQLmSauT94f4Ph0

Созда­ем еще один файл:

# vim·/etc/puppetlabs/code/modules/accounts/manifests/groups.pp
И добавь­те сле­ду­ю­щее содержимое:
class accounts::groups {
group { 'vagrant':
ensure => present,
}
}
Про­ве­ря­ем валид­ность файла:
puppet parser validate /etc/puppetlabs/code/modules/accounts/manifests/init.pp
Откры­ва­ем:
# vim /etc/puppetlabs/code/modules/accounts/examples/init.pp
И про­пи­сы­ва­ем:
include accounts
Давай­те про­те­сти­ру­ем модуль:
# puppet apply --noop /etc/puppetlabs/code/modules/accounts/examples/init.pp
Полу­ча­ем вывод:
Notice: Compiled catalog for puppet-server in environment production in 0.08 seconds
Notice: /Stage[main]/Accounts/User[vagrant]/home: current_value /home/vagrant, should be /home/username (noop)
Notice: /Stage[main]/Accounts/User[vagrant]/gid: current_value 1000, should be username (noop)
Notice: Class[Accounts]: Would have triggered 'refresh' from 2 events
Notice: Stage[main]: Would have triggered 'refresh' from 1 events
Notice: Applied catalog in 0.05 seconds
При­ме­ня­ем изменения:
# puppet apply /etc/puppetlabs/code/modules/accounts/examples/init.pp
И полу­ча­ем вывод:
Notice: Compiled catalog for puppet-server in environment production in 0.06 seconds
Notice: /Stage[main]/Accounts/User[vagrant]/password: changed password
Notice: /Stage[main]/Accounts/User[vagrant]/groups: groups changed 'vagrant' to ['vagrant', 'wheel']
Notice: Applied catalog in 0.05 seconds
Как вы уже поня­ли, я при­ме­нил создан­ный модуль на сер­ве­ре с пап­пет и он при­ме­нил все то, что я опи­сы­вал ранее.

 

ПРИМЕР 2 — Редак­ти­ро­ва­ние SSH настроек 

Копи­ру­ем конфиг-файл:

# cp -r /etc/ssh/sshd_config /etc/puppetlabs/code/modules/accounts/files
 Откры­ва­ем кон­фиг и пра­вим строку:
PermitRootLogin no
Созда­ем манифест:
# vim·/etc/puppetlabs/code/modules/accounts/manifests/ssh.pp
про­пи­сы­ва­ем в него:
class accounts::ssh {
file { '/etc/ssh/sshd_config':
ensure => present,
source => 'puppet:///modules/accounts/sshd_config',
}
}

Откры­ва­ем файл:

# vim·/etc/puppetlabs/code/modules/accounts/manifests/init.pp

И добав­ля­ем в него:

include accounts::ssh

Долж­но вый­ти, что-то типа:

class accounts {
include accounts::groups
include accounts::ssh
$rootgroup = $osfamily ? {
'Debian' => 'sudo',
'RedHat' => 'wheel',
default => warning('This distro not supported by Accounts module'),
}
user { 'vagrant':
ensure => present,
home => '/home/vagrant',
shell => '/bin/bash',
managehome => true,
gid => 'vagrant',
groups => "$rootgroup",
password => '$1$TkCXLpmE$9flKgFkEQLmSauT94f4Ph0'
}
}

Сно­во, про­ве­ря­ем валидацию:

# puppet parser validate /etc/puppetlabs/code/modules/accounts/manifests/ssh.pp

Выпол­ня­ем тест:

# puppet apply --noop /etc/puppetlabs/code/modules/accounts/examples/init.pp
Notice: Compiled catalog for puppet-server in environment production in 0.47 seconds
Notice: /Stage[main]/Accounts::Ssh/File[/etc/ssh/sshd_config]/content: current_value {md5}0440a9608de01c4fa1c1dd6301b568ec, should be {md5}4ffaa0befebc4ea61f5353b0a21cd7c7 (noop)
Notice: /Stage[main]/Accounts::Ssh/Service[sshd]: Would have triggered 'refresh' from 1 events
Notice: Class[Accounts::Ssh]: Would have triggered 'refresh' from 2 events
Notice: Stage[main]: Would have triggered 'refresh' from 1 events
Notice: Applied catalog in 0.05 seconds

При­ме­ня­ем:

# puppet apply /etc/puppetlabs/code/modules/accounts/examples/init.pp
Notice: Compiled catalog for puppet-server in environment production in 0.50 seconds
Notice: /Stage[main]/Accounts::Ssh/File[/etc/ssh/sshd_config]/content: content changed '{md5}0440a9608de01c4fa1c1dd6301b568ec' to '{md5}4ffaa0befebc4ea61f5353b0a21cd7c7'
Notice: /Stage[main]/Accounts::Ssh/Service[sshd]: Triggered 'refresh' from 1 events
Notice: Applied catalog in 0.18 seconds

 

ПРИМЕР 3 — Добав­ле­ние и настрой­ка IPTABLES ===-

В этом раз­де­ле я пока­жу как мож­но настра­и­вать пра­ви­ла бранд­мау­э­ра с помо­щью iptables. Одна­ко по умол­ча­нию эти пра­ви­ла не будут сохра­нять­ся при пере­за­груз­ке. Что­бы это­го избе­жать, перед тем, как про­дол­жить, уста­но­ви­те соот­вет­ству­ю­щий пакет на каж­дом узле (puppetmaster- е, puppet-агенте):

Для Debian/Ubuntu:

 # apt install iptables-persistent
Для CentOS 7:
 # systemctl stop firewalld && systemctl disable firewalld
# yum install iptables-services -y

Идем даль­ше, нуж­но уста­но­вить модуль на puppetmaster-е, для это­го слу­жит сле­ду­ю­щая команда:

# puppet module install puppetlabs-firewall
Notice: Preparing to install into /etc/puppetlabs/code/environments/production/modules
Notice: Downloading from https://forgeapi.puppet.com
Notice: Installing -- do not interrupt
/etc/puppetlabs/code/environments/production/modules
└── puppetlabs-firewall (v1.9.0)

Вывод гово­рит что модуль уста­но­вил­ся в /etc/puppetlabs/code/environments/production/modules/firewall дирек­то­рию, давай­те перей­дем в нее:

 # cd /etc/puppetlabs/code/environments/production/modules/firewall

После это­го, созда­ем файл:

 # vim manifests/pre.pp

И встав­ля­ем в него:

 class firewall::pre {
Firewall {
require => undef,
}
# Accept all loopback traffic
firewall { '000 lo traffic':
proto => 'all',
iniface => 'lo',
action => 'accept',
}->
#Drop non-loopback traffic
firewall { '001 reject non-lo':
proto => 'all',
iniface => '! lo',
destination => '127.0.0.0/8',
action => 'reject',
}->
#Accept established inbound connections
firewall { '002 accept established':
proto => 'all',
state => ['RELATED', 'ESTABLISHED'],
action => 'accept',
}->
#Allow all outbound traffic
firewall { '003 allow outbound':
chain => 'OUTPUT',
action => 'accept',
}->
#Allow ICMP/ping
firewall { '004 allow icmp':
proto => 'icmp',
action => 'accept',
}
#Allow SSH connections
firewall { '005 Allow SSH':
dport => '22',
proto => 'tcp',
action => 'accept',
}->
#Allow HTTP/HTTPS connections
firewall { '006 HTTP/HTTPS connections':
dport => ['80', '443'],
proto => 'tcp',
action => 'accept',
}
}

В этой дирек­то­рии, созда­ем еще один файл:

 # vim manifests/post.pp

И про­пи­сы­ва­ем в него:

 class firewall::post {
firewall { '999 drop all':
proto => 'all',
action => 'drop',
before => undef,
}
}

Дан­ные пра­ви­ла будут при­ме­нять­ся в фаэрволе.

Про­ве­рим валидность:

 # puppet parser validate manifests/pre.pp
# puppet parser validate manifests/post.pp
 Созда­дим папку:
 #·mkdir examples

Созда­ем еще файл для тестирования:

 # vim examples/init.pp

Про­пи­сы­ва­ем в него:

 resources { 'firewall':
purge => true,
}
Firewall {
before => Class['firewall::post'],
require => Class['firewall::pre'],
}
class { ['firewall::pre', 'firewall::post']: }
firewall { '200 Allow Puppet Master':
dport => '8140',
proto => 'tcp',
action => 'accept',
}

Вали­ди­ру­ем:

 # puppet parser validate examples/init.pp
# puppet apply --noop examples/init.pp
Notice: Compiled catalog for puppet-server in environment production in 0.21 seconds
Notice: /Stage[main]/Firewall::Pre/Firewall[000 lo traffic]/ensure: current_value absent, should be present (noop)
Notice: /Stage[main]/Firewall::Pre/Firewall[001 reject non-lo]/ensure: current_value absent, should be present (noop)
Notice: /Stage[main]/Firewall::Pre/Firewall[002 accept established]/ensure: current_value absent, should be present (noop)
Notice: /Stage[main]/Firewall::Pre/Firewall[003 allow outbound]/ensure: current_value absent, should be present (noop)
Notice: /Stage[main]/Firewall::Pre/Firewall[004 allow icmp]/ensure: current_value absent, should be present (noop)
Notice: /Stage[main]/Firewall::Pre/Firewall[005 Allow SSH]/ensure: current_value absent, should be present (noop)
Notice: /Stage[main]/Firewall::Pre/Firewall[006 HTTP/HTTPS connections]/ensure: current_value absent, should be present (noop)
Notice: Class[Firewall::Pre]: Would have triggered 'refresh' from 7 events
Notice: /Stage[main]/Main/Firewall[200 Allow Puppet Master]/ensure: current_value absent, should be present (noop)
Notice: Class[Main]: Would have triggered 'refresh' from 1 events
Notice: /Stage[main]/Firewall::Post/Firewall[999 drop all]/ensure: current_value absent, should be present (noop)
Notice: Class[Firewall::Post]: Would have triggered 'refresh' from 1 events
Notice: Stage[main]: Would have triggered 'refresh' from 3 events
Notice: Applied catalog in 1.50 seconds
Запус­ка­ем:
# puppet apply examples/init.pp
Notice: Compiled catalog for puppet-server in environment production in 0.21 seconds
Notice: /Stage[main]/Firewall::Pre/Firewall[000 lo traffic]/ensure: created
Warning: Firewall[000 lo traffic](provider=iptables): Unable to persist firewall rules: Execution of '/usr/libexec/iptables/iptables.init save' returned 1:
Notice: /Stage[main]/Firewall::Pre/Firewall[001 reject non-lo]/ensure: created
Warning: Firewall[001 reject non-lo](provider=iptables): Unable to persist firewall rules: Execution of '/usr/libexec/iptables/iptables.init save' returned 1:
Notice: /Stage[main]/Firewall::Pre/Firewall[002 accept established]/ensure: created
Warning: Firewall[002 accept established](provider=iptables): Unable to persist firewall rules: Execution of '/usr/libexec/iptables/iptables.init save' returned 1:
Notice: /Stage[main]/Firewall::Pre/Firewall[003 allow outbound]/ensure: created
Warning: Firewall[003 allow outbound](provider=iptables): Unable to persist firewall rules: Execution of '/usr/libexec/iptables/iptables.init save' returned 1:
Notice: /Stage[main]/Firewall::Pre/Firewall[004 allow icmp]/ensure: created
Warning: Firewall[004 allow icmp](provider=iptables): Unable to persist firewall rules: Execution of '/usr/libexec/iptables/iptables.init save' returned 1:
Notice: /Stage[main]/Firewall::Pre/Firewall[005 Allow SSH]/ensure: created
Warning: Firewall[005 Allow SSH](provider=iptables): Unable to persist firewall rules: Execution of '/usr/libexec/iptables/iptables.init save' returned 1:
Notice: /Stage[main]/Firewall::Pre/Firewall[006 HTTP/HTTPS connections]/ensure: created
Warning: Firewall[006 HTTP/HTTPS connections](provider=iptables): Unable to persist firewall rules: Execution of '/usr/libexec/iptables/iptables.init save' returned 1:
Notice: /Stage[main]/Main/Firewall[200 Allow Puppet Master]/ensure: created
Warning: Firewall[200 Allow Puppet Master](provider=iptables): Unable to persist firewall rules: Execution of '/usr/libexec/iptables/iptables.init save' returned 1:
Notice: /Stage[main]/Firewall::Post/Firewall[999 drop all]/ensure: created
Warning: Firewall[999 drop all](provider=iptables): Unable to persist firewall rules: Execution of '/usr/libexec/iptables/iptables.init save' returned 1:
Notice: Applied catalog in 1.93 seconds

Смот­рим что получилось:

 # iptables -L -n
Chain INPUT (policy ACCEPT)
target prot opt source destination
ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 /* 000 lo traffic */
REJECT all -- 0.0.0.0/0 127.0.0.0/8 /* 001 reject non-lo */ reject-with icmp-port-unreachable
ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 /* 002 accept established */ state RELATED,ESTABLISHED
ACCEPT icmp -- 0.0.0.0/0 0.0.0.0/0 /* 004 allow icmp */
ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 multiport dports 22 /* 005 Allow SSH */
ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 multiport dports 80,443 /* 006 HTTP/HTTPS connections */
ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 multiport dports 8140 /* 200 Allow Puppet Master */
DROP all -- 0.0.0.0/0 0.0.0.0/0 /* 999 drop all */
Chain FORWARD (policy ACCEPT)
target prot opt source destination
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 /* 003 allow outbound */

Вро­де бы все то, что про­пи­сы­ва­ли в пра­ви­лах — уже имеется.

Но это же я настра­и­вал все на пап­пет-сер­ве­ре, что­бы доба­вить модуль\манифест для нод, нуж­но кое-что прописать.

Откры­ва­ем файл:

 # vim·/etc/puppetlabs/code/environments/production/manifests/site.pp

И про­пи­сы­ва­ем:

 node 'host', 'puppet-agent' {
include accounts
resources { 'firewall':
purge => true,
}
Firewall {
before => Class['firewall::post'],
require => Class['firewall::pre'],
}
class { ['firewall::pre', 'firewall::post']: }
}

Запус­ка­ем на пап­пет-аген­те манифет:

 # puppet agent -t
Info: Using configured environment 'production'
Info: Retrieving pluginfacts
Info: Retrieving plugin
Notice: /File[/var/lib/puppet/lib/facter]/ensure: created
Notice: /File[/var/lib/puppet/lib/facter/ip6tables_version.rb]/ensure: defined content as '{md5}e1dbe35390cd819240e202709c52b1bb'
Notice: /File[/var/lib/puppet/lib/facter/iptables_persistent_version.rb]/ensure: defined content as '{md5}8ea76fecb8032174823ef6fb846c83c9'
Notice: /File[/var/lib/puppet/lib/facter/iptables_version.rb]/ensure: defined content as '{md5}116b96951342bf726f28fa952f2f5f4b'
Notice: /File[/var/lib/puppet/lib/puppet]/ensure: created
Notice: /File[/var/lib/puppet/lib/puppet/provider]/ensure: created
Notice: /File[/var/lib/puppet/lib/puppet/provider/firewall]/ensure: created
Notice: /File[/var/lib/puppet/lib/puppet/provider/firewall.rb]/ensure: defined content as '{md5}32d2f5e5dcc082986b82ef26a119038b'
Notice: /File[/var/lib/puppet/lib/puppet/provider/firewall/ip6tables.rb]/ensure: defined content as '{md5}b70c52ef1ff2e3a8e84257289a573b6f'
Notice: /File[/var/lib/puppet/lib/puppet/provider/firewall/iptables.rb]/ensure: defined content as '{md5}05fc4e96ccc3c0ae0c3949431b0502be'
Notice: /File[/var/lib/puppet/lib/puppet/provider/firewallchain]/ensure: created
Notice: /File[/var/lib/puppet/lib/puppet/provider/firewallchain/iptables_chain.rb]/ensure: defined content as '{md5}4d0432b240e8ecd46094a64462641e15'
Notice: /File[/var/lib/puppet/lib/puppet/type]/ensure: created
Notice: /File[/var/lib/puppet/lib/puppet/type/firewall.rb]/ensure: defined content as '{md5}0977fed5fef2c9a990764d8a42b9dd6d'
Notice: /File[/var/lib/puppet/lib/puppet/type/firewallchain.rb]/ensure: defined content as '{md5}9262061ade5c73329db773b769ee70a2'
Notice: /File[/var/lib/puppet/lib/puppet/util]/ensure: created
Notice: /File[/var/lib/puppet/lib/puppet/util/firewall.rb]/ensure: defined content as '{md5}036b832027cf4301356661f9c3c3a1d9'
Notice: /File[/var/lib/puppet/lib/puppet/util/ipcidr.rb]/ensure: defined content as '{md5}e1160dfd6e73fc5ef2bb8abc291f6fd5'
Info: Loading facts
Info: Caching catalog for puppet-agent
Info: Applying configuration version '1503487204'
Notice: /Stage[main]/Accounts::Groups/Group[vagrant]/ensure: created
Error: /Stage[main]/Accounts::Ssh/File[/etc/ssh/sshd_config]: Could not evaluate: Could not retrieve file metadata for puppet:///modules/accounts/sshd_config: Error 500 on SERVER: Server Error: Permission denied - /etc/puppetlabs/code/modules/accounts/files/sshd_config
Notice: /Stage[main]/Accounts::Ssh/Service[sshd]: Dependency File[/etc/ssh/sshd_config] has failures: true
Warning: /Stage[main]/Accounts::Ssh/Service[sshd]: Skipping because of failed dependencies
Notice: /Stage[main]/Accounts/User[vagrant]/ensure: created
Notice: /Stage[main]/Main/Node[puppet-agent]/Firewall[9001 fe701ab7ca74bd49f13b9f0ab39f3254]/ensure: removed
Notice: /Stage[main]/Main/Node[puppet-agent]/Firewall[9002 a8eb63c76896060f20aa62621c36f77a]/ensure: removed
Notice: /Stage[main]/Main/Node[puppet-agent]/Firewall[9003 49bcd611c61bdd18b235cea46ef04fae]/ensure: removed
Notice: /Stage[main]/Main/Node[puppet-agent]/Firewall[9004 dc0f1adfee77aa04ef7fdf348860a701]/ensure: removed
Notice: /Stage[main]/Main/Node[puppet-agent]/Firewall[9005 8eee49915b9ff9ef00b6af60d5113a66]/ensure: removed
Notice: /Stage[main]/Main/Node[puppet-agent]/Firewall[9006 a73ef6d2c52b1ce6c5ae8d9d326b34ed]/ensure: removed
Notice: /Stage[main]/Firewall::Pre/Firewall[000 lo traffic]/ensure: created
Notice: /Stage[main]/Firewall::Pre/Firewall[001 reject non-lo]/ensure: created
Notice: /Stage[main]/Firewall::Pre/Firewall[002 accept established]/ensure: created
Notice: /Stage[main]/Firewall::Pre/Firewall[003 allow outbound]/ensure: created
Notice: /Stage[main]/Firewall::Pre/Firewall[004 allow icmp]/ensure: created
Notice: /Stage[main]/Firewall::Pre/Firewall[005 Allow SSH]/ensure: created
Notice: /Stage[main]/Firewall::Pre/Firewall[006 HTTP/HTTPS connections]/ensure: created
Notice: /Stage[main]/Firewall::Post/Firewall[999 drop all]/ensure: created
Info: Stage[main]: Unscheduling all events on Stage[main]
Notice: Applied catalog in 2.16 seconds

Видим что у меня име­ет­ся ошиб­ка, не может про­чи­тать файл с пап­пет-сер­ве­ра (не хва­та­ет прав), но все осталь­ное — отра­бо­та­ло отлично.

Про­ве­ря­ем iptables на паппет-агенте:

# iptables -L -n
Chain INPUT (policy ACCEPT)
target prot opt source destination
ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 /* 000 lo traffic */
REJECT all -- 0.0.0.0/0 127.0.0.0/8 /* 001 reject non-lo */ reject-with icmp-port-unreachable
ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 /* 002 accept established */ state RELATED,ESTABLISHED
ACCEPT icmp -- 0.0.0.0/0 0.0.0.0/0 /* 004 allow icmp */
ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 multiport dports 22 /* 005 Allow SSH */
ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 multiport dports 80,443 /* 006 HTTP/HTTPS connections */
DROP all -- 0.0.0.0/0 0.0.0.0/0 /* 999 drop all */
Chain FORWARD (policy ACCEPT)
target prot opt source destination
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 /* 003 allow outbound */

Видим что пра­ви­ла применились!

Выключение/Включение Puppet в Unix/Linux

Ино­гда нуж­но выклю­чить пап­пет-агент что­бы тот не запус­кал мани­фе­сты. Я сей­час рас­ска­жу как мож­но выклю­чить или вклю­чить puppet. Ниче­го слож­но­го в этом нет. Ста­тья для обще­го понимания…

Смот­рим состояние:

# puppet agent -t
Info: Using configured environment 'production'
Info: Retrieving pluginfacts
Info: Retrieving plugin
Info: Loading facts
Info: Caching catalog for puppet-agent
Info: Applying configuration version '1503567446'
Notice: Applied catalog in 0.85 seconds
Как мож­но было понять с выво­да — у меня вклю­чен паппет-агент.

Что­бы отклю­чить исполь­зо­ва­ние Puppet аген­та, исполь­зуй­те сле­ду­ю­щую команду:

# puppet agent --disable "Reason is disabled"
 Где:
  • —disable —  Отклю­ча­ет рабо­ту в локаль­ной систе­ме. Дан­ное дей­ствие, бло­ки­ру­ет систе­му до тех пор, пока файл бло­ки­ров­ки уда­лен. Это полез­но, если вы тести­ру­е­те кон­фи­гу­ра­цию и не хоти­те выпол­не­ния манифеста(ов) пока все не про­ве­ре­но и не убе­ди­тесь что все рабо­та­ет долж­ным образом.
  • «Reason is disabled» — Мож­но оста­вить ком­мен­та­рий (При­чи­на отключения).

Что­бы убе­дить­ся, что он отклю­чен, про­сто запу­сти­те команду:

puppet agent -t
Notice: Skipping run of Puppet configuration client; administratively disabled (Reason: 'Reason why disabled');
Use 'puppet agent --enable' to re-enable.

Что­бы вклю­чить исполь­зо­ва­ние Puppet аген­та, исполь­зуй­те сле­ду­ю­щую команду:

 # puppet agent --enable

Для помо­щи, мож­но использовать:

 # puppet agent -help

Моду­ли в Puppet

Широ­кая кол­лек­ция уже суще­ству­ю­щих моду­лей пред­став­ле­на здесь
https://forge.puppet.com/

Поиск необ­хо­ди­мо­го модуля

Напри­мер, моду­ля mysql

Уста­нов­ка моду­ля mysql с Puppetlabs

Про­вер­ка син­так­си­са мани­фе­ста и его выполнение

Про­ве­ре­я­ем, что уста­но­вил­ся MySQL, пароль MySQL поль­зо­ва­те­ля root уста­нов­лен в 123456789, пара­метр max_connections уста­нов­лен в 1024

 

Про­смотр уста­нов­лен­ных модулей

 

Проверка,что puppet-manifest соот­вест­ву­ет сти­лю Puppet

Авто­ма­ти­че­ское исправ­ле­ние най­ден­ных раз­ли­чий в стиле

 

При­ме­ры опи­са­ния неко­то­рых ресурсов

Управ­ле­ние пакетами

Управ­ле­ние службами

Управ­ле­ние файлами

Управ­ле­ние пользователями

Выпол­не­ние команд

 

Puppet предо­став­ля­ет раз­лич­ные кон­струк­ции для управ­ле­ния усло­ви­я­ми внут­ри манифеста

Selectors

Case

If elsif else

 

Опе­ра­то­ры срав­не­ния в Puppet
Puppet под­дер­жи­ва­ет неко­то­рые общие опе­ра­то­ры сравнения

А так­же оператор

 

Ком­би­на­ция условий