Puppet with r10k [Best Practice]

2

Настало время занимательных историй вместе с r10k. Давайте сначала узнаем, что же это за зверь и зачем он нужен?
По мнению разработчиков:

R10k provides a general purpose toolset for deploying Puppet environme
nts and modules. It implements the Puppetfile format and provides a native implementation of Puppet dynamic environments

По-моему сугубо личному мнению:

r10k – это просто бесполезный костыль с очень ему подходящим именем (Robot 10000 killer) написанный на ruby с монументально скудным функционалом.

NAME
    r10k - Killer robot powered Puppet environment deployment

USAGE
    r10k <subcommand> [options]

DESCRIPTION
    r10k is a suite of commands to help deploy and manage puppet code for
    complex environments.

COMMANDS
    deploy         Puppet dynamic environment deployment
    help           show help
    puppetfile     Perform operations on a Puppetfile
    version        Print the version of r10k

OPTIONS
    -c --config     Specify a global configuration file
       --color      Enable colored log messages
    -h --help       Show help for this command
    -t --trace      Display stack traces on application crash
    -v --verbose    Set log verbosity. Valid values: fatal, error, warn, notice, info, debug, debug1, debug2

… вот собственно и всё, что он умеет. Конкретно из этого гигантского вывода help нам понадобится только deploy для разворачивания наших конфигов/модулей из git/svn, НО и даже тут не всё так гладко как хотелось бы.

Из минусов:
Ruby и его гемы. Давайте смотреть правде в глаза, да эту штуковину можно написать хоть на bash’е потому что абсолютно всё, что она делает – скачивает из гита файлы и просто заменяет ими те, что в рабочей директории puppet’a. Но что делают разработчики? Они пишут его на тяжёлом ruby + установку поручают gem’у, то есть нам придётся при апдейте системы, апдейтить и этот дурацкий gem в том числе, либо ставить модуль zack-r10k и заставлять puppetmaster делать это за нас. Лично я ему апдейты не доверяю.
Отсутствие системы контроля версий. Что это значит? А значит это, что ему нельзя сказать “Эй, друг, задеплой мне версию 952a65d9ea”, нет, он всегда будет деплоить последнюю версию.
Отсутствие агента. То есть, чтоб нам задеплоить наши изменения, нам надо будет зайти на puppetmaster и сказать r10k deploy environment -p -v , однако есть костыльные решения комрадов: 1. Написание hooks (если есть свой git) либо webhooks; 2. Просто по крону гонять эту команду, НО и тут есть жирный минус который описан в предыдущем пункте, а именно – r10k не знает о том что в данный момент у нас на сервере самый свежий коммит, и запуская это по крону он будет его скачивать и заменять самим же собой снова и снова, тратя на это процессорное время и прочие важные ресурсы машины.
Он может устанавливать модули, но не их зависимости. То есть, когда мы хотим поставить модулем, к примеру, банальный ntp, нам сначала надо найти его методату, глазами найти зависимости и руками указать ему их в конфиге. Но я ленивый админ, я не хочу делать это, это должна делать машина, иначе зачем она мне? Ладно, допустим я это сделаю, НО опять есть но… а что если я скажу ему ставить только последнюю версию модуля, а в последней версии автор добавит ещё одну зависимость? Ответ прост – у меня просто на всём серверном парке сломается ntp. То есть, я не могу ему доверить поддерживать модули в актуальном состоянии, мне придётся делать это самому.

Ну и конечно же плюсы:
+ Он очень прост в установке и использовании…
+ Может как git так и svn
+ Может устанавливать модули из реп puppetforge либо любых других
+ Поддерживает версионирование модулей (Не путать с манифестами!) то есть ему можно сказать в конфиге “Эй, r10k, установи такую-то версию, такого-то модуля”

