Создание манифестов 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.')

}
else {

notify { 'Good to go!': }

}

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

exec { "Test":

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

}

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

exec { "Test":

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, в котором используется переменная для создания корневого каталога этого хоста:

<VirtualHost *:80>
ServerAdmin webmaster@localhost
DocumentRoot <%= @doc_root %>
<Directory <%= @doc_root %>>
AllowOverride All
Require all granted
</Directory>
</VirtualHost>

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

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

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: , ,

1 комментарий

Добавить комментарий для Александр Отменить ответ