Управление конфигурацией 101: Написание марионеточных манифестов

Вступление

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

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

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

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

  1. Обновите кеш + apt +

  2. Установите Apache

  3. Создать пользовательский корневой каталог документов

  4. Поместите файл + index.html в пользовательский корень документа

  5. Примените шаблон для настройки нашего собственного виртуального хоста

  6. Перезапустите Apache

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

Начиная

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

Условия кукол

  • * Puppet Master *: главный сервер, который контролирует конфигурацию на узлах

  • * Узел Puppet Agent *: узел, управляемый Хозяином Марионеток

  • * Манифест *: файл, который содержит набор инструкций для выполнения

  • * Ресурс *: часть кода, которая объявляет элемент системы и как его состояние должно быть изменено. Например, чтобы установить пакет, нам нужно определить ресурс package и убедиться, что его состояние установлено на «установлен»

  • * Модуль *: коллекция манифестов и других связанных файлов, организованных в заранее определенном порядке, чтобы облегчить совместное использование и повторное использование частей обеспечения

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

  • * Факты *: глобальные переменные, содержащие информацию о системе, например, о сетевых интерфейсах и операционной системе

  • * Службы *: используется для запуска изменений состояния службы, таких как перезапуск или остановка службы

Подготовка марионеток написана с использованием настраиваемого DSL (предметно-ориентированного языка) на основе Ruby.

Ресурсы

В Puppet задачи или шаги определяются объявлением * resources *. Ресурсы могут представлять пакеты, файлы, сервисы, пользователей и команды. Они могут иметь состояние, которое вызовет изменение системы в случае, если состояние объявленного ресурса отличается от того, что в настоящее время находится в системе. Например, ресурс package, установленный в вашем манифесте на «+ instal +», запустит установку пакета в системе, если пакет не был установлен ранее.

Вот как выглядит package ресурс:

package { 'nginx':
   ensure  => 'installed'
}

Вы можете выполнить любую произвольную команду, объявив ресурс + exec +, например:

exec { 'apt-get update':
   command => '/usr/bin/apt-get update'
}

Обратите внимание, что часть + 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 +. Ниже вы можете найти пример простой книги воспроизведения, которая выполняет две задачи: обновляет кеш + apt + и впоследствии устанавливает + vim +:

exec { 'apt-get update':
   command => '/usr/bin/apt-get update'
}

package { 'vim':
   ensure => 'installed'
   require => Exec['apt-get update']
}

Перед концом этого руководства мы увидим более реальный пример манифеста, подробно объясненный. В следующем разделе представлен обзор наиболее важных элементов и функций, которые можно использовать для написания манифестов 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 +, будут поддерживать атрибуты, которые работают как условные, но принимают только вывод команды в качестве условия.

Допустим, вы хотите выполнить команду, основанную на fact. В этом случае, когда вы хотите проверить значение переменной, вам нужно использовать одну из поддерживаемых условных структур, например + if / else +:

if $osfamily != 'Debian' {
warning('This manifest is not supported on this OS.')
}
else {
notify { 'Good to go!': }
}

Другая распространенная ситуация - когда вы хотите обусловить выполнение команды на основе вывода другой команды. Для подобных случаев вы можете использовать + onlyif + или +, если только +, как в примере ниже. Эта команда будет выполнена только тогда, когда вывод из + / bin / which php + успешен, то есть команда завершается со статусом * 0 *:

exec { "Test":
command => "/bin/echo PHP is installed here > /tmp/test.txt",
onlyif => "/bin/which php"
}

Точно так же +, если + не выполнит команду все время, кроме случаев, когда команда в +, если + не завершится успешно:

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

Работа с шаблонами

Шаблоны обычно используются для настройки файлов конфигурации, что позволяет использовать переменные и другие функции, предназначенные для того, чтобы сделать эти файлы более универсальными и пригодными для повторного использования. Puppet поддерживает два разных формата для шаблонов: Embedded Puppet (EPP) и Embedded Ruby (ERB). Однако формат EPP работает только с последними версиями Puppet (начиная с версии 4.0).

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

