...

понедельник, 5 мая 2014 г.

Berkshelf и зависимости Chef cookbook-ов

Привет, Хабрапользователи!

Я продолжаю свое погружение в пикантности automation-а и configuration management-а, параллельно пытаясь делится опытом с community.

Речь пойдет опять об инструменте автоматизации разрешения зависимостей Сhef cookbook-ов, которым наша компания пользуется, а именно — Berkshelf.


А при чем тут Berkshelf?




Chef имеет достаточно большое и развивающееся community, которое постоянно делает свой внос в создание и редактирование cookbook-ов. Все они хранятся на сайте Community, многие из них — очень часто используются нами.

Однако есть одно «но» в нашей компании, связанное с редактированием community cookbook-ов. Правильный путь внесения каких-либо изменений в оные, связанных с спецификой инфраструктуры компании — это написание wrapper-ов, содержащих в себе изменения (например, переназначение атрибутов, подмена рецептов и пр.). Вкратце, процесс написания wrapper-а описан в этой статье.


Но, наличие правильного пути совсем не означает, что все последуют по нему. Именно поэтому в репозитории cookbook-ов нашей компании — оказалось много community cookbook-ов с недобросовестными правками. И настало время почистить репозиторий :)


План был следующим:


— выделить community cookbook-и в нашем репозитории;

— оценить наличие и количество локальных правок (diff между одинаковыми версиями cookbook-ов);

— вынести изменения во wrapper и включить в него вызов community cookbook-а или рецепта из него;

— удалить community cookbook и внести его в зависимостях wrapper-а.


А что делать с «очищенными» community cookbook-ами? Как после удаления — они появятся «чистыми» на Chef Server-е?


Как раз тут на помощь и приходит Berkshelf.


Что такое Berkshelf и с чем его едят?


Berkshelf является менеджером зависимостей для Chef cookbook-ов. Он написан на Ruby и имеет методы и API для взаимодействия с Chef Server.

Установка Berkshelf происходит из Ruby Gems либо в рамках использования Chef DK.

Мы используем Berkshelf версии 2.0, однако совсем недавно была выпущена версия 3.0, которая принесла некоторые изменения и «плюшки».

Если вы решите использовать Ruby Gem — советую устанавливать его в рамках Ruby, установленного Chef Server-ом (исполняемые файлы находятся по пути — /opt/chef/embedded/bin/).

Для взаимодействия с Chef Server-ом необходимо сконфигурировать Berkshelf, указывая ему адрес нашего сервера и сертификаты для авторизации на нем. Для конфигурации необходимо запустить следующую команду:



berks configure



Конфигурационные файлы находятся по одному из нижеприведенных путей:

$PWD/.berkshelf/config.json
$PWD/berkshelf/config.json
$PWD/berkshelf-config.json
$PWD/config.json
~/.berkshelf/config.json




После корректной установки Berkshelf-а — можно переходить к разрешению зависимостей cookbook-ов.

Для этого, Berkshelf на первом этапе копирует cookbook-и и их зависимости на свои shelf-ы (локальный хранилище/репозиторий Berkshelf-а, по умолчанию — директория ~/.berkshelf/cookbooks/), а потом загружает все на Chef Server.

Сразу появляются вопросы: "Откуда Berkshelf знает про зависимости?", "Что он делает для их разрешения?"

Инструкции для Berkshelf содержатся в Berksfile, находящемся в корневой директории cookbook-а. Создается этот файл при помощи команды

berks init

в корневой директории.

Содержимое этого файла описывает зависимости и источник для их разрешения. Пример такого файла:

site :opscode
metadata
cookbook 'my-cookbook', (:path | :git | :github)
cookbook 'my-book-2', ('> 1.0.0')


Этот файл предписывается следующее:

— учитывать зависимости из файла metadata.rb нашего cookbook-а и загружать их с Opscode Community сайта;

my-cookbook будет загружен по пути, указанному в скобках (это может быть либо локальный путь, либо ссылка на Git);

my-book-2 последней версии, высшей чем 1.0.0, будет загружен с Opscode Community сайта.


После этого можно запустить



berks install

