Управление конфигурацией 101: Написание рецептов шеф-повара

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

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

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

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

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

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

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

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

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

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

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

[.note] #Note: Это руководство предназначено для ознакомления вас с языком Chef и с тем, как писать рецепты для автоматизации подготовки вашего сервера. Для более вводного представления Chef, включая шаги, необходимые для установки и начала работы с этим инструментом, обратитесь кChef’s official documentation.
#

Начиная

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

Условия шеф-повара

  • Chef Server: центральный сервер, который хранит информацию и управляет подготовкой узлов

  • Chef Node: отдельный сервер, управляемый Chef Server

  • Chef Workstation: компьютер-контроллер, на котором создаются и загружаются на Chef Server настройки.

  • Recipe: файл, содержащий набор инструкций (ресурсов) для выполнения. Рецепт должен содержаться вCookbook

  • Resource: часть кода, которая объявляет элемент системы и какое действие следует выполнить. Например, чтобы установить пакет, мы объявляем ресурсpackage с действиемinstall

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

  • Attributes: подробности о конкретном узле. Атрибуты могут быть автоматическими (см. Следующее определение), а также могут быть определены внутри рецептов.

  • Automatic Attributes: глобальные переменные, содержащие информацию о системе, такую ​​как сетевые интерфейсы и операционная система (известные какfacts в других инструментах). Эти автоматические атрибуты собираются инструментомOhai.

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

Формат рецепта

Рецепты шеф-повара написаны с использованием Ruby. Рецепт - это, в основном, набор определений ресурсов, которые создадут пошаговый набор инструкций, которые будут выполняться узлами. Эти определения ресурсов могут быть смешаны с кодом Ruby для большей гибкости и модульности.

Ниже вы можете найти простой пример рецепта, который запуститapt-get update и после этого установитvim:

execute "apt-get update" do
 command "apt-get update"
end

apt_package "vim" do
 action :install
end

Написание рецептов

Работа с переменными

Локальные переменные могут быть определены внутри рецептов как обычные локальные переменные Ruby. В приведенном ниже примере показано, как создать локальную переменную, которая позднее будет использоваться внутри определения ресурса:

package  = "vim"

apt_package package do
 action :install
end

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

Использование атрибутов

Атрибуты представляют подробности об узле. У Chef есть автоматические атрибуты, которые представляют собой атрибуты, собранные инструментом Ohai и содержащие информацию о системе (например, платформа, имя хоста и IP-адрес по умолчанию), но также позволяют вам определять свои собственные пользовательские атрибуты.

Атрибуты имеют разные уровни приоритета, определяемые типом создаваемого вами атрибута. Атрибутыdefault являются наиболее распространенным выбором, так как при желании они могут быть перезаписаны другими типами атрибутов.

В следующем примере показано, как предыдущий пример будет выглядеть с атрибутом узлаdefault вместо локальной переменной:

node.default['main']['package'] = "vim"

apt_package node['main']['package'] do
 action :install
end

В этом примере есть две детали:

При определении переменных узлов рекомендуется организовывать их в виде хэшей с использованием текущей поваренной книги, используемой в качестве ключа. В данном случае мы использовалиmain, потому что у нас есть кулинарная книга с таким же именем. Это позволяет избежать путаницы, если вы работаете с несколькими кулинарными книгами, которые могут иметь похожие именованные атрибуты.
Обратите внимание, что мы использовалиnode.default при определении атрибута, но при доступе к его значению позже мы использовалиnode прямо. Использованиеnode.default определяет, что мы создаем атрибут типаdefault. Значение этого атрибута могло быть перезаписано другим типом с более высоким приоритетом, таким как атрибутыnormal илиoverride.

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

node.normal['main']['package']  = "vim"

node.override['main']['package'] = "git"

node.default['main']['package'] = "curl"

apt_package node['main']['package'] do
 action :install
end

