Паттерны и антипаттерны Chef

от автора

Предисловие от переводчика

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

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

Статья будет полезна как для видавших виды «поваров», так и для новичков.

Антипаттерн: Изменение (forking) комьюнити cookbook-ов

Я так делал, возмонжно вы тоже. Всё начинается довольно невинно и не предвещает ничего плохого. Вы добавляете парочку атрибутов, меняете metadata.rb. Вскоре вам нужно добавить свой рецепт, и может даже LWRP. Теперь у вас каша из ваших изменений и комьюнити кода, особенно если cookbook в активной разработке на GitHub-е. Рано или поздно придётся исправлять конфликты. Будет сложно выделить логические ошибки, если и в исходном cookbook-е, и в вашем изменения почти одинаковые. И как теперь вы будете версионировать этого «Франкенштейна»? Использовать ту же версию, что и в апстриме? Короче говоря, это антипаттерн, который потом трудно исправить.

Единственное исключение из правила «не форкай комьюнити cookbook-и» — это если вы собираетесь свои изменения вернуть назад сообществу. Тогда нужно создать фичер ветку в git-е и послать pull request. Это должна быть ветка живущая только до тех пор, пока изменения не объединятся с основной веткой.

Паттерн: Создать свою обёртку (wrapper-cookbook) со своими атрибутами и рецептами

Вместо форканья комьюнити кукбука лучше использовать его «как есть» при помощи кукбука-обёртки. В этом кукбуке-обертке в metadata.rb нужно прописать зависимость от этого кукбука и использовать include_recipe для запуска рецептов из комьюнити кукбука. Нужно поменять дефолтные атрибуты? Тогда нужно переписать их в кукбуке-обертке. Дополнительные рецепты также могут быть включены, но тогда это правильнее называть application cookbook (прим. переводчика).

С этим паттерном может помочь gem Chef-Rewind.

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

Перечисление аттрибутов в ролях опасный антипаттерн, который может поломать ваш продакшн. Представьте следующий сценарий. У вас есть web_server роль с атрибутами для имен и настроек двух сайтов, которые нужно установить на этот сервер. Теперь представьте, что вам нужно разделить эти сайты на две роли app_server и blog_server. Ну и как вы собираетесь это тестировать на dev окружении? Можно рискнуть и надеяться, что все будет ОК или перезаписать атрибуты в Chef Environments (сначала на dev, потом на qa и т.д.) и не забыть почистить их после того, как они попадут на продакшн. Не самый лучший вариант.

Лучше использовать атрибуты в кукбуке-обёртке.

Паттерн: Установка своих аттрибутов в кукбуке-обёртке

Роли версионировать Chef не умеет, зато кукбуки — да. Устанавливая нужные атрибуты в кукбуке-обёртке и указвая в Chef Environment нужную версию кукбука, можно продвигать изменения от dev к production-у.

В идеале это должно быть частью CI процесса с тестами и постепенным продвижением изменений в автоматическом режиме. Но это уже отдельная история.

Антипаттерн: Установка списка запуска (run list) в роли

Chef роли кажутся идеальнами для хранения списка запускаемых рецептов. Однако, этот подход страдает теми же недостатками, что и предыдущий антипаттерн. Если вы добавите или удалите рецепт из списка run_list в роли, то эти изменения применятся ко всем серверам с этой ролью, включая продакшн серверы.

Так делать не нужно:

name "web_server" description "Role for web servers"  run_list(    "recipe[base_server::disk_configuration]",   "recipe[base_server::dhcp_reservation]",   "recipe[base_server::pagefile]",   "recipe[utility::install_tools]",   "recipe[web_server::web_sites]",   "recipe[base_server::ssl_certs]"  ) 

Паттерн: Укажите run list в рецепте default в созданном спциально для этого cookbook-e (т.н. role-cookbook или application-cookbook)

Храните в роли минимальный список рецептов. Полный список рецептов должен храниться в application-cookbook-е. Например, вот так может выглядеть роль web_server:

name "web_server" description "Role for web servers"  run_list(   "role[base]",   "recipe{web_server]" )  

Рецепт default вашего application-cookbook-а будет выглядеть примерно так:

# web_server cookbook recipes/default.rb    include_recipe "base_server::disk_configuration",   include_recipe "base_server::dhcp_reservation",   include_recipe "base_server::pagefile",   include_recipe "utility::install_tools",   include_recipe "web_server::web_sites",   include_recipe "base_server::ssl_certs" 

Опять же, это для того, чтобы можно было легко управлять версиями кукбуков и тестировать изменения до версии 2.1.0 на dev окружении в то время, как на продкшене будет стабильная 1.5.0.

Заключение

Следуя приведенным выше паттернам, вы сэкономите кучу сил и времени. Вам не нужно будет делать сложных мёрджей, так как все изменения хранятся в кукбуке-обёртке(wrapper cookbook).

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

ссылка на оригинал статьи http://habrahabr.ru/company/epam_systems/blog/209232/


Комментарии

Добавить комментарий

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