Кто не любит побаловать свою девушку какой-нибудь вкусняшкой на завтрак? Ведь парень, умеющий готовить, это здорово! Но на практике большая часть из нас едва ли способна пожарить яичницу, что уже говорить о более «сложных» утренних блюдах, таких, например, как омлет. Признайтесь, вы — отчаянный романтик, но повар из вас — так себе...
Вы можете отрицать этот факт сколько хотите, но с развертыванием приложений дела у вас обстоят ни чуть не лучше: как бы вы ни старались, рано или поздно вы все равно где-нибудь да накосячите.
Будь то необходимость сделать мгновенный откат до предыдущего релиза или внезапное и бесследное исчезновение Васи Пупкина, ответственного за развертывание, — что-нибудь постоянно портит вам нервы и мешает спокойно спать. Причины у ваших ночных кошмаров как правило две:
- вы круто шарите в разработке ПО, но никак не можете подружиться с развертыванием;
- вы не автоматизируете последнее.
В этой статье мы сосредоточимся именно на втором пункте — автоматизации развертывания.
Автоматизация развертывания ПО на .NET в последние годы стала неимоверно простой: благодаря новым инструментам этот процесс стал чрезвычайно быстрым, безболезненным и практически бесплатным. Поэтому не использовать автоматическое развертывание, когда на дворе
Тем не менее некоторые «консерваторы» яростно сопротивляются внедрению автоматизации развертывания, поскольку (наивно) полагают, что овчинка выделки не стоит. Зря.
Есть ∞ причин, по которым внедрением автоматизации развертывания на .NET надо было подзаняться еще вчера: сделав это, вы сможете развертывать чаще, а ваши «шансы на успех» будут велики как никогда. Но, пожалуй, самая главная причина — профит для компании. Звучит недостаточно убедительно? Копнем глубже!
Стабильное развертывание вручную — это утопия
Давайте посмотрим на типичный процесс развертывания самого обычного приложения:
1. экcпорт правильной версии развертываемого исходного кода из системы контроля версий (последний коммит ветки /Release_01);
2. сборка решения с указанием всех необходимых настроек;
3. трансформация конфигурации под нужное окружение;
4. упаковка/публикация новой версии;
5. остановка приложения/настройка балансировщика нагрузки с тем, чтобы пользователи не попадали в приложение в процессе развертывания;
6. бэкап базы данных;
7. обновление структуры/данных БД;
8. удаление старых файлов (с сохранением некоторых, например папки /Uploads);
9. копирование новой версии на продакшен-сервер;
10. установка соответствующих ACL разрешений/других настроек окружения;
11. рекурсивное развертывание зависимостей;
12. запуск приложения;
13. проверка работоспособности.
И это лишь основные пункты. Безусловно, у каждого приложения будет свой список, но в целом все развертывания сводятся к подобному сценарию.
На первый взгляд все вышеперечисленное можно запросто сделать вручную, не так ли? И да, и нет. Практика показывает, что при ручном развертывании что-то зачастую идет не так. Причина тому — человеческая природа. Люди (особенно такие креативные, как девелоперы) не очень хорошо справляются с выполнением однообразных рутинных задач (для этого, собственно, люди и придумали компьютеры). Вот лишь некоторые примеры наиболее глупых ошибок, допущенных при ручном развертывании, с которыми мне приходилось сталкиваться:
· Проверка версии развертываемого исходного кода. Когда-нибудь публиковали /Dev ветку в продакшен-среду просто потому, что Вася Пупкин, ответственный за развертывание, забыл переключился на /Production ветку?
Или того хуже: опубликовать /Production ветку вместе с промежуточными локальными изменениями (ведь про них так легко забыть когда развертываешь hotfix)? И в итоге никто не понимает, почему приложение глючит (я видел, как люди в отчаянии декомпилируют .dll рефлектором, чтобы понять, что там внутри, ведь продакшен-код отличается от любой версии кода в репозитории).
· Сборка решения с указанием всех необходимых настроек. Вы не поверите, насколько часто люди забывают переключить Visual Studio в конфигурацию Release перед сборкой исходного кода. А потом рвут на себе волосы из-за того, что приложение сильно тупит в продакшене из-за компиляции в режиме DEBUG.
· Соответствующее трансформирование конфигурации. Нет ничего веселого в том, когда после нового релиза пользователи внезапно начинают жаловаться на потерю данных, поскольку приложение в продакшене коннектится к базе данных, используемой при разработке (потому что кто-то забыл поменять строку подключения в web.config). Как правило, ручное трансформирование конфигурации — плохая идея, потому что оно не версионируется (что на практике означает, что разработчики должны понимать, в чем отличие между файлами конфигурации для продакшен-среды и среды разработки, и каждый раз объединять их вручную. В итоге, никто до конца не уверен в том, какая же конфигурация используется для продакшен-среды и когда/зачем она была изменена); «Какой requestTimeOut в продакшене? — хм, сейчас 300 секунд, хотя на прошлой неделе было 100. Кто его поменял?»
· Бэкап базы данных. Вы когда-нибудь обнаруживали, что вы забыли сделать бэкап продакшен-БД как раз в тот момент, когда миграционный скрипт глючит и запарывает базу?
Ну в общем вы поняли. Я даже не сомневаюсь в том, что вы хоть раз да и сталкивались с чем-нибудь из вышеперечисленного и сами можете привести кучу других примеров. Основная проблема здесь заключается в том, что такие ошибки очень легко допустить, но при этом зачастую очень трудно докопаться до причины ваших проблем. А на их обнаружение и исправление уходит много времени и сил.
Вот почему у вас либо есть специальный чек-лист по развертыванию или же тот самый Вася Пупкин, ответственный за развертывание (или и то и другое). Однако, как у чек-листа, так и у Васи есть существенные недостатки:
- Чек-листы по развертыванию зачастую всегда устаревшие (разработчики, как правило, не очень то и следят за документацией, и на то есть причина: писать бумажки — скучное занятие). Более того, новые члены команды, которые присоединяются к проекту, вынуждены проходить тренинг по развертыванию, а это занимает время.
- Bus factor вашей команды — 1. Никакую версию/hotfix нельзя будет развернуть, если Вася уехал в отпуск.
Ничто из этого не будет мешать вам жить, если вы автоматизируете развертывание, потому что компьютеры отлично справляются с однотипными рутинными задачами (а мы, люди — нет).
Время — деньги: вы выиграете и то, и другое
Если бы вам предложили миллион долларов прямо сейчас или один цент, который бы вам удваивали каждый день на протяжении месяца, и вы бы выбрали первое — я бы вас огорчил тем, что вы плохой математик, потому что в последнем случае вы бы получили больше десяти миллионов. Дело обстоит точно также с инвестированием в автоматизацию развертывания. Помимо рационализации ваших релизов, вы еще и существенно экономите.
Из личного опыта, единичное развертывание вручную на маленьком проекте занимает у среднестатистического разработчика около часа. В Agile-среде вам будет необходимо постоянно производить развертывания на QA/UAT-платформы для того, чтобы быстро тестировать и внедрять новую функциональность (т. е. производить
Еще одним важным аспектом автоматизации является тот факт, что общая эффективность работы команды повышается, поскольку команда QA больше не будет отвлекать разработчиков от работы над новой функциональностью каждый раз, когда ей будет нужен новый билд на валидацию. На практике это означает большую гибкость.
Взгляните график из книги Макконнелла «Остаться в живых. Руководство для менеджера программных проектов». Чем больше времени проходит между появлением ошибки и ее обнаружением, тем больше времени (и денег) уходит на ее исправление. Возможность развертывания без участия разработчиков, в свою очередь, означает более частые развертывания и, как следствие, более быстрое обнаружение ошибок (таким образом, позволяя вашей команде работать быстрее!).
Развёртывание новых версий становится менее рискованным, а значит — более частым. А более частые развертывания означают большую обратную связь от тестировщиков и конечных пользователей.
Но и это еще не все. Если сделать все с умом, автоматизация развертывания влечет за собой и автоматическую генерацию отчетности, что на практике означает более простое соответствие требованиям аудита и повышает ваши шансы на его успешное прохождение.
Слишком хорошо, чтобы быть похожим на правду? Вот статистика по некоторым показателям нашей команды до и после внедрения автоматизации развертывания на одном из .NET-проектов:
Трудозатраты |
90 человеко-месяцев |
|
Продолжительность |
20 месяцев |
|
Ручное развертывание |
Автоматизированное развертывание |
|
Время развертывания |
2 человеко-часа/развертывание |
16 человеко-часов на единократное внедрение |
Частота развертывания |
Два раза в неделю |
Раз в день |
Коэффициент ошибок |
10% |
2% |
Стоимость развертывания |
16 часов/месяц |
16 часов (единократно) |
Общий profit |
$6400 (320 человеко-часов) экономии; 200%-ное увеличение частоты развертываний; |
И это только простой пример. В более сложных проектах/проектах с высокой частотой развертывания команды могут сэкономить тысячи человеко-часов в год.
Новые возможности, которые открывает автоматизация развертывания
Я — ярый приверженец автоматизации развертывания по двум основным причинам:
- Она освобождает разработчиков от необходимости выполнения рутинных задач, которым сопутствуют ошибки (что, в свою очередь, экономит деньги).
- Она открывает новые возможности, которые могут положительно сказаться на успехе вашего проекта.
ИМХО, вторая причина наиболее важна для бизнеса, поскольку:
· Интеграционные тесты — часть вашего ежедневного рабочего процесса.Все прекрасно знают, что автоматизация регрессионного тестирования целесообразна с финансовой точки зрения. На сегодняшний день есть множество классных инструментов для выполнения интеграционного тестирования. Хороший набор регрессионных тестов пользовательского интерфейса критически необходим для устойчивого развития длительных проектов. В противном случае, через год или два вы попросту не сможете внедрять новую функциональность, поскольку будете слишком озабочены исправлением багов в старой.
Автоматическое развертывание необходимо для того, чтобы проводить эти тесты чаще и в автоматическом режиме. Я рекомендую проводить их в течение дня (а в идеале — после каждого чекина) — это сэкономит вам деньги и позволит придерживаться графика, поскольку вы будете обнаруживать ошибки в течение часа, после того, как ошибка будет допущена.
· Повысить видимость за счет ночных билдов.При Agile-разработке все хотят обеспечить максимальную видимость. Чем чаще вы что-то делаете и показываете владельцам продукта/конечным пользователям, тем быстрее вы понимаете, что именно они хотят от ПО (избавляясь таким образом от ситуации «вы сделали то, что я просил, но это не то, что мне надо»). Отличный способ бесплатно повысить видимость — внедрить ночной билд, который развертывает текущую версию разрабатываемого приложения на тестовое окружение для ознакомления. Таким образом, все заинтересованные стороны (менеджеры, бета-пользователи и т. п.) могут видеть, какая работа была проделана за день.
· DevOps.Если вы и ваша команда хотите погрузиться в мир DevOps, будьте готовы инвестировать в автоматизацию развертывания. Разработчики зачастую не любят задачи из сферы Ops, но просто обожают автоматизировать все вокруг (вот почему мы автоматизируем email-ответы и программируем нашу кофе-машину варить нам кофе каждое утро к нашему пробуждению). Таким образом, скучное занятие по конфигурации новой UAT-платформы превращается в увлекательный челлендж по автоматизации этой процедуры.
· Continuous delivery. Подход Continuous_delivery (каждое изменение, которое проходит автоматизированное тестирование, автоматически попадает в продакшен-среду, в последние годы набирает новые обороты и принимается на вооружение крупными компаниями (WordPress, Google, Facebook, Amazon).
Подводя итог: не использовать автоматизированное развертывание на .NET web-проектах сегодня — самоубийство. Нынешние технологии в данной сфере просты в использовании и позволяют сэкономить время и деньги, устраняют труднодиагностируемые ошибки, поскольку процесс развертывания воспроизводим и версионируем, а также позволяет вашей команде работать быстрее, повышая ее гибкость.
Автор статьи — старший .NET-разработчик компании Itransition.