<VirtualHost *:80>
   ServerAdmin webmaster@localhost
   DocumentRoot <%= @doc_root %>

   <Directory <%= @doc_root %>>
       AllowOverride All
       Require all granted
   </Directory>
</VirtualHost>

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

file { "/etc/apache2/sites-available/000-default.conf":
   ensure => "present",
   content => template("apache/vhost.erb")
}

Puppet делает несколько предположений при работе с локальными файлами, чтобы обеспечить организацию и модульность. В этом случае Puppet будет искать файл шаблона + vhost.erb + внутри папки + apache / templates + внутри директории ваших модулей.

Определение и запуск сервисов

Сервисные ресурсы используются, чтобы убедиться, что сервисы инициализированы и включены. Они также используются для запуска перезапуска службы.

Давайте рассмотрим наш предыдущий пример использования шаблона, где мы настраивали виртуальный хост Apache. Если вы хотите убедиться, что Apache перезапускается после смены виртуального хоста, вам сначала нужно создать ресурс service для службы Apache. Вот как такой ресурс определяется в Puppet:

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, как обсуждалось во введении к этому руководству.

Полный пример, включая файл шаблона для настройки Apache и файл HTML для обслуживания веб-сервером, можно найти по адресу on Github. В папке также содержится Vagrantfile, который позволяет протестировать манифест в упрощенной настройке с использованием виртуальной машины, управляемой https://vagrantup.com [Vagrant].

Ниже вы можете найти полный манифест:

default.pp

$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
}

Манифест объяснил

строка 1

Манифест начинается с определения переменной + $ doc_root +. Эта переменная позже используется в объявлении ресурса.

строки 3-5

Этот * exec * ресурс выполняет команду + apt-get update +.

строки 7-10

Этот ресурс * package * устанавливает пакет + apache2 +, определяя, что ресурс + apt-get update + является требованием, что означает, что он будет выполняться только после оценки требуемого ресурса.

линии 12-17

Мы используем ресурс * file *, чтобы создать новый каталог, который будет служить корневым каталогом нашего документа. Ресурс + file + может использоваться для создания каталогов и файлов, а также для применения шаблонов и копирования локальных файлов на удаленный сервер. Эта задача может быть выполнена в любой точке инициализации, поэтому нам не нужно было устанавливать здесь + require +.

линии 19-23

Здесь мы используем другой ресурс * file *, на этот раз, чтобы скопировать наш локальный файл * index.html * в корневой каталог документа на сервере. Мы используем параметр + source +, чтобы Puppet знал, где найти исходный файл. Эта номенклатура основана на том, как Puppet обрабатывает локальные файлы; если вы загляните в Github пример репозитория, вы увидите, как должна создаваться структура каталогов чтобы позволить Puppet найти этот ресурс. Корневой каталог документа должен быть создан до выполнения этого ресурса, поэтому мы включаем опцию `+ require + ', ссылающуюся на предыдущий ресурс.

линии 25-30

Новый ресурс * file * используется для применения шаблона Apache и уведомления службы о перезапуске. В этом примере наша подготовка организована в модуле под названием * main *, и поэтому источником шаблона является * main / vhost.erb *. Мы используем оператор + require +, чтобы убедиться, что ресурс шаблона выполняется только после установки пакета + apache2 +, в противном случае структура каталогов, используемая Apache, может еще не присутствовать.

строки 32-35

Наконец, ресурс * service * объявляет сервис + apache2 +, который мы уведомляем о перезапуске с ресурса, который применяет шаблон виртуального хоста.

Заключение

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

В руководстве next этой серии мы рассмотрим Chef, еще один мощный инструмент управления конфигурацией, который использует язык программирования Ruby для автоматизации администрирования и предоставления инфраструктуры.

Related