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

в 8:37, , рубрики: chef, cookbook, антипаттерны, Блог компании EPAM Systems, паттерны, системное администрирование

Паттерны и антипаттерны 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 в кукбуках, а не в ролях, вы не получите проблем с версионированием и изоляцией окружений.

Автор: morkot

Источник


* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js