Настройка современного Puppet сервера с нуля

http://stdout.no/a-modern-puppet-master-from-scratch/
  • Перевод
Недавно я переосмыслил процедуру установки нового сервера Puppet с нуля на Ubuntu 12.04, включая все современные свистелки и перделки. В итоге у меня получился этот гайд.

Для начала нам потребуется чистая Ubuntu c работающей сетью и настроенным DNS.

В итоге мы должны получить:
  • Установленый везде Puppet 3-й версии
  • Конфиги в git репозитории с общим доступом
  • Динамические окружения, управляемые r10k
  • Поддержку PuppetDB
  • Поддержку Hiera


Данное руководство довольно длинное, т.к. все настройки делаются вручную, чтобы впоследствии легко можно было пользоваться результатом и подстраивать его под себя. Единственным исключением является PuppetDB, который проще установливать через собственный модуль от Puppet Labs, а не вручную.

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


Установка Puppet


Добавьте репозиторий Puppet Labs, путем установки их пакета:
source /etc/lsb-release
wget https://apt.puppetlabs.com/puppetlabs-release-$DISTRIB_CODENAME.deb
dpkg -i puppetlabs-release-$DISTRIB_CODENAME.deb
rm puppetlabs-release-$DISTRIB_CODENAME.deb

Установите Puppet и Puppet Master:
apt-get update
apt-get install puppet puppetmaster

Примечание от переводчика: документация Puppet Labs рекомендует устанавливать puppetmaster-passenger.

Настройка Puppet


Создайте директорию, в которой будут расположены настройки ваших окружений и дайте группе puppet права на запись:
mkdir /etc/puppet/environments
chgrp puppet /etc/puppet/environments
chmod 2775 /etc/puppet/environment

Мы никогда не будем редактировать содержимое данной директории напрямую, за нас это будет делать r10k через git hook, который мы настроим чуть позже.

Теперь необходимо сделать некоторые настройки в файле /etc/puppet/puppet.conf. Вот неплохой пример, с которого вы можете начать:
[main]
  environment   = production
  confdir       = /etc/puppet
  logdir        = /var/log/puppet
  vardir        = /var/lib/puppet
  ssldir        = $vardir/ssl
  rundir        = /var/run/puppet
  factpath      = $vardir/lib/facter
  templatedir   = $confdir/templates
  pluginsync    = true

[agent]
  environment   = production
  report        = true
  show_diff     = true

[master]
  environment   = production
  manifest      = $confdir/environments/$environment/manifests/site.pp
  modulepath    = $confdir/environments/$environment/modules:$confdir/environments/$environment/site
  # Passenger
  ssl_client_header        = SSL_CLIENT_S_DN
  ssl_client_verify_header = SSL_CLIENT_VERIFY

Примечание от переводчика: начиная с версии 3.6, переменные manifest/modulepath/config_version устарели в пользу окружений.

Если у вас еще не настроено определение имени "puppet" в DNS, вы можете добавить server = your.server.com в секцию [main].

Настройка Hiera


Hiera так же требует некоторой конфигурации. Создайте файл /etc/puppet/hiera.yaml:
---
:hierarchy:
  - "nodes/%{::fqdn}"
  - "manufacturers/%{::manufacturer}"
  - "virtual/%{::virtual}"
  - common
:backends:
  - yaml
:yaml:
  :datadir: "/etc/puppet/environments/%{::environment}/hieradata"

Для того, что бы сделать отладку Hiera немного проще и избежать путаницы в дальнейшем, я предпочитаю заменить файл /etc/hiera.yaml (о котором Puppet даже не подозревает) символической ссылкой на /etc/puppet/hiera.yaml:
ln -sf /etc/puppet/hiera.yaml /etc/hiera.yaml


Проверка работоспособности Puppet


Сейчас самое время перезапустить сервис Puppet Master:
/etc/init.d/puppetmaster restart

Проверьте работоспособность Puppet агента:
puppet agent --test

В результате вы должны получить нечто похожее:
Info: Retrieving plugin
Error: /File[/var/lib/puppet/lib]: Could not evaluate: Could not retrieve information from environment production source(s) puppet://testpm.qix.no/plugins
Info: Caching catalog for testpm.qix.no
Info: Applying configuration version '1384949455'
Info: Creating state file /var/lib/puppet/state/state.yaml
Notice: Finished catalog run in 0.03 seconds

