Skip to content

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://[email protected]': 
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‘у. Впрочем, это уже совсем другая история. (с)

Published inIT

3 Comments

  1. Антон Антон

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

    • iglov iglov

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

  2. Антон Антон

    Или для этого случая достаточно будет vcsrepo?

Leave a Reply

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