Привет-привет, читатель! Все еще с нами? CHEF – это интересно! Продолжим наш вояж к мастерству воина-автоматизатора, который начался в первой части данной статьи. В этой статье речь пойдет о первом опыте написания cookbook-а, о рецептах, атрибутах и шаблонах.
Прежде чем идти дальше, маленькое отступление по поводу инфраструктуры. В дальнейшем нам понадобиться пара компьютеров или виртуальных машин. Конечно же, есть VirtualBox, есть Vagrant, но я настоятельно советую использовать Amazon Web Services (AWS). Основная причина – AWS повсеместно используется разными компаниями, и знакомство с ним – дополнительный бонус Вам же. Есть бесплатные образы на нем, которые каждый может использовать. Существует большое количество разных сервисов и инструментов, которые предлагает Amazon. Некоторые из них — крайне актуальны. Я считаю, что данный опыт — must-have experience.
Шаг 5. Добро пожаловать на кухню, детка
Добро пожаловать на кухню! В наших руках находится самый главный и незаменимый инструмент – knife!
Что мы будем готовить? Конечно же наш первый рецепт, и дабы не забыть его и использовать его в будущем – запишем его в наш cookbook. Именно в этом нам поможет knife, который умеет создавать cookbook-и. Конечно же можно воссоздать структуру cookbook-а вручную, но зачем? Лучше познакомиться с корректной структурой стандартного cookbook-а.
В создании нам поможет директива knife cookbook create. Она создаст в директории /cookbooks (указать ее местоположение можно указать в файле конфигурации knife.rb) папку с нашим первым cookbook-ом. Давайте ознакомимся с основным содержимым данной папки.
- Директория /attributes содержит в себе файлы, с описанием атрибутов cookbook-а, которые могут быть использованы на узле для перезаписи значения тех или иных дефолтных значений узла. Это могут быть переменные, содержащие в себе пути к рабочим директориям, номера сетевых портов для сервисов, какие-либо специфические метки данного узла (например, его роль в рабочей среде). Самое главное при использовании атрибутов – понимание как их применить посредством рецепта. Как же CHEF получает значения стандартных атрибутов? У него существует инструмент, называемый ohai – коллектор атрибутов системы, используемых для CHEF. Эти атрибуты не являются системными переменными, Вы вряд ли увидите такие названия атрибутов в Вашей ОС – это переменные, с логически понятными названиями, такими как node[“platform”], которая хранит название ОС узла, или node[“fqdn”] – хранящая полное доменное имя узла. Если Вы хотите вносить изменения в текущую конфигурацию того или иного сервиса/ПО – необходимо использовать именно те названия атрибутов, которые предоставляет ohai. Не менее важным свойством атрибутов является идентификация узла – назначение упомянутых «меток». Приведу пример из практики.
Необходимо было создать группу виртуальных машин (chef-клиентов), связать их с Chef-сервером и раздать им cookbook-и в соответствии с их ролью в этой группе (master или slave). На этапе регистрации узлов на Chef-сервере неизвестно, какой узел является master, а какой – slave. Что делать, не руками же назначать каждому? Решилось все просто до невозможности. Каждый узел получал, в зависимости от своего назначения, атрибут env_role = master или slave, который был доступен Chef-серверу. Сервер, в свою очередь, по всем зарегистрированным на нем узлам, проводил поиск по данному атрибуту и в зависимости от значения – раздавал cookbook-и (посредством ролей, о которых мы поговорим в дальнейшем). - Директория /files – содержит в себе набор файлов, которые будут использованы для дистрибуции на узлы. Иными словами, если надо генерировать на узле файл со статическим содержимым (подразумевается, что содержимое файла не меняется в процессе использования оного) – это именно та директория, куда Вы поместите файлы. Далее, в рецепте, ресурс cookbook_file инициализирует использование Вашего файла. Стоит заметить, что имя данного ресурса указывает на абсолютный путь расположения файла на узле, так что будьте внимательны при указании имени. Для того, чтобы указать исходный файл – используется свойство ресурса под названием source, в котором указывается имя исходного файла, размещенного в директории /files. Также дополнительно можно указывать права доступа к файлам на узлах, пользователя и группу пользователей, «владеющих» данными файлами.
Еще одним интересным свойством обладает имя файла. Для него существуют шаблоны, согласно которым специфический файл может быть передан конкретному узлу (используя FQDN), использован на конкретной платформе с конкретной текущей версией. Пример – файл с именем ubuntu-12.04 будет передан только узлам с ОС Ubuntu версии 12.04. - Директория /recipies – фундаментальная директория нашего cookbook-а, директория с рецептами. Это наши рецепты. Именно тут определяется что и как мы будем конфигурировать. Файл рецепта – это Ruby-файл, в котором, очевидно, используется синтаксис языка Ruby (кэп тут!) В зависимости от сложности задачи – может содержать в себе описание функционала и коллекции ресурсов (для простых задач) либо же коллекции ресурсов и вызовы провайдеров (о них мы поговорим ниже). В рецепте можно вызывать другие рецепты, выстраивать зависимости от других рецептов, помещать блоки скриптов для конечных узлов (например, bash или powershell команды) и использовать многие другие возможности, доступные языку Ruby. Стоит запомнить, что выполнение кода происходит именно в том порядке, который указан в рецепте. В итоге, в наших руках достаточно массивные возможности, ограниченные нашим знанием языка Ruby и его возможностями.
- Директория /templates – содержит шаблоны ресурсов, которые могут быть использованы в рецепте. Шаблоны описываются в формате Embedded Ruby, имеют расширение .erb и описывают динамический контент, который генерируется на базе переменных, логики или же простого текста. Далее ресурс шаблон объявляется в ресурсе. Минимальный вариант объявления выглядит следующим образом:
template “/path/to/file/on/our/node.cmd” do
source “node.erb”
endТакже, есть возможность задать, например, права доступа, владельца и группу владельцев этого файла. В этом конкретном случае на узле создастся файл cmd с указанным абсолютным путем, шаблоном которого является файл node.erb. Этот шаблон может быть набором команд, которые необходимо запустить на узле через командную строку. А может также содержать какие-то переменные и логику. Переменные в шаблоне могут быть, например, атрибутами Вашего cookbook-а, придавая шаблону упомянутую динамичность. Выглядит это так:
<%= node['sql_server']['product_key'] %>
,
и является объявлением атрибута (ключа SQL сервера), присутствующего в cookbook-е. Также, стоит отметить, что, как и имена файлов в директории /files, имена шаблонов имеют такое же свойство имени, а именно описывают соответствие шаблона конкретной ОС и версии, либо FQDN узла. - Директории /providers и /resources – это те две директории, которые в терминах Chef организуют LWRP (light-weight resource providers). Я бы мог сравнить это с понятием класса в ООП, однако может такое сравнение и не очень корректно (уж простят админа братья-программисты). В провайдере можно описать функционал, в ресурсах – атрибуты/переменные и доступные action (возможные действия для провайдеров, которые могут быть вызваны из рецептов). Ресурсы идентифицируются и ассоциируются с провайдером, образуя подобие «класса».
Взаимодействия между частями LWRP обеспечивается использованием Resource DSL – языка, содержащего несколько методов, для описания атрибутов и действий. И учитывая, что это вариант Ruby DSL – то и Ruby-код может быть частью определения ресурсов и провайдеров. Дабы долго не вдаваться в теорию, вот пример LWRP, который рассылает письма (например, при наступлении какого-либо события в системе)./providers/default.rbdef mailing
puts "n Sending your email..."r = chef_gem «mail» do
action :install
endGem.clear_paths
require 'mail'
options = {
:address => new_resource.server,
:port => new_resource.port,
:mailto => new_resource.mailto,
:user_name => new_resource.user_name,
:password => new_resource.password,
:authentication => 'plain',
:enable_starttls_auto => true
}Mail.defaults do
delivery_method :smtp, options
endmail = Mail.deliver do
from options[:user_name]
to options[:mailto]
subject 'Hello'
body new_resource.msg
endend
/resources/default.rbactions :create
default_action :createattribute :app_name, :kind_of => String
attribute :user_name, :kind_of => String, :default => ""
attribute :password, :kind_of => String, :default => ""
attribute :server, :kind_of => String, :default => ""
attribute :port, :kind_of => Integer, :default => 465
attribute :mailto, :kind_of => [String, NilClass], :default => ""
attribute :from, :kind_of => [String, NilClass], :default => ""
attribute :msg, :kind_of => String, :default => «Hi there»def initialize(*args)
super
@ action = :create
End
Я думаю, достаточно очевидно, даже для тех, кто не встречался с синтаксисом Ruby, что описано в данном файле. Это функция отправки письма по электронной почте. В следующей части – мы познакомимся с cookbook-ом, который использует LWRP для отправки сообщений об изменениях в системе.
Шаг 6. Время дегустации
Ну что ж, давайте представим себе, что наш cookbook уже готов (я предоставлю его пример и опишу использование в следующей части).
Что делать дальше? Как загрузить его на сервер и отправить на исполнение узлами? Knife сделает это за нас. Для того, чтобы успешно провести дальнейшие операции, нам необходимо, чтобы Chef-админ имел верно сконфигурированный knife (файл knife.rb) и сертификат администратора (например, admin.pem). Далее, необходимо перейти в директорию /chef-repo (там, где находится наш starter kit, например) и, находясь в ней, исполнять команды.
Первое действие — удостоверится, что узлы зарегистрированы на сервере — knife node list
. В результате должны получить имена активных узлов.
Далее, загрузим наш cookbook на сервер. Он должен находится в директории, указанной в cookbook_path файла knife.rb.
Выполняем — knife cookbook upload name-of-cookbook
. В результате — сообщение об успешной загрузке и присутствие нашего cookbook-а в списке, полученном командой knife cookbook list
.
Следующий шаг — назначение run-list узла. Тут можно пойти 2 путями — простым или правильным.
Простой — сразу добавить в run-list рецепт — knife node edit name-of-node
и внести текстовые изменения в раздел run-list, добавляя туда строку «recipe[name-of-recipe]». А что, если таких рецептов десяток? Не очень удобно.
Правильный путь — добавить роль. Файл роли представляет собой описание атрибутов run-list. В том числе — и рецептов. Соответственно, одна роль может быть назначена множеству узлов. Файл роли находится по адресу /chef-repo/roles:
name «mailer»
description «Role for host that will notify us on changes»
run_list «recipe[name-of-recipe]»
Для того, чтоб загрузить роль на сервер, используется команда knife role from file name-of-role-file
. После загрузки — роль можно назначить в run-list узла, что мы и сделаем.
На этом нехитрый процесс закончен, мы готовы запускать клиента на узле. После этого — получим узел с (условно) реализованным на нем cookbook-ом.
На этом я буду заканчивать вторую часть и буду анонсировать третью — более технически-ориентированную (с большим количеством кода), которая расскажет о примере использование AWS и Chef.
Автор: MistiC