Единственная ошибка может быть проигнорирована, т.к. у нас еще нет ни конфигов, ни плагинов.
Перед тем как продолжать, удостоверьтесь, что данная команда работает. Проблемы на данном этапе скорее всего связаны с DNS.

Установка r10k


Бесподобный Adrien Thebo создал такую же бесподобную утилиту для управления динамическими окружениями Puppet и эффективного использования внешних модулей — неважно, нашли ли вы их на Puppet Forge или храните их в своем собственном репозитории.
Дополнительную информацию вы можете найти на страничке GitHub. Для установки выполните команды:
apt-get install rubygems
gem install r10k


Настройка r10k


Необходимо создать директорию с кешами, в которой r10k будет хранить копии модулей:
mkdir /var/cache/r10k
chgrp puppet /var/cache/r10k
chmod 2775 /var/cache/r10k

И конечно же, r10k имеет свой файл с настройками. Создайте /etc/r10k.yaml со следующим содержимым:
# location for cached repos
:cachedir: '/var/cache/r10k'

# git repositories containing environments
:sources:
  :base:
    remote: '/srv/puppet.git'
    basedir: '/etc/puppet/environments'

# purge non-existing environments found here
:purgedirs:
  - '/etc/puppet/environments'


Установка git


К сожалению, версия git, которая идет в поставке Ubuntu 12.04, подвержена этому багу, который устанавливает неверные права (0755) на все новые окружения Puppet. Это не позволяет расшаривать репозитории между несколькими пользователями.

Добавьте PPA от команды поддержки git:
apt-get install python-software-properties
add-apt-repository ppa:git-core/ppa

Установите последнюю стабильную версию git:
apt-get update
apt-get install git


Создание git репозитория


Теперь создайте новый git репозиторий, который станет главным источником Puppet конфигурации для вашего сервера.
Все ваши администраторы будут работать с этим репозиторием, а r10k будет обновляться из него, чтобы автоматически создавать (или удалять) окружения Puppet.
Создайте новый репозиторий в /srv/puppet.git:
git init --bare --shared=group /srv/puppet.git
chgrp -R puppet /srv/puppet.git
cd /srv/puppet.git
git symbolic-ref HEAD refs/heads/production

Обратите внимание, что у этого репозитория есть три отличительных особенности:
  1. он bare;
  2. он shared;
  3. ветка master переименована в production.


Настройка прав доступа


Пришло время начать настраивать Puppet в git репозитории.
Вы не должны работать с git репозиторием из под пользователя root, поэтому добавьте своего пользователя в группу puppet, которая будет использована для ограничения доступа к репозиторию:
adduser <myuser> puppet

Перелогиньтесь, что бы изменения вступили в силу.
Еще раз проверьте членство в группе, выполнив данную команду от обычного пользователя:
id | grep puppet


Создание git хука


Продолжайте работать под своим обычным пользователем.
Создайте файл /srv/puppet.git/hooks/post-receive, который будет запускать r10k при каждом push'е в репозиторий:
#!/bin/bash

umask 0002

while read oldrev newrev ref
do
    branch=$(echo $ref | cut -d/ -f3)
    echo
    echo "--> Deploying ${branch}..."
    echo
    r10k deploy environment $branch -p
    # sometimes r10k gets permissions wrong too
    find /etc/puppet/environments/$branch/modules -type d -exec chmod 2775 {} \; 2> /dev/null
    find /etc/puppet/environments/$branch/modules -type f -exec chmod 664 {} \; 2> /dev/null
done

Не забудьте сделать скрипт исполняемым:
chmod 0775 /srv/puppet.git/hooks/post-receive


Создание первого окружения


Перейдите в домашнюю директорию под своим обычным пользователем и склонируйте пустой репозиторий:
cd
git clone /srv/puppet.git
cd puppet

Создайте несколько необходимых директорий:
mkdir -p hieradata/nodes manifests site

