- PVSM.RU - https://www.pvsm.ru -
Что происходит с кодом после того, как он написан? Во многих областях разработки ПО его жизнь только начинается. Например, в разработке для веба, приложение исполняется где-то на сервере. Значит, после написания кода встаёт задача интегрировать его в приложение и доставить на конечную машину. Именно этот процесс мы сегодня обсудим.
Данный текст предназначен широкому кругу разработчиков и рассчитан на тех, кто мало знаком с процессом выкладки кода. Так же этот текст может быть полезен тем, кто строит систему деплоймента и находится в поиске идей.
Статья написана на основе материалов внутреннего семинара компании Аори, и рассказывает о принципах деплоймента на примере процесса, построенного у нас.
В самом общем приближении после написания кода существует одна единственная задача — отправить написанное куда-то, где оно будет запускаться. То есть, грубо говоря, залить его по ftp или по ssh.
N.B. Если вы заливаете обновление сайта про котиков по ftp, это тоже деплоймент.
Сегодня у нас нет котиков, но есть линукс, консоль и мы заливаем всё по ssh. Значит, процесс деплоймента будет таким:
Когда мы распаковываем проект на удалённом сервере, мы фактически перезаписываем содержимое папки новым. По-хорошему, следует предварительно очищать папку. Однако тогда сервис во время выкладки будет недоступен.
К тому же, что мы будем делать, если выкатим проект с ошибкой? Нам придётся откатывать локальную версию, заново производить все манипуляции с заливкой архива, и высока вероятность напортачить в спешке.
Есть очень простое решение этих проблем — выкладка происходит каждый раз в новую папку, на которую каждый раз переключается одноимённый симлинк:
ln -nsf /home/project/versions/{0} /home/project/current
Поддиректории versions удобно называть по порядковому номеру процедуры выкладки.
Скорее всего, конфиги для удалённой машины нужны свои. Это значит, перед упаковкой проекта необходимо накатить боевые конфиги.
Ну и если во время выкладки на каком-то из шагов произошла ошибка, выкладку нужно остановить.
Получается, что для того, чтобы выложить проект на удалённую машину, минимально необходимые шаги будут такими:
Если на любом из шагов произошла ошибка, остановить.
Понятно, что выполнять эти задачи вручную не стоит, нам понадобиться какая-то автоматизация, что-то наподобие баш-скрипта, который мы будем запускать для выкладки.
N.B. В принципе, подойдёт и bash-скрипт.
В Аори для конечного деплоя мы используем Fabric [1]. Это библиотека на питоне, позволяющая очень простыми средствами решить перечисленные выше задачи.
Из приятностей хотелось бы отметить так называемые роли — именованные группы машин, которые позволяют выполнять некоторые пункты деплоя не на всех машинах, а только на некоторых. Скажем, у нас в боевом окружении три роли: статика, веб-приложение и скрипты. Соответственно, прогрев кэша на машинах со статикой не нужен, а обновить кронтаб нужно только на скриптовых машинах.
Вот кусочек нашего фабрик-скрипта для примера:
@parallel
@roles('web', 'script', 'static')
def switch(id):
run('ln -nsf /home/project/versions/{0} /home/project/current'.format(id))
@roles('script')
def crontab(id):
run('crontab /home/project/versions/{0}/build/crontab'.format(id))
@parallel
@roles('web', 'script', 'static')
def clear(id):
with cd('/home/project/versions'):
run("ls -1 | grep -E '^[0-9]+$' | sort -n | head -n -3 | xargs -rt rm -rf")
def deploy(id):
execute(prepare)
execute(upload)
execute(upload_static, id)
execute(build, id)
execute(migrate, id)
execute(switch, id)
execute(crontab, id)
execute(clear, id)
Если вы используете ветки, у вас как минимум есть master для готового к отправке на продакшн кода, и development, в которую коммитится всё подряд, тестируется и подливается в master по мере стабилизации.
В этом случае development тоже куда-то выкладывается, и для него нужен свой отдельный фабрик-скрипт.
Перед отправкой кода куда-либо нужно прогнать тесты, поскольку бессмысленно выкладывать заведомо битый код.
Итак, список действий для выкладки кода увеличивается.
Если на любом из этапов случилась ошибка, остановить.
Ну и раз мы всё делаем по-уму, то
Похоже, нам требуется ещё один инструмент, потому что выполнять все эти действия руками, даже имея набор фабрик-скриптов, немыслимо.
Инструмент, который нам поможет, называется Continuous Integration Server [2], и занимается, по сути, тем, что по команде, по расписанию или по внешнему событию вынимает свежий код указанного репозитория, а дальше выполняет перечисленный набор команд. Мы в качестве инструмента для CI используем Jenkins [3].
Важно понимать, что сам сервер непрерывной интеграции из перечисленных выше задач умеет делать только инкремент счётчика сборок и отправку письма в случае неудачи. Для запуска юнит-тестов, наката конфигов и прочих полезных дел нужен ещё один инструмент, выполняющий расширенные функции bash-скрипта.
Если для деплоймента мы взяли фабрик, то для задач сборки проекта мы используем Phing [4]. Во-первых, он удобен, во-вторых, дженкинс хорошо с ним интегрируется, и, в трётьих, так сложилось исторически.
Вот примеры задач, которые решает наш финг:
phing build — сборка проекта
phing gerrit-phpcs — проверка на кодстандарты
phing copy-production-configs — достать конфиги продакшн-машин из закрытого репозитория
phing write-version — сохранить в файл таймстемп текущей сборки.
А вот полный путь нашего кода из ветки development на тестовый сервер:
Сначала работает финг. Все действия происходят в локальной папке дженкинса:
Фабрик отвечает за отправку кода на конечные машины. Последовательность действий такая:
В заключение хотелось бы рассказать о решениях для инспекций кода.
В самом простейшем виде ревью можно осуществлять через плечо вашего сотрудника и давать комментарии устно. Также можно смотреть, что разработчик закоммитил, и писать комментарии в тикет. В принципе, в каких-то случаях этого достаточно, однако существуют специализированные инструменты, позволяющие упростить процесс инспекции и совместить его с автоматическими проверками.
У себя в разработке мы используем Gerrit [6].
Самый главный плюс геррита в том, что он тесно интегрируется с git, становясь, по сути, git-сервером. После этого через веб-интерфейс геррита можно не только выполнять собственно ревью, но и управлять правами на гит. Таким образом, рядовые разработчики не имеют права на прямой пуш в девелопмент или мастер, они могут только отправлять чейнджсеты на ревью, запуская скрипт git review <branch>
N.B. С технической точки зрения, отправляя ченджсет на ревью, разработчик всё-таки делает пуш, но в специально отведённую для этого ветку. После чего, если ревьюеру всё нравится, при помощи кнопки submit специальная ветка вмёрживается в ту, которая была указана при команде git review.
Перед кодревью имеет смысл прогнать юнит-тесты. Для этой цели можно использовать тот же дженкинс, который хорошо интегрируется с Герритом: по событию «обновление ветки с именем, соответствующим шаблону» прогоняет тесты и ставит свою отметку в кодревью. С недавнего времени мы дополнительно к юнит-тестам автоматически проверяем код на кодстандарты.
Упомянутые инструменты хорошо зарекомендовали себя в работе, однако для ваших задач может лучше подходить что-то другое. Например, github предоставляет реализацию полного набора инструментов для ревью и непрерывной интеграции. С другой стороны, принципы, описанные в тексте, более-менее универсальны и, насколько известно автору, применимы как для одной конечной машины, так и для сотен машин с параметризованными ролями.
Jenkins [3] — Wikipedia
Jenkins + Python [7] — хорошая статья на хабре
Gerrit [6] — Wikipedia
Gerrit в Баду [8] — коллеги запилили подробную статью по установке и использованию
Fabric [9] — документация на сайте
Прикладные рецепты Fabric [10]
Phing [4] — официальная документация
Краткое введение в Phing [10] на хабре
Continuous Integration [2] — Wikipedia
Автор: lukyanov
Источник [11]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/razrabotka/56999
Ссылки в тексте:
[1] Fabric: http://docs.fabfile.org/en/1.8/
[2] Continuous Integration Server: http://en.wikipedia.org/wiki/Continuous_integration
[3] Jenkins: http://en.wikipedia.org/wiki/Jenkins_%28software%29
[4] Phing: http://www.phing.info/
[5] переменные дженкинса: https://wiki.jenkins-ci.org/display/JENKINS/Building+a+software+project
[6] Gerrit: http://en.wikipedia.org/wiki/Gerrit_%28software%29
[7] Jenkins + Python: http://habrahabr.ru/post/114745/
[8] Gerrit в Баду: http://habrahabr.ru/company/badoo/blog/147508/
[9] Fabric: http://docs.fabfile.org
[10] Прикладные рецепты Fabric: http://habrahabr.ru/post/141271/
[11] Источник: http://habrahabr.ru/post/215601/
Нажмите здесь для печати.