Вы знаете, какой пакет будет установлен в этом случае? Если вы угадалиgit, значит, вы угадали правильно. Независимо от порядка, в котором были определены атрибуты, более высокий приоритет типаoverride сделает+node['main']['package'] be evaluated to+`git.

Использование циклов

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

Chef поддерживает все структуры циклов Ruby для создания циклов внутри рецептов. Для простого использования обычно используетсяeach:

['vim', 'git', 'curl'].each do |package|
 apt_package package do
   action :install
 end
end

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

packages = ['vim', 'git', 'curl']

packages.each do |package|
 apt_package package do
   action :install
 end
end

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

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

Chef поддерживает все условные выражения Ruby для создания условных операторов внутри рецептов. Кроме того, все типы ресурсов поддерживают два специальных свойства, которые будут оценивать выражение перед принятием решения, следует ли выполнять задачу или нет:if_only иnot_if.

В приведенном ниже примере будет проверяться наличиеphp перед попыткой установить расширениеphp-pear. Он будет использовать командуwhich для проверки наличия исполняемого файлаphp, установленного в настоящее время в этой системе. Если командаwhich php вернет false, эта задача не будет выполнена:

apt_package "php-pear" do
 action :install
 only_if "which php"
end

Если мы хотим сделать обратное, выполняя команду все времяexcept, когда условие оценивается как истинное, мы вместо этого используемnot_if. В этом примере будет установленphp5, если система не является CentOS:

apt_package "php5" do
 action :install
 not_if { node['platform'] == 'centos' }
end

Для выполнения более сложных оценок, если вы хотите выполнить несколько задач в определенных условиях, вы можете использовать любое из стандартных условий Ruby. В следующем примереapt-get update выполняется только в том случае, если в системе используется Debianor Ubuntu:

if node['platform'] == 'debian' || node['platform'] == 'ubuntu'
 execute "apt-get update" do
   command "apt-get update"
 end
end

Атрибутnode['platform'] - это автоматический атрибут от Chef. Последний пример должен был продемонстрировать только более сложную условную конструкцию, однако его можно было заменить простым тестом с использованием автоматического атрибутаnode['platform_family'], который вернет «debian» как для систем Debian, так и для Ubuntu.

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

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

Chef использует шаблоны Embedded Ruby (ERB), которые используются в Puppet. Они поддерживают условные выражения, циклы и другие функции Ruby.

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


    ServerAdmin webmaster@localhost
    DocumentRoot <%= @doc_root %>

    >
        AllowOverride All
        Require all granted
    

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

template "/etc/apache2/sites-available/000-default.conf" do
 source "vhost.erb"
 variables({ :doc_root => node['main']['doc_root'] })
 action :create
end

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

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

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

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

В Chef сервисные ресурсы должны быть объявлены до того, как вы попытаетесь их уведомить, иначе вы получите ошибку.

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

service "apache2" do
  action [ :enable, :start ]
end

Теперь при определении ресурсаtemplate вам необходимо включить параметрnotify, чтобы запустить перезапуск:

template "/etc/apache2/sites-available/000-default.conf" do
 source "vhost.erb"
 variables({ :doc_root => node['main']['doc_root'] })
 action :create
 notifies :restart, resources(:service => "apache2")
end

Пример рецепта

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

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

Ниже вы можете найти полный рецепт:

node.default['main']['doc_root'] = "/vagrant/web"

execute "apt-get update" do
 command "apt-get update"
end

apt_package "apache2" do
 action :install
end

service "apache2" do
 action [ :enable, :start ]
end

directory node['main']['doc_root'] do
 owner 'www-data'
 group 'www-data'
 mode '0644'
 action :create
end

cookbook_file "#{node['main']['doc_root']}/index.html" do
 source 'index.html'
 owner 'www-data'
 group 'www-data'
 action :create
end

template "/etc/apache2/sites-available/000-default.conf" do
 source "vhost.erb"
 variables({ :doc_root => node['main']['doc_root'] })
 action :create
 notifies :restart, resources(:service => "apache2")
end

Рецепт объяснил

строка 1

Рецепт начинается с определенияattribute,node['main']['doc_root']. Мы могли бы использовать простую локальную переменную здесь, однако в большинстве сценариев использования рецепты должны определять глобальные переменные, которые будут использоваться из включенных рецептов или других файлов. Для этих ситуаций необходимо создать атрибут вместо локальной переменной, так как последний имеет ограниченную область действия.

строки 3-5

Этот ресурсexecute запускаетapt-get update.

строки 7-10

Этот ресурсapt_package устанавливает пакетapache2.

линии 12-15

Этот ресурсservice включает и запускает службуapache2. Позже нам нужно будет уведомить этот ресурс о перезапуске службы. Важно, чтобы определение службы предшествовало любому ресурсу, который пытается уведомить службу, в противном случае вы получите ошибку.

строки 17-22

Этот ресурсdirectory использует значение, определенное настраиваемым атрибутомnode['main']['doc_root'], для создания каталога, который будет служить нашимdocument root.

линии 24-29

Ресурсcookbook_file используется для копирования локального файла на удаленный сервер. Этот ресурс скопирует наш файлindex.html и поместит его в корень документа, который мы создали в предыдущей задаче.

линии 31-36

Наконец, этот ресурсtemplate применяет наш шаблон виртуального хоста Apache и уведомляет службуapache2 о перезапуске.

Заключение

Chef - это мощный инструмент управления конфигурацией, использующий язык Ruby для автоматизации подготовки и развертывания серверов. Это дает вам свободу использовать стандартные языковые функции для максимальной гибкости, а также предлагает настраиваемые DSL для некоторых ресурсов.

Related