Папку modules мы не создаем, т.к. она будет управляться через r10k. Локальные модули (т.е. модули исключительно для данного puppet master сервера) будут располагаться в директории site.
Теперь давайте приступим к настройке r10k. Создайте файл Puppetfile в корне репозитория со следующим содержимым:
# Puppet Forge
mod 'puppetlabs/ntp', '3.0.0-rc1'
mod 'puppetlabs/puppetdb', '3.0.0'
mod 'puppetlabs/stdlib', '4.1.0'
mod 'puppetlabs/concat', '1.0.0'
mod 'puppetlabs/inifile', '1.0.0'
mod 'puppetlabs/postgresql', '3.2.0'
mod 'puppetlabs/firewall', '0.4.2'

# A module from your own git server
#mod 'custom',
#  :git => 'git://git.mydomain.com/custom.git',
#  :ref => '1.0'

Формат файла Puppetfile был впервые предложен Тимом Шарпом (Tim Sharpe) для использования в librarian-puppet, поэтому используйте его как источник документации.
Два важных момента о Puppetfile:
  • В отличии от команды puppet module, r10k не поддерживает автоматическую обработку зависимостей (для версии 1.1.0). Вы должны включить все зависимости вручную.
  • Вы можете ссылаться на git коммиты заменяя теги на git хеши. Для тестирования вы даже можете переключить ветку, установив ref на что-нибудь типа master, но это возможно не очень хорошая идея в боевом окружении.


Теперь мы настроим два модуля, подключив их через Hiera.
Все хосты должны иметь ntp модуль, поэтому создайте файл hieradata/common.yaml со следующим содержимым:
---
classes:
  - ntp

ntp::servers:
  - 0.pool.ntp.org
  - 1.pool.ntp.org
  - 2.pool.ntp.org
  - 3.pool.ntp.org


Нашему puppet master серверу требуется модуль puppetdb, поэтому создайте файл hieradata/nodes/$(hostname -f).yaml и добавьте в него необходимый класс с дефолтными настройками:
---
classes:
  - puppetdb
  - puppetdb::master::config

Наконец, создайте очень простой манифест manifests/site.pp, который будет включать все классы, которые мы определили в Hiera:
hiera_include('classes')


Commit и push


Оставайтесь в git репозитории — пришло время выполнить commit и push первой версии окружения production.
Из-за того, что git не позволяет сохранять пустые директории, а у нас пока что нет локальных модулей, добавьте фиктивный файл директорию site:
touch site/.keep

Удостоверьтесь, что у вас правильная ветка, добавьте все файлы и выполните commit и push:
git checkout -b production
git add *
git commit -a -m "initital commit"
git push -u origin production


В результате вы должны получить примерно такой ответ:
Counting objects: 11, done.
Compressing objects: 100% (5/5), done.
Writing objects: 100% (11/11), 867 bytes | 0 bytes/s, done.
Total 11 (delta 0), reused 0 (delta 0)
remote: 
remote: --> Deploying production...
remote: 
To /srv/puppet.git
 * [new branch]      production -> production
Branch production set up to track remote branch production from origin.

Обратите внимание на сообщение --> Deploying production..., которое означает, что наш git хук сработал.
Вы может так же проверить, что директория /etc/puppet/environments/production была создана и содержимое ее папки modules содержит модули Puppet Forge, которые мы перечислили в Puppetfile.

Запуск Puppet


Переключитесь обратно на пользователя root и запустите puppet агента:
puppet agent --test

Вы должны получить несколько экранов вывода черного и зеленого текста, описывающих прогресс инсталляции и конфигурации NTP и PuppetDB сервисов, включая базу данных PostgreSQL, необходимую для PuppetDB.
Проверьте, что сервисы запущены:
/etc/init.d/ntp status
/etc/init.d/puppetdb status


Проверка PuppetDB


Запустите puppet еще раз, чтобы наполнить данными postgresql:
puppet agent --test

После этого запустите такую команду:
puppet node status $(hostname -f)

Вы должны получить примерно такой ответ:
testpm.qix.no
Currently active
Last catalog: 2013-11-20T13:22:05.036Z
Last facts: 2013-11-20T13:22:00.437Z

Полезный совет: попробуйте следующую команду, чтобы увидеть всю информацию о вашем хосте, которую хранит puppetdb в отформатированном json:
puppet node find $(hostname -f) | python -mjson.tool