Если вы дочитали до этого момента и до сих пор не передумали это устанавливать – вы сумасшедший. Впрочем, это рекомендуют сделать разработчики puppet, а значит и мы сделаем то же самое, ведь это серия Best Practice ;(

Установка



Для начала поправим /etc/sudoers изменив там Defaults на следующий:

Defaults    secure_path = /sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin:/usr/local/sbin:/opt/puppetlabs/bin

Разработчик предлагает нам на выбор установку с помощью системного ruby, либо с помощью ruby уже “вшитого” в puppet. Разумеется мы выбираем первый вариант. Устанавливаем гемы и гит.

yum install rubygems git

Теперь можно установить и виновника сей статьи.

gem install r10k

Создадим необходимые каталоги и файлы для работы r10k.

mkdir -p /var/r10k/cache
mkdir -p /etc/puppetlabs/r10k
touch /etc/puppetlabs/r10k/r10k.yaml

Настроим этого маленького монстра редактировав для этого /etc/puppetlabs/r10k/r10k.yaml

# location for cached repos
:cachedir: '/var/r10k/cache'

# git repositories containing environments
:sources:
  :base:
    remote: 'https://gitlab.com/vasya/puppet.git'
    basedir: '/etc/puppetlabs/code/environments'

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

В remote у вас будет указана ваша репа, разумеется. Подробнее об этом ниже.
Чтоб нам где-то хранить наши конфиги, нам нужно это “где-то” организовать. Можно поднять приватный git, можно даже хоть на сервере с puppet’ом это сделать

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

НО я не заморачивался и просто создал репу на gitlab. Единственное что вам нужно будет сделать – переименовать branch master в production, потому что у этой штуки все ваши environments должны соответствовать именам веток в репе. То есть, допустим, у вас дефолтный environment production и есть ещё один для тестирования testing, соответственно в вашей репе будут аналогичные ветки production и testing.
В своём домашнем хомяке (vasya, – вы же не забыли что мы работаем из под него?) пишем:

git clone https://gitlab.com/vasya/puppet.git
cd puppet
git checkout -b production

Вместо https://gitlab.com/vasya/puppet.git у вас будет своя репа, как вы уже поняли. Создаём необходимые директории и файлы.

mkdir -p {modules,site/profile/manifests,hieradata/nodes}
touch hieradata/common.yaml
touch site/profile/manifests/base.pp
touch environment.conf
touch Puppetfile
touch site.pp

Редактируем environment.conf

manifest = site.pp
modulepath = modules:site

Редактируем site.pp внося туда одну единственную строку вместо всего того, что у нас там есть, которая будет говорить нашему puppet’у, чтоб он руководствовался исключительно hiera для всех нод.

hiera_include('classes')

И наконец самый главный файл Puppetfile – это конфиг того, что r10k будет ставить при деплое.

forge 'forge.puppetlabs.com'

# Forge Modules
mod 'puppetlabs/ntp', :latest
mod 'puppetlabs/puppetdb', :latest
mod 'puppetlabs/stdlib', :latest
mod 'puppetlabs/apt', :latest
mod 'puppetlabs/concat', :latest
mod 'puppetlabs/firewall', :latest
mod 'puppetlabs/inifile', :latest
mod 'puppetlabs/postgresql', :latest

# Local Modules
mod 'tm', :local => true

Здесь мы объявили все модули которые мы используем, сказали, что хотим использовать только последнюю версию (Хоть я и зарекался это делать (см. минусы в начале)) и место откуда хотим их брать.
Как бонус к статье – создаём hieradata/common.yaml в котором укажем использование профиля по-умолчанию, он будет применяться ко всем нодам.

---
classes:
 - 'profile::base'

ntp::restrict:
 -
ntp::enable: true
ntp::servers:
  - 0.ru.pool.ntp.org
  - 1.ru.pool.ntp.org

Создаём сам профиль site/profile/manifests/base.pp и записываем туда

class profile::base {
  class { '::ntp': }
}

Не забываем про наши манифесты. Создаём из в hieradata/nodes
puppet.my.domain.yaml

---
# Declare our classes
classes:
 - tm

# Here is example our module "Test Module" via /etc/puppetlabs/code/environments/production/modules/tm
tm::parameter_one: "There is no other way, and there never was. I lost in this place. Pls, i beg u, help me if u can"

и puppetdb.my.domain.yaml

---
# Declare our classes
classes:
 - tm
 - puppetdb

# After declare, work with it, we can transfer any var that supports to it
puppetdb::globals::version: "latest"

 Here is example our module "Test Module" via /etc/puppetlabs/code/environments/production/modules/tm
tm::parameter_one: "There is no other way, and there never was. I lost in this place. Pls, i beg u, help me if u can"

С этим вроде бы закончили… пришла пора первого коммита!

git checkout -b production
git add *
git commit -a -m "initital commit"
git push -u origin production

Ответ здорового человека:

Username for 'https://gitlab.com': vasya
Password for 'https://vasya@gitlab.com': 
Counting objects: 3, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (2/2), 211 bytes | 0 bytes/s, done.
Total 2 (delta 1), reused 0 (delta 0)
To https://gitlab.com/vasya/puppet.git
   7bd8f3c..b78f485  production -> production
Branch production set up to track remote branch production from origin.

Ну и собсно деплоим из гита наши изменения

sudo r10k deploy environment -p -v

На что он должен сказать что-то вроде

INFO	 -> Deploying environment /etc/puppetlabs/code/environments/production
INFO	 -> Environment production is now at b78f4851629fb94209c41615d96f5fc15f8e950d
INFO	 -> Deploying module /etc/puppetlabs/code/environments/production/modules/ntp
INFO	 -> Deploying module /etc/puppetlabs/code/environments/production/modules/puppetdb
INFO	 -> Deploying module /etc/puppetlabs/code/environments/production/modules/stdlib
INFO	 -> Deploying module /etc/puppetlabs/code/environments/production/modules/apt
INFO	 -> Deploying module /etc/puppetlabs/code/environments/production/modules/concat
INFO	 -> Deploying module /etc/puppetlabs/code/environments/production/modules/firewall
INFO	 -> Deploying module /etc/puppetlabs/code/environments/production/modules/inifile
INFO	 -> Deploying module /etc/puppetlabs/code/environments/production/modules/postgresql
INFO	 -> Deploying module /etc/puppetlabs/code/environments/production/modules/tm

Проверяем на нашем puppetdb

puppetdb vasya # sudo puppet agent --no-daemonize --onetime --verbose
Info: Using configured environment 'production'
Info: Retrieving pluginfacts
Info: Retrieving plugin
Info: Loading facts
Info: Caching catalog for puppetdb.local
Info: Applying configuration version '1468782923'
Notice: /Stage[main]/Tm/File[/tmp/test_module]/ensure: defined content as '{md5}ef4186a646a01838b0427bdffeae7cc6'
Notice: /Stage[main]/Ntp::Config/File[/etc/ntp.conf]/ensure: defined content as '{md5}2083e99dd158ddc605aff2a01a30ea5f'
Info: Class[Ntp::Config]: Scheduling refresh of Class[Ntp::Service]
Info: Class[Ntp::Service]: Scheduling refresh of Service[ntp]
Notice: /Stage[main]/Ntp::Service/Service[ntp]: Triggered 'refresh' from 1 events
Notice: Applied catalog in 2.10 seconds

Удивительно, но всё работает!

Мораль



r10k как самостоятельный продукт – бесполезен чуть менее чем полностью. Всё то, что он умеет и не умеет делать, может описать в bash-скрипте даже… автомеханик. Лично я бы поручил деплоинг и контроль версий специализированному продукту, например, jenkins‘у. Впрочем, это уже совсем другая история. (с)

3 thoughts on “Puppet with r10k [Best Practice]

  1. Подскажите, пожалуйста, стоит ли использовать r10k на puppet 4, если у меня environments это отдельный проект в gitlab?

    • Лично я б Вам порекомендовал в 20!8 гэ использовать для этих нужд либо gitlab CI, либо jenkins, либо если у Вас нет времени с этим разбираться, то да, можно и vcsrepo. r10k не развивается, в гит не принимаются новые pull request’ы, они даже не могут реализовать установку модулей с их зависимостями, хотя я открыл этот feature request в момент написания этой статьи. В общем, как я и писал в статье, категорически рекомендую Вам воздержаться от использования r10k.

Leave a Reply

Your email address will not be published. Required fields are marked *