и дождаться успешного копирования зависимостей в локальное хранилище Berkshelf-а. В результате в директории хранилища должны оказаться все cookbook-и, упомянутые в поле depends файла metadata.rb, их зависимости (зависимости зависимостей) и два cookbook-а, упомянутых в Berksfile. Верифицировать результат можно командой

berks shelf list



Следующий шаг — запуск

berks upload

который загрузит все с локального хранилища на Chef Server. В результате (при условии, что Chef Server доступен и мы можем авторизоваться на нем, используя файлы сертификатов) — все зависимости будут разрешены. Результат загрузки можно проверить командой

knife cookbook list

вывод которой должен содержать новые cookbook-и.

По сути, вот и весь процесс базового использования Berkshelf. Конечно, это еще не весь функционал, т.к. не упоминается взаимодействие Berkshelf с Vagrant, Chef Solo, Chef Client, а также некоторые новшества версии 3.0. Однако, я считаю этого достаточно для большинства.


Наша история использования Berkshelf




Все было бы хорошо, если бы опять не одно «но» — Berkshelf не умеет работать циклически. Я очень удивлен, т.к. не нашел варианта, при котором он "нативно" мог учитывать вложенность директорий с cookbook-ами, эдакий nested-режим. Что я имею ввиду?

Например, представим себе типичнейшую ситуацию, есть директория chef-repo, в которой вложена директория cookbooks, содержащая наши cookbook-и (./chef-repo/cookbooks/).

В текущей версии Berkshelf — необходимо переходить в каждую из директорий cookbook-ов и выполнять в ней команды, связанные с Berkshelf. То есть — bash-скрипт, который бы это делал, не руками же, в самом деле… Это решение, но увы — не самое лучшее, откровенно говоря — «костыльное».

На просторах Интернета была найдена статья, в которой используя Ruby-код, решался данный вопрос.

Приведу код нашего "корневого" Berksfile, находящегося в директории ./chef-repo/:

site :opscode

metadata

def dependencies(path)
berks = "#{path}/Berksfile"
instance_eval(File.read(berks)) if File.exists?(berks)
end

Dir.glob('./cookbooks/*').each do |path|
dependencies path
cookbook File.basename(path), :path => path
end

cookbook 'gecode', '= 2.1.0'


По сути, этот кусок кода собирается содержимое всех директорий cookbook-ов (их metadata.rb и Berksfile-ов) в "корневой" Berksfile.


Мы успешно применили предложенное решение и вуаля — все cookbook-и оказались на нашем Chef Server.

Однако, в упомянутой статье не упоминалось одна большая особенность — формат Berksfile-ов наших cookbook-ов.

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



group :name_of_cookbook do
cookbook 'my-cookbook', (:path | :git | :github)
cookbook 'my-book-2', ('> 1.0.0')
end




То есть, список cookbook-ов, которые должны соответствовать определенным условиям — например, версии или местоположению, заключенный в группу (для того, чтобы одинаковые зависимости разных cookbook-ов не вызывали конфликты типа multiple entries). Все остальные зависимости берутся из файла metadata.rb. Под катом — конкретный пример, дабы было нагляднее:

Скрытый текст


group :database do
cookbook 'postgresql', '= 3.3.4'
cookbook 'aws', :path => './cookbooks/aws'
cookbook 'xfs', :path => './cookbooks/xfs'
cookbook 'mysql', '= 4.1.2'
end







В итоге, для cookbookdatabase будут загружены 4 cookbook-а, соответствующих определенным условиям, а также все остальные зависимости, упомянутые в metadata.rb, а также упомянутые зависимости зависимостей (уж простите за тавтологию).

Все, что остается сделать после редактирования Berksfile-ов наших cookbook-ов — это запустить в директории ./chef-repo команды

berks install && berks upload



Вот такое вот решение, возможно не очень надежное или удобное — но решение. Отработало с нашими репозиториями несколько раз успешно.

Если кто-то сталкивался с данным вопросом и может поделится опытом — пишите комментарии или ЛС.

Всем спасибо за внимание, до новых статей.


P.S. Коллега говорит, что Berkshelf v.3.0 — поломан, так что — не советуем!


This entry passed through the Full-Text RSS service — if this is your content and you're reading it on someone else's site, please read the FAQ at http://ift.tt/jcXqJW.


Комментариев нет:

Отправить комментарий