Теперь puppetdb полностью настроен и вы можете использовать экспорт ресурсов для таких вещей как распределение ssh ключей по всем хостам.

Проверка Hiera


Если вы дошли до этого шага, значит Hiera уже работает, но вам может быть неоходимо во время разработки потестировать Hiera из командной строки.
Надеюсь, вы последовали моему совету и сделали файл /etc/hiera.yaml символической ссылкой на /etc/puppet/hiera.yaml. Тогда следующая команда перечислит все классы, которые будут применены к текущему хосту в production окружении:
hiera -a classes ::environment=production ::fqdn=$(hostname -f)

В результате вы должны получить:
["puppetdb", "puppetdb::master::config", "ntp"]


Процесс работы с Puppet Master


Создание веток в git не требует особых усилий, поэтому процесс разработки будет выглядеть так:
# создайте новую ветку и сделайте требуемые изменения
git checkout -b new_feature
vim somefile
git add somefile
git commit -m "best feature ever"

# новая ветка == новое окружение
git push --set-upstream origin new_feature

# проведите тесты (ведь вы это будете делать на тестовом сервере, не так ли?)
puppet agent --test --noop --environment new_feature
puppet agent --test --environment new_feature

# diff and merge
git checkout production
git diff ..new_feature
git diff --name-only new_feature
git merge new_feature

# выложите новую фичу в production
git push

# удалите локальную ветку
git branch -d new_feature

# удалите ветку с сервера == удалить окружение
git push origin :new_feature


Процесс работы с модулями


Если вы работаете над модулем, который вы хотите использовать на нескольких серверах Puppet Master (но не отдавать наружу), один из способов это сделать — выложить на внутренний git сервер и настроить ветку, над которой вы работаете в Puppetfile:
mod 'my_app',
  :git => 'git://git.mydomain.com/my_app.git',
  :ref => 'master'

Данный модуль будет обновляться под последний коммит в ветке master каждый раз когда вы делаете push репозитория /srv/puppet.git. А что, если вы не делали никаких изменений в этот репозиторий? В таком случае просто выполните r10k явно. Даннная команда обновит все модули во всех окружениях:
r10k deploy environment -p

Для обновления только окружения testing:
r10k deploy environment testing -p

Единственная проблема при запуске r10k таким образом это то, что при этом могут поехать права в /etc/puppet/environments, что приведет к проблемам в расшаренном репозитории. Что бы этого избежать создайте скрипт /usr/local/bin/deploy и дайте ему права на исполнение:
#!/bin/sh

umask 0002

r10k deploy environment $1 -p

find /etc/puppet/environments -mindepth 1 -type d -exec chmod 2775 {} \;
find /etc/puppet/environments -type f -exec chmod 0664 {} \;

Теперь при обновлении модулей, которые настроены на определенную ветку, вы можете запустить команды:
# обновить все модули во всех окружениях
deploy

# обновить все модули в тестовом окружении
deploy testing

После окончания работы над своем модулем, не забудьте создать для него тег:
git tag -a 1.0 -m "finally no error messages"
git push --tags

… и обновите ваш Puppetfile, что бы ссылаться по имени тега, а не по имени ветки. Чуть позже вы будете благодарны себе за это.

Заключение


Теперь вы должны иметь прочную и современную (ну, на какое-то время) базовую конфигурацию Puppet. Удачи!

Рекомендую почитать




Дополнения от переводчика


У себя на Puppet Master я настроил связку gitolite+gitlist. Все репозитории лежат в gitolite, изменения можно удобно просматривать в браузере (gitlab мне показался слишком монструозным с большим количеством зависимостей и ненужным в моем случае функционалом). Директория /etc/puppet тоже лежит в отдельном git репозитории (environments добавлены в .gitignore)
Для мониторинга отчетов я использую puppetexplorer — очень удобный интерфейс для PuppetDB, работающий на стороне клиента (написан на AngularJS и CoffeeScript).

Ссылки:
Поделиться публикацией

