Puppet язык. Master of puppets: Установка и настройка системы удаленного управления конфигурацией Puppet. Основы использования Puppet

Шла о том, что такое управление конфигурацией и как внедрить эту технологию в свою инфраструктуру.

Примечание : Руководство выполнено на Ubuntu 14.04 и Apache.

Данное руководство поможет подготовить автоматизированную оркестровку сервера с помощью инструмента конфигурационного управления Puppet. Вы ознакомитесь с основными терминами, синтаксисом и функциями Puppet. В результате вы получите полностью автоматизированное простое развёртывание, которое состоит из таких этапов:

  • Обновление индекса пакетов.
  • Установка Apache.
  • Создание пользовательского каталога document root.
  • Создание в нём файла index.html.
  • Применение шаблона для установки пользовательского виртуального хоста.
  • Перезапуск Apache.

Примечание : Данное руководство сосредоточено на создании манифестов – сценариев Puppet для автоматизации настройки. Больше о Puppet можно прочитать в статьях:

Начало работы

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

Терминология Puppet

  • Мастер Puppet: ведущий сервер, который управляет настройкой нод.
  • Агент Puppet: ведомая нода, которая подчиняется мастеру.
  • Манифест: сценарий оркестровки.
  • Ресурс: фрагмент кода, который определяет необходимые системе изменения.
  • Модуль: группа манифестов и других файлов, организованная заранее определенным образом, которая позволяет облегчить совместное и повторное использование ее отдельных частей оркестровки.
  • Класс: как и в любом обычном языке программирования, классы отвечают за организацию и повторное использование частей оркестровки.
  • Факты: глобальные переменные системы.
  • Сервисы: изменяют статус сервиса (запуск, остановка и т.д.).

Оркестровка Puppet разрабатывается на языке DSL, который основан на Ruby.

Ресурсы

Puppet определяет задачи с помощью ресурсов. Ресурсы могут представлять пакеты, файлы, сервисы, пользователей и команды. Они могут иметь состояние, которое будет приводить к изменению системы в случае, если состояние заявленного ресурса отличается от текущего состояния системы. Например, ресурс package с состоянием installed в манифесте запустит установку пакета, если такой пакет не был установлен ранее. Такой ресурс выглядит так:

package { "apache2":

ensure => "installed"

Ресурс exec позволяет выполнить любую команду:

exec { "apt-get update":

command => ‘/usr/bin/apt-get update’

Обратите внимание: apt-get update в приведённом выше примере является не объявлением команды, а идентификатором ресурса. Часто в Puppet нужно ссылаться на другие ресурсы, и для этого используются их идентификаторы.

Зависимость ресурсов

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

В качестве примера можно привести следующий код; он определяет зависимость ресурса, а уже затем сам ресурс:

package { "python-software-properties":

ensure => "installed"

}
exec { "add-repository":

command => "/usr/bin/add-apt-repository ppa:ondrej/php5 -y"
require => Package["python-software-properties"]

Опция require получает в качестве параметра ссылку на другой ресурс. В данном случае ресурс Package определяется пакетом python-software-properties.

Примечание : Объявления ресурсов начинаются с маленькой буквы (exec, package), а зависимости – с большой (Exec, Package).

К примеру, вам нужно сделать так, чтобы одна задача выполнялась перед второй. Для этого используется опция before.

package { "curl":

ensure => "installed"
before => Exec["install script"]

exec { "install script":

command => "/usr/bin/curl http://example.com/some-script.sh"

Формат манифестов

Манифесты – это наборы ресурсов с расширением.pp. Ниже приведён пример простого манифеста, который выполняет две задачи: обновляет индекс пакетов и устанавливает vim.

exec { "apt-get update":

command => "/usr/bin/apt-get update"

}
package { "vim":

ensure => "installed"
require => Exec["apt-get update"]

Примечание : В конце данного руководства вы найдёте полный код манифеста Puppet.

Написание манифеста

Переменные

Переменные можно определить в любой части манифеста. Наиболее распространёнными типами переменных являются строки и массивы строк, но Puppet поддерживает и другие типы.

Этот код определяет строку переменной, которую в дальнейшем можно использовать в манифесте:

$package = "vim"
package { $package:

ensure => "installed"

Циклы

Циклы, как правило, используются для повторения задачи с помощью различных входных значений. То есть, вместо того чтобы создавать 10 задач для установки 10 различных пакетов, вы можете создать одну задачу и использовать цикл, чтобы повторить задачу для установки любых пакетов.

Проще всего определить цикл в Puppet с помощью массива, например:

$packages = ["vim", "git", "curl"]
package { $packages:

ensure => "installed"

С версии 4 Puppet поддерживает дополнительные пути для перебора задач. Приведенный ниже код делает то же самое, что и предыдущий код, но на этот раз используется итератор each. Эта опция упрощает создание циклов ресурсов:

$packages.each |String $package| {
package { $package:

ensure => "installed"

Использование условных выражений

Условные выражения можно использовать для динамической настройки (например, когда на основе переменной или вывода команды нужно решить, следует ли выполнять задачу).

Puppet поддерживает большую часть условных структур традиционных языков программирования (например, выражения if/else и case); кроме того, некоторые ресурсы (например, exec), поддерживают атрибуты, которые работают как условные выражения, но принимают как условие только выходные данные команды.

Допустим, вы хотите выполнить команду, основываясь на факте. В таком случае, чтобы проверить значение переменной, вам необходимо использовать одну из поддерживаемых условных структур поддерживается, например if/else:

if $osfamily != "Debian" {

warning("This manifest is not supported on this OS.")

notify { "Good to go!": }

Также условные выражения часто используются в IT-автоматизации, если выполнение одной команды зависит от вывода другой команды. В таких случаях используются onlyif или unless, как показано в примере ниже. Следующая команда будет выполнена только в том случае, если вывод /bin/which php успешен:

command => "/bin/echo PHP is installed here > /tmp/test.txt",
onlyif => "/bin/which php"

Аналогично, выражение unless выполнит команду, только если команда в unless не была выполнена.

command => "/bin/echo PHP is NOT installed here > /tmp/test.txt",
unless => "/bin/which php"

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

Шаблоны обычно используются в конфигурационных файлах и позволяют добавлять переменные и другие функции, которые делают эти файлы более универсальными и обеспечивают их повторное выполнение. Puppet поддерживает два формата шаблонов

  • Embedded Puppet (EPP): работает только с Puppet 4+.
  • Embedded Ruby (ERB)

Ниже приведён пример шаблона ERB для создания виртуального хоста Apache, в котором используется переменная для создания корневого каталога этого хоста:


ServerAdmin webmaster@localhost
DocumentRoot <%= @doc_root %>
>
AllowOverride All
Require all granted

Чтобы применить шаблон, нужно создать ресурс file, который отображает содержание шаблона с помощью метода template. Чтобы заменить виртуальный хост Apache по умолчанию, используйте такой шаблон:

ensure => "present",
content => template("apache/vhost.erb")

В данном случае Puppet будет искать шаблон vhost.tpl в каталоге apache/templates.

Определение сервисов

Ресурсы сервисов изменяют состояние системного сервиса (например, останавливают или перезапускают его).

Рассмотрим предыдущий пример шаблона, который предназначен для создания виртуального хоста Apache. Чтобы обеспечить перезагрузку Apache после изменения виртуального хоста, нужно создать ресурс сервиса. Это делается так:

service { "apache2":

ensure => running,
enable => true

Чтобы определить ресурс, используйте опцию notify.

file { "/etc/apache2/sites-available/000-default.conf":

ensure => "present",
content => template("vhost.erb"),
notify => Service["apache2"]

Пример манифеста

Теперь можно собрать весь код данного руководства в один манифест, который будет автоматизировать установку Apache в Ubuntu 14.04.

Примечание: Дополненный вариант манифеста можно найти на Github . Также эта папка содержит файл Vagrant, который позволяет протестировать манифест на упрощённой установке с помощью виртуальной машины Vagrant .

$doc_root = "/var/www/example"
exec { "apt-get update":

command => "/usr/bin/apt-get update"

}
package { "apache2":

ensure => "installed",
require => Exec["apt-get update"]

}
file { $doc_root:

ensure => "directory",
owner => "www-data",
group => "www-data",
mode => 644

}
file { "$doc_root/index.html":

ensure => "present",
source => "puppet:///modules/main/index.html",
require => File[$doc_root]

}
file { "/etc/apache2/sites-available/000-default.conf":

ensure => "present",
content => template("main/vhost.erb"),
notify => Service["apache2"],
require => Package["apache2"]

}
service { "apache2":

ensure => running,
enable => true

  • В первой строке находится переменная $doc_root, которая в дальнейшем используется для объявления ресурса.
  • Строки 3-5: ресурс exec выполняет команду apt-get update.
  • Строки 7-10: ресурс package устанавливает пакет apache2, зависит от apt-get update. То есть этот ресурс будет выполнен только если выполнится требуемый ресурс.
  • Строки 12-17: ресурс file создаёт новый корневой каталог. Ресурс file может создавать файлы и каталоги, применять шаблоны и копировать локальные файлы на удалённый сервер. Эта задача может быть выполнена на любом этапе оркестровки, потому ей не нужны зависимости.
  • Строки 19-23: ещё один ресурс file копирует файл index.html в корневой каталог на сервере. Параметр source позволяет Puppet найти исходный файл. Этот код основан на методе обработки локальных файлов в Puppet. В репозитории Github можно найти структуру каталогов, которая позволит Puppet найти этот ресурс. Корневой каталог нужно создать до выполнения этого ресурса, потому здесь применяется опция require.
  • Строки 25-30: этот ресурс file применяет шаблон Apache и перезапускает сервис. В данном примере оркестровка организована с помощью модуля main (потому исходным шаблоном будет main/vhost.erb). Опция require обеспечивает выполнение ресурса только в том случае, если установлен пакет apache2.
  • Строки 32-35: ресурс service перезапускает сервис apache2.

Заключение

Puppet – это производительный инструмент управления конфигурацией, который использует язык DSL для управления ресурсами сервера и автоматизации задач. Этот язык предлагает дополнительные ресурсы, которые обеспечивают гибкость оркестровки.

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

Tags: ,

Статья написана в журнале Системный администратор

World Revolution

Управление множеством Unix систем нельзя называть комфортабельным. Для конфигурации 1-го параметра администратору приходится обращаться к каждой машине, скрипты только частично могут помочь, ну и не во всех ситуациях.

Следует признать, что администраторы Windows сетей находятся все-таки в более успешном положении. Достаточно поменять функции групповых политик и через некоторое время все компютеры сети, в том числе и с не так издавна установленной операционной системой “выяснят” о нововведении, если они их естественно касаются.

Оглянувшись на длиннющий период развития Unix, можно узреть, что ничего подобного так и не прижилось. Есть решения вроде kickstart, которые помогают при первичной установке операционной системы, но грядущая доводка потребует важных усилий.

Коммерческие решения вроде BladeLogic и OpsWare , делему автоматизации опций решают только отчасти, основное их достоинство наличие графического интерфейса, ну и позволить их приобрести могут только в огромных организациях. Есть естественно и проекты предлагающие свободные решения, но за всегда собственного существования они так и не смогли сделать большого общества.

Например Cfengine не очень пользуется популярностью у администраторов, хотя не считая Linux, может употребляться в *BSD, Windows и Mac OS X. Может быть это связано с относительной сложностью в разработке конфигураций. При описании заданий приходится учитывать особенности каждой определенной системы, и вручную контролировать последовательность действий при выполнении команд.

Другими словами администратор должен держать в голове, что для одних систем следует писать adduser для других useradd, учитывать размещение файлов в разных системах, и т.д.. Это на порядок усложняет процесс написания команд, с ходу сделать правильную конфигурацию очень тяжело, а изготовленные конфигурации прочитать через некоторое время практически не реально.

Не смотря на GPL лицензию Cfengine фактически проект 1-го человека, который контролирует все конфигурации и не очень заинтересован в построении открытого общества. В конечном итоге возможности cfengine вполне удовлетворяют разработчика, а для других администраторов это резвее лишняя боль в голове.

Чтобы улучшить cfengine сторонними разработчиками были изготовлены различные дополнения, что часто только ухудшало ситуацию. Создатель нескольких таких модулей к cfengine Люке Каниес (Luke Kanies) в итоге решил сделать похожий инструмент, но лишенный многих недостатков cfengine.

Возможности Puppet

Puppet как и cfengine является клиент-серверной системой использующей декларативный, другими словами неотклонимый для выполнения язык для описания задач и библиотеки для их реализации. Клиенты периодически (по умолчанию 30 минут) соединяются с центральным сервером и получают последнюю конфигурацию.

Если обретенные функции не совпадают с системным состоянием, они будут выполнены, при необходимости серверу отсылается отчет о изготовленных операциях. Сервер сообщения может сохранить в syslog или файл, сделать RRD график, отослать на обозначенный e-mail.

Дополнительные уровни абстракции Transactional и Resource обепечивают наивысшую сопоставимость с существующими опциями и приложениями, позволяя сфокусироваться на системных объектах, не заботясь о различиях в реализации и описании подробных команд и форматах файлов. Администратор оперирует только с типом объекта, остальное Puppet берет на себя. Так тип packages знает о Семнадцать пакетных системах, подходящая автоматом будет распознана на основании инфы о версии дистрибутива или системы, хотя при необходимости пакетный менеджер можно задать принудительно.

В отличие от скриптов, которые часто не может быть использовать в других системах, конфигурации Puppet написанные сторонними администраторами будут в большинстве без заморочек работать в хоть какой другой сети. В Puppet CookBook уже имеется три 10-ка готовых рецептов. В настоящее время Puppet официально поддерживает следующие операционные системы и сервисы: Debian, RedHat/Fedora, Solaris, SUSE, CentOS, Mac OS X, OpenBSD, Gentoo и MySQL, LDAP.

Язык Puppet

Чтобы идти дальше, поначалу следует разобраться с основными элементами и возможностями языка. Язык это одна из сильных сторон Puppet. С его помощью описываются ресурсы которыми администратор планирует управлять и деяния.

В отличие от большинства похожих решений, в Puppet язык позволяет упростить обращение ко всем схожим ресурсам на хоть какой системе в гетерогенной среде. Описание ресурса, обычно, состоит из наименования, типа и атрибутов. Например укажем на файл /etc/passwd и установим его атрибуты:

file { «/etc/passwd»:

owner => root,

group => root,

На данный момент клиенты, подключившись к серверу скопируют файл /etc/passwd и установят обозначенные аттрибуты. В одном правиле можно определять слету несколько ресурсов, разделяя их с помощью точки с запятой.

А что делать если конфигурационный файл используемый на сервере отличается от клиентских или вообще не употребляется? Например такая ситуация может показаться при настройках VPN соединений. В этом случае следует на файл можно указать директивой source.

Здесь два варианта, как обычно указать путь к другому файлу, также поддерживается два URI протокола: file и puppet. В первом случае употребляется ссылка на внешний NFS сервер, во втором варианте на сервере Puppet, запускается NFS похожий сервис, который и экспортирует ресурсы.

В последнем случае по умолчанию путь указывается относительно корневого каталога puppet - /etc/puppet. Другими словами ссылка puppet://server.domain.com/config/sshd_config будет соответствовать файлу /etc/puppet/config/sshd_config.

Переопределить этот каталог, можно с помощью директивы filebucket, хотя более правильно использовать одноименную секцию в файле /etc/puppet/fileserver.conf. В этом случае можно ограничить доступ к сервису только с определенных адресов. Например опишем секцию config.

path /var/puppet/config

allow *.domain.com

allow 192.168.0.*

allow 192.168.1.0/24

deny *.wireless.domain.com

А позже обращаемся к этой секции при описании ресурса.

source => «puppet://server.domain.com/config/sshd_config»

Перед двоеточием располагается название ресурса. В самых обыденных случаях в качестве имени можно просто указатьлучше использовать псевдоним или переменные. Псевдоним устанавливается с помощью директивы alias. полный путь к файлу. В более сложных конфигурациях

file { «/etc/passwd»:

alias => passwd

Другой вариант сотворения псевдонима, прекрасно подходит в данном случае, когда приходится иметь дело с разными операционными системами. Например, создадим ресурс описывающий файл sshd_config:

file { sshdconfig:

name => $operatingsystem ? {

solaris => «/usr/local/etc/ssh/sshd_config»,

default => «/etc/ssh/sshd_config»

В этом примере мы столкнулись с возможностью выбора. Раздельно указан файл для Solaris, для всех других будет избран файл /etc/ssh/sshd_config. На данный момент к этому ресурсу можно обращаться как к sshdconfig, зависимо от операционной системы будет избран подходящий путь.

Например укажем, что в случае если бес sshd запущен и получен новый файл, следует перезапустить сервис.

ensure => true,

subscribe => File

Переменные часто используются при работе с пользовательскими данными. Например описываем месторасположение домашнних каталогов юзеров:

$homeroot = «/home»

На данный момент к файлам определенного пользователя можно обратиться как

${homeroot}/$name

В параметр $name будет подставлено учетное имя пользователя. В некоторых случаях комфортабельно отыскать значение по умолчанию для некоторого типа. Например для типа exec очень часто указывают сборники в каких он должен отыскивать исполняемый файл:

Exec { path => «/usr/bin:/bin:/usr/sbin:/sbin» }

В том случе если нужно указать на несколько вложенных файлов и каталогов, можно использовать параметр recurse.

file { «/etc/apache2/conf.d»:

source => «puppet:// puppet://server.domain.com/config/apache/conf.d»,

recurse => «true»

Несколько ресурсов могут быть объеденены в классы или определения. Классы являются законченным описанием системы или сервиса и употребляются обособленно.

«/etc/passwd»: owner => root, group => root, mode => 644;

«/etc/shadow»: owner => root, group => root, mode => 440

Как и в объектно-ориентированных языках классы могут переопределяться. Например в FreeBSD группой-владельцем этих файлов является wheel. Поэтому чтобы не переписывать ресурс полностью, создадим новый класс freebsd, который будет наследовать класс linux:

class freebsd inherits linux {

File["/etc/passwd"] { group => wheel };

File["/etc/shadow"] { group => wheel }

Для удобства все классы можно вынести в отдельный файл, который подключать директивой include. Определения могут принимать многочисленные свойства в качестве аргументов, но не поддерживают наследования и употребляются в данном случае если нужно описать не один раз используемые объекты. Например определим домашний каталог юзеров и команды нужные для сотворения новой учетной записи.

define user_homedir ($group, $fullname, $ingroups) {

user { «$name»:

ensure => present,

comment => «$fullname»,

gid => «$group»,

groups => $ingroups,

membership => minimum,

shell => «/bin/bash»,

home => «/home/$name»,

require => Group[$group],

exec { «$name homedir»:

command => «/bin/cp -R /etc/skel /home/$name; /bin/chown -R $name:$group /home/$name»,

Puppet - это кроссплатформенная структура, позволяющая системным администраторам выполнять общие задачи с использованием кода. Код позволяет выполнять различные задачи от установки новых программ до проверки прав доступа файлов или обновлений пользовательских учетных записей. Puppet превосходна не только в процессе изначальной установки системы, но и на протяжении всего жизненного цикла системы. В большинстве случаев puppet используется в конфигурации клиент/сервер.

Этот раздел показывает установку и настройку Puppet в конфигурации клиент/сервер. Этот простой пример демонстрирует как установить Apache с использованием Puppet .

Установка

Для установки Puppet введите в терминале:

Sudo apt-get install puppetmaster

На клиентской машине (или машинах) введите:

Sudo apt-get install puppet

Настройка

Прежде чем настраивать puppet вам возможно захочется добавить запись DNS CNAME для puppet.example.com , где example.com - это ваш домен. По умолчанию клиенты Puppet проверяют DNS на наличие puppet.example.com в качестве имени puppet сервера (Puppet Master ). Смотрите Служба доменных имен для дополнительных деталей использования DNS .

Если вы не предполагаете использовать DNS , вы можете добавить записи в файл /etc/hosts на сервере и клиенте. Например, в файл /etc/hosts Puppet сервера добавьте:

127.0.0.1 localhost.localdomain localhost puppet 192.168.1.17 meercat02.example.com meercat02

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

192.168.1.16 meercat.example.com meercat puppet

Замените IP адреса и доменные имена из примера на ваши актуальные адреса и имена сервера и клиентов.

Теперь настроим некоторые ресурсы для apache2 . Создайте файл /etc/puppet/manifests/site.pp , содержащий следующее:

Package { "apache2": ensure => installed } service { "apache2": ensure => true, enable => true, require => Package["apache2"] }

Node "meercat02.example.com" { include apache2 }

Замените meercat02.example.com на актуальное имя вашего Puppet клиента.

Финальным шагом для этого простого Puppet сервера является перезапуск сервиса:

Sudo /etc/init.d/puppetmaster restart

Теперь на Puppet сервере все настроено и время настроить клиента.

Сначала настроим сервис Puppet агента для запуска. Отредактируйте /etc/default/puppet, заменив значение START на yes :

Sudo /etc/init.d/puppet start

Возвращаемся на Puppet сервер для подписи клиентского сертификата с помощью команды:

Sudo puppetca --sign meercat02.example.com

Проверьте /var/log/syslog на любые ошибки конфигурации. Если все прошло хорошо, пакет apache2 и его зависимости будут установлены на Puppet клиенте.

Этот пример очень простой и не показывает многие возможности и преимущества Puppet . Для дополнительной информации смотрите

Администрирование виртуальных серверов с использованием Puppet

Часть 1. Установка и настройка Puppet

Серия контента:

В процессе организации серверной среды с использованием средств виртуализации или облачных сервисов быстро растет количество отдельных серверов. Каждый раз при создании нового сервера возникает необходимость установки и конфигурации соответствующего программного обеспечения. Более того, синхронизация серверных конфигураций требует дополнительных усилий, таких, например, как написание cценариев на языке командной оболочки shell .

С помощью программного средства Puppet можно быстро создать новый сервер и настроить его параметры буквально в несколько команд без каких-либо затруднений. Кроме того, Puppet будет периодически синхронизировать конфигурации созданных серверов.

Несмотря на то, что эта программа обычно используется для управления крупными серверными структурами (например, в дата-центрах или на Web-сервисах с большим количеством пользователей), её вполне можно применить и для обслуживания нескольких серверов (скажем, в локальной сети небольшого офиса или в домашней сети).

История Puppet

Проект Puppet является разработкой компании Puppet Labs и распространяется как ПО с открытым исходным кодом (Open Source Software). Программа имеет гибкую модульную структуру: в настоящее время для Puppet написано уже более 200 модулей расширения.

Puppet поддерживается не только компанией-разработчиком, но и весьма активным сообществом пользователей .

Установка и подготовка Puppet к работе

Функционирование Puppet организовано по схеме "клиент-сервер". Каждый клиент периодически устанавливает связь с главным управляющим сервером (или несколькими такими серверами) и выполняет синхронизацию конфигурации. По умолчанию такие сеансы связи происходят каждые полчаса. Поэтому для обеспечения нормальной работы Puppet потребуются как минимум два установленных сервера: один будет выполнять функции главного управляющего сервера (master server), а другой (или другие) выступать в роли подчинённых ему серверов, то есть, в данном контексте можно назвать их серверами-"клиентами".

Для того, чтобы установить Puppet на хосте, который будет управлять другими серверами в качестве главного управляющего сервера, необходимо выполнить команды, показанные в листинге 1. Следует отметить, что эти команды выполняются от имени суперпользователя root .

Листинг 1. Установка пакета puppet-server на главный управляющий сервер
# yum -y install puppet-server # chkconfig puppetmaster on # service puppetmaster start

Пакеты для подчинённых серверов устанавливаются на клиентских хостах, как показано в листинге 2 (команды выполняются также от имени суперпользователя root ).

Листинг 2. Установка пакета puppet на хосте-клиенте
# yum -y install puppet # chkconfig puppet on # service puppet start

Если хост главного управляющего сервера защищён сетевым экраном, а хосты-клиенты расположены "снаружи" относительно этого сетевого экрана (например, компьютеры в локальной сети), то на главном сервере необходимо открыть TCP-порт с номером 8140 и, по возможности, сделать его доступным только для клиентских хостов. Если все операции будут выполняться на одном компьютере (localhost), то никаких манипуляций с сетевым экраном не требуется.

Основы использования Puppet

С точки зрения Puppet все конфигурации определяются и описываются как ресурсы (resources ), которые можно назвать основными структурными компонентами управляющей среды. Ресурсами могут быть файлы, сервисы (server services), программные пакеты (software packages) и т.д. Более того, ресурсом может быть даже одиночный вызов команды оболочки shell. Например, описываемый в листинге 3 ресурс типа file представляет известный всем файл /etc/passwd, владельцем которого является root .

Листинг 3. Описание ресурса - файла /etc/passwd
file { "/etc/passwd": owner => root, mode => 644, }

Ресурсы можно группировать по определённым характеристикам: так, например, любой файл имеет владельца и расположен по конкретному адресу (path) в файловой системе, у каждого пользователя есть регистрационное имя (login), личный идентификатор (UID) и идентификатор группы (GID). В соответствии с этими характеристиками формируются типы ресурсов. Кроме того, самые важные характеристики типа ресурса в общем смысле одинаковы для любых операционных систем, независимо от незначительных деталей реализации. То есть описание ресурса вполне можно абстрагировать от его реализации в той или иной операционной системе.

На основе вышеописанных предпосылок сформирован уровень абстракции ресурсов (resource abstraction layer - RAL ) программы Puppet. RAL разделяет ресурсы на типы (types ), являющиеся моделями высокого уровня, и провайдеры (providers ), которые представляют более низкий уровень, то есть реализации ресурсов, зависящие от конкретной платформы. Такая организация RAL позволяет составлять описания ресурсов способом, применимым практически на любой системе.

Цикл синхронизации RAL

Puppet использует RAL как для чтения, так и для изменения состояния ресурсов системы. Являясь декларативной системой контроля и управления, Puppet начинает рабочий цикл с получения информации о том, в каком состоянии должен находиться тот или иной ресурс. При синхронизации ресурса используется RAL для запроса текущего состояния, сравнения его с требуемым и внесения всех необходимых изменений при обнаружении каких-либо различий.

Структура описания ресурса

Как было сказано выше, в Puppet каждый ресурс является экземпляром некоторого типа (resource type ), с указания которого начинается собственно описание. Ресурс идентифицируется именем (title ), которое записывается в одиночных кавычках после открывающей фигурной скобки и сопровождается символом двоеточия. Далее с новой строки определяются атрибуты типа (attributes ), причём некоторые атрибуты являются общими для всех типов, другие же присущи только данному конкретному типу ресурса. Каждый атрибут имеет значение (value ), таким образом, записи атрибутов с соответствующими значениями имеют общую форму attribute => value .

Общее представление о синтаксисе языка описания ресурсов Puppet можно получить из листинга 4, в котором показан самый простой случай - описание ресурса типа "пользователь" (user ).

Листинг 4. Синтаксис языка описания ресурсов Puppet на примере пользователя
user { "alex": ensure => present, uid => "501", gid => "admin", shell => "/bin/bash", home => "/home/alex", managehome => true, }

Каждая строка определения атрибута заканчивается запятой, а закрывающая фигурная скобка сообщает о том, что описание ресурса завершено.

Следующая конфигурация, демонстрируемая в листинге 5, позволяет установить пакет openssh-server , разрешить использование сервиса sshd по умолчанию и выполнить проверку, чтобы убедиться в том, что этот сервис действительно активизирован и работает.

Листинг 5. Описание ресурса - сервиса sshd (установка, запуск, проверка)
package { "openssh-server": ensure => installed, } service { "sshd": enable => true, ensure => running, require => Package["openssh-server"], }

Теперь необходимо применить описанные выше конфигурации к соответствующим серверам. В пакет Puppet по умолчанию включён специальный файл конфигурирования ресурсов site.pp , который располагается в каталоге /etc/puppet/manifests . Если параметры конфигурации ресурсов не очень сложны, то их можно добавить в этот файл вручную: например, содержимое вышеприведённых листингов 3 и 4.

После того, как все требуемые программы установлены и активированы, а файлы конфигурации сформированы, обязательно нужно зарегистрировать все подчинённые серверы (клиенты) на главном управляющем сервере и подтвердить достоверность регистрации (sign ), то есть пройти своеобразную сертификацию. На подчинённых серверах регистрация выполняется следующей командой (также требуются права суперпользователя root ):

puppetd --test --waitforcert 30 --server MASTER_SERVER_ADDRESS

Вместо MASTER_SERVER_ADDRESS следует указать реальный адрес главного управляющего сервера.

После регистрации всех необходимых клиентов на главном управляющем сервере выполняются команды, показанные в листинге 6.

Листинг 6. Сертификация зарегистрированных клиентов на главном управляющем сервере
puppetca --list # выводится список адресов зарегистрированных клиентов puppetca --sign CLIENT_SERVER_ADDRESS # вместо CLIENT_SERVER_ADDRESS следует указать реальный адрес клиента # команда повторяется для адреса каждого клиента

После завершения операций регистрации и сертификации Puppet автоматически применит описанные выше конфигурации ресурсов на зарегистрированных клиентах.

# здесь также записывается реальный адрес сервера server = MASTER_SERVER_ADDRESS

Теперь Puppet полностью настроен и работает. Автоматическая синхронизация конфигураций ресурсов подчинённых серверов будет производиться каждые 30 минут. Пронаблюдать процесс можно выполнив команду:

tail -f /var/log/messages

Заключение

В этой статье мы рассмотрели процесс настройки и конфигурации Puppet на главном управляющем сервере и клиентских серверах, состояние которых и будет отслеживаться. В следующей статье данного цикла будут рассмотрены примеры конфигурации Puppet для выполнения стандартных задач системного администратора.

Сергей Яремчук

Централизованная настройка UNIX-систем с помощью Puppet

Управление большим количеством UNIX-систем нельзя назвать удобным. Для изменения одного параметра администратору приходится обращаться к каждой машине, скрипты лишь частично могут помочь, да и не во всех ситуациях.

Следует признать, что администраторы Windows-сетей находятся все-таки в более выгодном положении. Достаточно изменить настройки групповых политик, и через некоторое время все компьютеры сети, в том числе и с недавно установленной операционной системой, «узнают» о нововведении, если они их, конечно, касаются. Оглянувшись на долгий период развития UNIX, можно заметить, что ничего подобного так и не прижилось. Есть решения вроде kickstart, которые помогают при первичной установке операционной системы, но дальнейшая доводка потребует значительных усилий. Коммерческие решения, вроде BladeLogic и OpsWare , проблему автоматизации настроек решают лишь отчасти, основное их достоинство – наличие графического интерфейса, да и позволить их приобрести могут только крупные организации. Есть, конечно, и проекты, предлагающие свободные решения, но за все время своего существования они так и не смогли создать большого сообщества. Например, Cfengine не очень пользуется популярностью уадминистраторов, хотя, кроме Linux, может использоваться в *BSD, Windows и Mac OS X. Возможно, это связано с относительной сложностью в создании конфигураций. Приописании заданий приходится учитывать особенности каждой конкретной системы и вручную контролировать последовательность действий при выполнении команд. То есть администратор должен помнить, что для одних систем следует писать adduser для других – useradd, учитывать расположение файлов в разных системах и так далее. Это на порядок усложняет процесс написания команд, с ходу создать правильную конфигурацию очень сложно, а созданные конфигурации прочитать через некоторое время практически нереально. Несмотря на GPL-лицензию Cfengine, фактически проект одного человека, который контролирует все изменения и не очень заинтересован в построении открытого общества. В результате возможности Cfengine вполне удовлетворяют разработчика, а для остальных администраторов это скорее лишняя головная боль. Чтобы улучшить Cfengine, сторонними разработчиками были созданы различные дополнения, что часто только ухудшало ситуацию. Автор нескольких таких модулей к Cfengine Люке Каниес (Luke Kanies) витоге решил разработать подобный инструмент, но лишенный многих недостатков Cfengine.

Возможности Puppet

Puppet , как и Cfengine, является клиент-серверной системой, использующей декларативный, то есть обязательный для выполнения язык для описания задач и библиотеки дляихреализации. Клиенты периодически (по умолчанию каждые 30 минут) соединяются с центральным сервером и получают последнюю конфигурацию. Если полученные настройки не совпадают с системным состоянием, они будут выполнены, при необходимости серверу отсылается отчет о произведенных операциях. Сервер сообщения может сохранить вsyslog или файл, создать RRD-график, отослать на указанный e-mail. Дополнительные уровни абстракции Transactional и Resource обеспечивают максимальную совместимость ссуществующими настройками и приложениями, позволяя сфокусироваться на системных объектах, не заботясь о различиях в реализации и описании подробных команд иформатах файлов. Администратор оперирует лишь с типом объекта, остальное Puppet берет на себя. Так, тип packages знает о 17 пакетных системах, нужная автоматически будет распознана на основании информации о версии дистрибутива или системы, хотя при необходимости пакетный менеджер можно задать принудительно.

В отличие от скриптов, которые часто невозможно использовать в других системах, конфигурации Puppet, написанные сторонними администраторами, будут в большинстве безпроблем работать в любой другой сети. В Puppet CookBook уже имеется три десятка готовых рецептов. В настоящее время Puppet официально поддерживает следующие операционные системы и сервисы: Debian, RedHat/Fedora, Solaris, SUSE, CentOS, Mac OS X, OpenBSD, Gentoo и MySQL, LDAP.

Язык Puppet

Чтобы идти дальше, вначале следует разобраться с основными элементами и возможностями языка. Язык – это одна из сильных сторон Puppet. С его помощью описываются ресурсы, которыми администратор планирует управлять, и действия. В отличие от большинства подобных решений, в Puppet язык позволяет упростить обращение ко всем схожим ресурсам на любой системе в гетерогенной среде. Описание ресурса, как правило, состоит из названия, типа и атрибутов. Например, укажем на файл /etc/passwd и установим его атрибуты:

file { "/etc/passwd":

Owner => root,

Group => root,

Mode => 644,

Теперь клиенты, подключившись к серверу, скопируют файл /etc/passwd и установят указанные атрибуты. В одном правиле можно определять сразу несколько ресурсов, разделяя их с помощью точки с запятой. А что делать, если конфигурационный файл, используемый на сервере, отличается от клиентских или вообще не используется? Например, такая ситуация может возникнуть при настройках VPN-соединений. В этом случае следует указать на файл директивой source. Здесь два варианта, можно, как обычно указать путь кдругому файлу, а также с помощью поддерживающихся двух URI протоколов: file и puppet. В первом случае используется ссылка на внешний NFS-сервер, во втором варианте насервере Puppet запускается NFS-подобный сервис, который и экспортирует ресурсы. В последнем случае по умолчанию путь указывается относительно корневого каталога puppet– /etc/puppet. То есть ссылка puppet://server.domain.com/config/sshd_config будет соответствовать файлу /etc/puppet/config/sshd_config. Переопределить этот каталог можно спомощью директивы filebucket, хотя более правильно использовать одноименную секцию в файле /etc/puppet/fileserver.conf. В этом случае можно ограничить доступ к сервису только сопределенных адресов. Например, опишем секцию config:

Path /var/puppet/config

Allow *.domain.com

Allow 127.0.0.1

Allow 192.168.0.*

Allow 192.168.1.0/24

Deny *.wireless.domain.com

А затем обращаемся к этой секции при описании ресурса:

source => "puppet://server.domain.com/config/sshd_config"

Перед двоеточием располагается название ресурса. В самых простых случаях в качестве имени можно просто указать полный путь к файлу. В более сложных конфигурациях лучше использовать псевдоним или переменные. Псевдоним устанавливается с помощью директивы alias:

file { "/etc/passwd":

Alias => passwd

Другой вариант создания псевдонима хорошо подходит в том случае, когда приходится иметь дело с разными операционными системами. Например, создадим ресурс, описывающий файл sshd_config:

file { sshdconfig:

Name => $operatingsystem ? {

Solaris => "/usr/local/etc/ssh/sshd_config",

Default => "/etc/ssh/sshd_config"

В этом примере мы столкнулись с возможностью выбора. Отдельно указан файл для Solaris, для всех остальных будет выбран файл /etc/ssh/sshd_config. Теперь к этому ресурсу можно обращаться как к sshdconfig, в зависимости от операционной системы будет выбран нужный путь. Например, укажем, что в случае, если демон sshd запущен и получен новый файл, следует перезапустить сервис:

service { sshd:

Ensure => true,

Subscribe => File

Переменные часто используются при работе с пользовательскими данными. Например описываем месторасположение домашних каталогов пользователей:

$homeroot = "/home"

Теперь к файлам конкретного пользователя можно обратиться как:

${homeroot}/$name

В параметр $name будет подставлено учетное имя пользователя. В некоторых случаях удобно определить значение по умолчанию для некоторого типа. Например, для типа exec очень часто указывают каталоги, в которых он должен искать исполняемый файл:

Exec { path => "/usr/bin:/bin:/usr/sbin:/sbin" }

В том случае, если нужно указать на несколько вложенных файлов и каталогов, можно использовать параметр recurse:

file { "/etc/apache2/conf.d":

Source => "puppet:// puppet://server.domain.com/config/apache/conf.d",

Recurse => "true"

Несколько ресурсов могут быть объединены в классы или определения. Классы являются законченным описанием системы или сервиса и используются обособленно:

class linux {

File {

"/etc/passwd": owner => root, group => root, mode => 644;

"/etc/shadow": owner => root, group => root, mode => 440

Как и в объектно-ориентированных языках, классы могут переопределяться. Например, в FreeBSD группой-владельцем этих файлов является wheel. Поэтому, чтобы не переписывать ресурс полностью, создадим новый класс freebsd, который будет наследовать класс linux:

class freebsd inherits linux {

File["/etc/passwd"] { group => wheel };

File["/etc/shadow"] { group => wheel }

Для удобства все классы можно вынести в отдельный файл, который нужно подключать директивой include. Определения могут принимать многочисленные параметры в качестве аргументов, но не поддерживают наследования и используются в том случае, если нужно описать многократно используемые объекты. Например, определим домашний каталог пользователей и команды, необходимые для создания новой учетной записи:

define user_homedir ($group, $fullname, $ingroups) {

User { "$name":

Ensure => present,

Comment => "$fullname",

Gid => "$group",

Groups => $ingroups,

Membership => minimum,

Shell => "/bin/bash",

Home => "/home/$name",

Require => Group[$group],

Exec { "$name homedir":

Command => "/bin/cp -R /etc/skel /home/$name; /bin/chown -R $name:$group /home/$name",

Creates => "/home/$name",

Require => User[$name],

Теперь, чтобы создать новую учетную запись, достаточно обратиться к user_homedir:

user_homedir { "sergej":

Group => "sergej",

Fullname => "Sergej Jaremchuk",

Ingroups => ["media", " admin]

Отдельно стоят описания узлов (node), которые поддерживают наследование, как и классы. При подключении клиента к серверу Puppet будет произведен поиск соответствующей секции node и выданы специфические только для этого компьютера настройки. Для описания всех остальных систем можно использовать node default. Описание всех типов приведено в документе «Type Reference», с которым необходимо ознакомиться в любом случае, хотя бы для того, чтобы понять все возможности языка Puppet. Различные типы позволяют выполнять указанные команды, в том числе и при выполнении определенных условий (например, изменение конфигурационного файла), работать с cron, учетными данными и группами пользователей, компьютерами, монтированием ресурсов, запуском и остановкой сервисов, установкой, обновлением и удалением пакетов, работой с SSH-ключами, зонами Solaris и так далее. Вот так просто можно заставить обновлять список пакетов в дистрибутивах, использующих apt, ежедневно между 2 и 4 часами:

schedule { daily:

Period => daily,

Range =>

exec { "/usr/bin/apt-get update":

Schedule => daily

Обновление за тот период каждой системой будет выполнено только один раз, после чего задание считается выполненным и будет удалено с клиентского компьютера. Язык Puppet поддерживает другие привычные структуры: условия, функции, массивы, комментарии и подобные.

Установка Puppet

Для работы Puppet потребуются Ruby (начиная с версии 1.8.1 и выше) с поддержкой OpenSSL и библиотеками XMLRPC, а также библиотека Faster . В репозитарии Ubuntu 7.04, который использовался при тестовой установке, уже включен пакет puppy:

$ sudo apt-cache search puppet

~$ ruby -rxmlrpc/client -e "puts:yep"

yep

Если не получено ошибок, значит, все необходимое уже включено. Файлы, в которых описывается желательная конфигурация систем, в терминологии Puppet называются манифестами (manifests). При запуске демон пытается прочитать файл /etc/puppet/manifests/site.pp, при его отсутствии выдает предупреждающее сообщение. При тестировании можно указать демону на работу в автономном режиме, при котором манифест не требуется:

$ sudo /usr/bin/puppetmasterd --nonodes

При необходимости к site.pp можно подключать другие файлы, например, с описаниями классов. Для тестового запуска в этот файл можно занести самую простую инструкцию.

class sudo {

File { "/etc/sudoers":

Owner => root,

Group => root,

Mode => 440,

node default {

Include sudo

Все конфигурационные файлы, как сервера так и клиентов, расположены в /etc/puppet. Файл fileserver.conf, о котором мы уже говорили, не обязателен и используется только в том случае, когда Puppet будет работать еще и как файл-сервер. В Ubuntu в этом файле экспортируется подкаталог /etc/puppet/files. В подкаталоге ssl расположены сертификаты и ключи, которые будут использоваться для шифрования при подключениях клиентов. Ключи создаются автоматически при первом запуске puppetmasterd, вручную их можно создать командой:

$ sudo /usr/bin/puppetmasterd --mkusers

Файлы puppetd.conf и puppetmasterd.conf похожи. В них указываются некоторые параметры работы демонов на клиентской системе и сервере. Клиентский файл отличается только наличием параметра server, указывающего на компьютер, на котором запущен puppetmasterd:

server = grinder.com

logdir = /var/log/puppet

vardir = /var/lib/puppet

rundir = /var/run

# отсылаем отчет серверу

report = true

Чтобы не печатать все вручную, можно создать шаблон с помощью самого puppetd:

$ puppetd --genconfig > /etc/puppet/puppetd.conf

Аналогично можно создать и site.pp на сервере:

$ puppetd --genmanifest > /etc/puppet/manifests/site.pp

Еще один файл tagmail.conf, позволяет указать почтовые адреса, на которые будут отсылаться отчеты. В простейшем случае можно использовать одну строку:

all: [email protected]

Конфигурационных файлов недостаточно, чтобы клиент мог подключаться к серверу. Для этого необходимо еще подписать сертификаты.

Сначала, чтобы сервер узнал о новом компьютере, на клиентской системе вводим команду:

$ sudo puppetd --server grinder.com --waitforcert 60 –test

Межсетевой экран должен разрешать соединения на порт 8140.

На сервере получаем список сертификатов, нуждающихся в подписи:

$ sudo puppetca –list

nomad.grinder.com

И подписываем сертификат клиента:

$ sudo puppetca –sign nomad.grinder.com

Теперь клиент может свободно подключаться к серверу и получать настройки.

К сожалению, все возможности Puppet в пределах статьи показать невозможно. Но, как видите, это функциональный и гибкий инструмент, позволяющий решить большую часть задач по одновременному администрированию большого числа систем. И самое главное, проекту удалось собрать пока небольшое, но постоянно растущее сообщество. Поэтому будем надеяться, что хорошей идее не дадут умереть или уйти в сторону.

Удачи!

  1. Сайт проекта BladeLogic – http://www.bladelogic.com .
  2. Сайт проекта OpsWare – http://www.opsware.com .
  3. Сайт проекта Cfengine – http://www.cfengine.org .
  4. Сайт проекта Puppet – http://reductivelabs.com/projects/puppet .
  5. Puppet CookBook – http://www.reductivelabs.com/trac/puppet/tagspuppet%2Crecipe .
  6. Библиотека Faster –