Комментарии 15

    0
    Спасибо за перевод. Сам пользуюсь фореманом и git на всю /etc/puppet и с разделением окружений на продакшен и девелопмент становится сложнее следить за хозяйством. эта статья заставила взглянуть на этот процесс с правильной стороны. буду менять структуру. Спасибо.
      0
      Раньше тоже использовал Foreman. Но пользовался исключительно просмотром отчетов о запусках агентов.
      В итоге, когда решал, что поставить остановился на puppetexplorer.
        0
        я его использую гораздо шире:
        — 2 окружения (прод, дев)
        — различные параметры в зависимости от различных признаков (домен, имя хоста, группа)
        — отчёты, само собой

        В принципе почти устраивает, единственно — хочется редактировать манифесты из него же (из форемана), но я как то искал — не нашёл такой возможности.
        Ну и + я ещё хочу начать использовать его возможности по управлению гипервизорами для автоматического поднятия виртуалок, но пока модуль под xenserver только пилится и я его ещё не пробовал.
      +2
      А вы не настраивали никакой веб-сервер (типа Nginx) перед puppet'ом? Коллеги говорят, что при большом числе управляемых серверов начинаются тормоза, если перед сервером приложений puppet'а нет балансировщика и отдатчика статики.
        0
        Примечание от переводчика: документация Puppet Labs рекомендует устанавливать puppetmaster-passenger.

        Собственно puppetmaster-passenger сразу же настраивает Puppet за апачем — тут можно почитать подробнее. У себя сделал именно так — хотя хостов и не очень много.
          0
          Большом — это каком?
          У нас на, примерно, 300 клиентских серверах тормозов не замечено.
          Правда, мы готовим puppet подругому: каждый хост имеет локальную копию всех манифестов, стянутую с мастера.
          При параллельной массовой синхронизации ничего не тормозит.
          +1
          Спасибо за r10k, надо посмотреть.
            0
            Удивлен был, что в рунете о нем как-то не особо в курсе. Собственно, это была одна из причин, по которым решил перевести статью.
            +1
            Для тех кто будет следовать инструкции:
            необходимо указать более новую версию puppetdb
            mod 'puppetlabs/puppetdb', '3.0.1'
            

            И для версий puppet начиная с 3.6 конфиг будет иметь вид:
            [main]
              environment   = production
              confdir       = /etc/puppet
              logdir        = /var/log/puppet
              vardir        = /var/lib/puppet
              ssldir        = $vardir/ssl
              rundir        = /var/run/puppet
              factpath      = $vardir/lib/facter
              pluginsync    = true
            
            [agent]
              environment   = production
              report        = true
              show_diff     = true
            
            [master]
              environment   = production
              environmentpath = $confdir/environments
            
              # Passenger
              ssl_client_header        = SSL_CLIENT_S_DN
              ssl_client_verify_header = SSL_CLIENT_VERIFY
            
              0
              А чем r10k лучше Форемана?
                0
                Если я верно понял, то их нельзя сравнивать, т.к. это инструменты разного уровня. r10k — версионирование, деплой модулей и сред. The Foreman — система уже для полного контроля машины — от поднятия и накатки оси на голое железо (с помощью управления разными прокси) и сопровождение поднятого сервера до завершения эксплуатации.
                На сайте форемана написано — Foreman is a complete lifecycle management tool for physical and virtual servers.
                на гите r10k — Puppet environment and module deployment

                Так что это, по идее взаимодополняющие системы.
                Автор статьи же указал, что вместо форемана используется puppetexplorer.

                UPD: r10k — мечта моего коллеги-программиста — деплоить параметры и модули паппета так же как он деплоит свои проекты (php) ))
                0
                Если получили ошибку installing r10k: requires Ruby version >= 1.9.3. а вы думаю ее получите если у вас Debian GNU/Linux 6.0.10 (squeeze)
                то решение об установке и смене релиза Ruby вот тут
                  0
                  RLY?

                  HowTo: Find Out My Linux Distribution Name and Version

                  палитесь
                    0
                    Да, совет не актуален, обновился до Debian GNU/Linux 7.8 (wheezy), идет все по инструкции.
                  0
                  Полезный совет: попробуйте следующую команду, чтобы увидеть всю информацию о вашем хосте, которую хранит puppetdb в отформатированном json:
                  puppet node find $(hostname -f) | python -mjson.tool

                  Я пользуюсь утилитой jq
                  Пример:
                  puppet node find $(hostname -f) | jq .
                  

                  Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                  Самое читаемое