Нужно ли запрещать деплоить в production в определённое время? Или движение #NoDeployFriday стало реликтом времён, когда не было всеобъемлющих интеграционных тестов и непрерывного деплоймента?
В своей команде вы могли столкнуться с той же самой дилеммой. Кто прав, а кто виноват? Является ли отказ от деплоя по пятницам разумной стратегией снижения рисков, или это вредная культура, мешающая нам создавать более качественные и устойчивые системы?
Динь-динь
Уверен, что инженеры, имевшие счастье быть «на связи», лишались выходных из-за всё сломавших пятничных изменений. Я тоже был в такой ситуации. Телефонный звонок во время выхода с семьёй или посреди ночи, уведомляющий о падении приложения. После того, как залезешь в компьютер и проверишь быстро растущие логи, становится очевидно, что всё порушило редкое необработанное исключение. Отвратительно.
В ходе анализа выясняется, что для сценария, который привёл к сбою, не были написаны тесты, видимо, потому что это не посчитали вероятным. После ряда длительных созвонов с другими инженерами в поисках лучшего способа откатить изменения и всё исправить, система снова начинает работать. Фух.
В понедельник проводится встреча «пять почему».
"Давайте просто прекратим деплоить по пятницам. Тогда на выходных всё будет стабильно работать, а на следующей неделе мы будем начеку после всевозможных релизов".
Все кивают. Если что-то не уходит в эксплуатацию до полудня четверга, то оно ждёт до утра понедельника. Такой подход вредит или помогает?
Как вы знаете, высказывания в Твиттере часто очень субъективны. Хотя запрет пятничных релизов выглядит разумным, кто-то быстро укажет, что это просто костыль из-за хрупкости платформы, причина которой в плохих процессах тестирования и деплоя.
Некоторые даже предполагают, что вам просто больше нравится спокойное развёртывание, чем сами выходные:
Другие пользователи полагают, что возможным решением проблемы может быть внедрение флагов функций.
Этот пользователь считает, что проблемы рискованного деплоя не должно возникать благодаря доступным нам сегодня процессами и инструментам.
Кто принимает решения?
Весь этот обмен мнениями свидетельствует о том, что мы, как сообщество инженеров, можем сильно расходиться во мнениях и не обязательно соглашаться друг с другом. Кто бы мог подумать. Вероятно, эта ситуация также демонстрирует, что общая картина с #NoDeployFriday содержит такие нюансы, которые не слишком хорошо отражены в Твиттере. Верно ли, что мы все должны применять непрерывный деплоймент, а иначе «делаем неправильно»?
В принятии подобного решения есть психологический аспект. Неприязнь к пятничным релизам происходит из страха сделать в течение недели ошибки (из-за усталости или спешки), которые могут навредить, пока большинство сотрудников два дня отдыхают. В результате пятничный коммит, содержащий потенциальную проблему, может испортить выходные куче народу: дежурным инженерам, другим инженерам, которые будут удалённо помогать решать проблему, а возможно и специалистам по инфраструктуре, которым придётся восстанавливать повреждённые данные. Если сбой окажется серьёзным, то в ситуацию могут быть вовлечены и другие сотрудники компании, которым нужно будет связываться с клиентами и минимизировать ущерб.
Заняв позицию идеалиста, можно предположить, что в идеальном мире с идеальным кодом, идеальным покрытием тестами и идеальным QA никакие изменения не смогут привести к проблеме. Но мы люди, а людям свойственно ошибаться. Всегда будут какие-то странные пограничные случаи, которые не закрыты при разработке. Это жизнь. Так что движение #NoDeployFriday имеет смысл, хотя бы теоретически. Однако это лишь слепой инструмент. Я считаю, что оценивать сделанные изменения нужно в зависимости от ситуации, и априори нужно исходить из того, что мы деплоим в любой день, даже по пятницам, но при этом должны иметь возможность изолировать те изменения, которые должны подождать до понедельника.
Есть некоторые вопросы, которые мы можем обсудить. Я поделил их на категории:
- Понимание «радиуса поражения» изменения.
- Продуманность процесса деплоя.
- Способность автоматически определять ошибки.
- Сколько времени уходит на решение проблем.
Теперь давайте обсудим.
Понимание «радиуса поражения»
Когда в онлайне опять начинают ломать копья про пятничные релизы, всегда забывают о важном — о самой природе изменений. Не бывает одинаковых изменений в кодовой базе. Одни коммиты немного правят интерфейс и ничего более; другие рефакторят сотни классов, не затрагивая функциональность программы; третьи меняют схемы базы данных и вносят серьёзные изменения в процесс потребления данных в реальном времени; четвёртые могут перезапустить один экземпляр, в то время как пятые способны инициировать каскадный перезапуск всевозможных сервисов.
Глядя на код, инженеры должны хорошо представлять «радиус поражения» вносимых изменений. Какая часть кода и приложения будет подвержена влиянию? Что может упасть, если новый код будет сбоить? Это всего лишь клик по кнопке, который выкинет ошибку, или будут потеряны все новые записи? Изменение вносится в один изолированный сервис, или синхронно поменяются многие сервисы и зависимости?
Не представляю, кто будет отказываться вносить изменения с небольшим «радиусом поражения» и простым деплоем в любой день недели. Но при этом внесение крупных изменений — особенно, связанных с инфраструктурой хранилищ, — должно проводиться осторожнее, возможно, в то время, когда в онлайне находится меньше всего пользователей. Будет ещё лучше, если такие масштабные изменения запускать в эксплуатацию параллельно, чтобы протестировать и оценить их работу при реальной нагрузке, и никто об этом даже не узнает.
Здесь нужно принимать решения в зависимости от ситуации. Каждый ли инженер осознаёт «радиус поражения» изменений в production-среде, а не только в среде разработки? Если нет, то почему? Можно ли улучшить документацию, обучение и отображение влияния изменений кода в production?
«Радиус поражения» маленький? Запускайте в пятницу.
«Радиус поражения» большой? Ждите до понедельника.
Продуманность процесса деплоя
Один из способов снижения рисков заключается в непрерывном совершенствовании процесса деплоя. Если для запуска свежей версии приложения всё ещё необходимо, чтобы специалист знал, какой нужно запустить скрипт, какой файл и куда скопировать, то пора плотно заняться автоматизацией. За последние годы инструментарий в этой сфере шагнул далеко вперёд. Мы часто используем Jenkins Pipeline и Concourse, они позволяют прямо кодом задавать конвейеры сборки, тестирования и деплоя.
Процесс полной автоматизации развёртывания — вещь интересная. Он позволяет вам отступить назад и попробовать абстрагировать то, что должно произойти с момента инициализации pull request до отправки приложения в эксплуатацию. Описание всех шагов в коде, например, в упомянутых выше инструментах, поможет вам обобщить определения шагов и повторно использовать их во всех приложениях. К тому же вам будет интересно отметить некоторые странные или ленивые решения, которые вы когда-то приняли и с которыми смирились.
Каждому инженеру, который прочитал предыдущие два параграфа и отреагировал в стиле «Ну конечно! Мы это делаем годами!» я могу гарантировать, что ещё 9 других представили свою инфраструктуру приложения и скривились, осознав объём работы, который нужно проделать для перевода системы на современный конвейер деплоя. Это подразумевает использование преимуществ современных инструментов, которые не только выполняют непрерывную интеграцию, но и позволяют непрерывно поставлять баги в прод, причём инженерам достаточно нажать кнопку для ввода в эксплуатацию (или вообще делать это автоматически, если вы достаточно смелы).
Совершенствование конвейера деплоя требует вовлечённости и соответствующего персонала — это точно не побочный проект. Хорошим решением будет выделить команду для улучшения внутреннего инструментария. Если они ещё не знают о существующих проблемах — а они наверняка знают, — то можно собрать информацию по самым болезненным ситуациям, связанным с процессом релиза, затем приоритезировать и совместно с другими заняться исправлением. Медленно, но верно положение будет улучшаться: код станет отправляться в эксплуатацию быстрее и с меньшим количеством проблем. Всё больше людей смогут изучать лучшие подходы и самостоятельно вносить улучшения. По мере выправления ситуации, подходы будут распространяться в командах, и этот новый проект будет завершён правильно, без привычного копирования старых дурных привычек.
С момента мерджа pull request’а до внесения коммита должен быть автоматизирован настолько, чтобы вам даже не нужно было думать об этом. Это не только помогает изолировать реальные проблемы в QA, потому что единственной переменной является изменённый код, но делает написание кода куда более приятным делом. Введение в эксплуатацию децентрализуется, что повышает личную автономность и ответственность. А это, в свою очередь, приводит к более обдуманным решениям относительно того, когда и как выкатывать новый код.
Надёжный конвейер деплоя? Выкатывайте в пятницу.
Вручную копируете скрипты? Ждите до понедельника.
Способность определять ошибки
Введение в эксплуатацию не останавливается после того, как код начал работать. Если что-то идёт не так, нам нужно знать об этом, и желательно, чтобы нам об этом сообщали, а не приходилось выискивать информацию самостоятельно. Для этого нужно автоматическое сканирование логов приложений на ошибки, явное отслеживание ключевых метрик (например, количество обработанных сообщений в секунду, или доля ошибок), а также система предупреждения, сообщающая инженерам о возникновении критических проблем и демонстрирующая негативную тенденцию по определённым метрикам.
Эксплуатация всегда отличается от разработки, и инженерам нужно отслеживать работу определённых частей системы. Нужно отвечать на вопросы о каждом последующем изменении: оно ускорило или замедлило систему? Таймаутов стало больше или меньше? Мы ограничены по процессору или по вводу/выводу?
Данные по метрикам и ошибкам должны передаваться в систему предупреждения. У команд должна быть возможность определять, какие сигналы свидетельствуют о негативной ситуации, и рассылать автоматические сообщения об этом. Для наших команд и самых серьёзных инцидентов мы используем PagerDuty.
Измерение метрик production-системы означает, что инженеры смогут увидеть, если что-то изменилось после каждого деплоя, к лучшему или к худшему. И в самых плохих случаях система автоматически сообщит кому-то о возникшей проблеме.
Хороший мониторинг, уведомления и дежурные специалисты? Деплойте в пятницу.
Вручную просматриваете логи через ssh? Ждите до понедельника.
Сколько времени уходит на решение проблем
Наконец, главный критерий — сколько времени займёт исправление проблем. Это отчасти зависит от «радиуса поражения» вносимых изменений. Даже если у вас вылизанный конвейер деплоя, некоторые изменения трудно быстро исправить. Откат изменений в системе извлечения данных и в схеме поискового индекса может потребовать трудоемкого переиндексирования, помимо исправления какой-то строчки кода. Средняя длительность деплоя, проверки, исправления и переразвёртывания изменений в CSS может составлять минуты, в то время как серьёзные изменения в хранилище могут потребовать дней работы.
Для всех работ в рамках конвейера деплоя, которые на макроуровне могут повысить надёжность внесения изменений, никакие изменения не являются одинаковыми, поэтому нужно оценивать их по отдельности. Если что-то пойдёт не так, мы сможем всё быстро исправить?
Полностью исправляется с помощью одного восстанавливающего коммита? Деплойте в пятницу.
Возможны большие затруднения, если что-то пойдёт не так? Ждите до понедельника.
Думайте сами, решайте сами
Какова моя позиция по #NoDeployFriday? Я считаю, что всё зависит от релиза. Изменения с маленьким «радиусом поражения», которые легко откатить, можно деплоить в любое время в любой день. При больших изменениях, влияние которых нужно внимательно отслеживать в production-системе, я очень рекомендую подождать до понедельника.
По сути, это вам решать, деплоить ли по пятницам. Если вы работаете со скрипучей и хрупкой системой, то лучше избегать пятниц, пока не сделаете всё необходимое, чтобы улучшить процесс деплоя. Только обязательно это сделайте, не отмахивайтесь. Отказ от пятничных релизов — это нормальный способ прикрыть временные недоработки в инфраструктуре. Это разумное снижение ущерба ради блага бизнеса. Но плохо, если это правило прикрывает постоянные недоработки.
Если вы не уверены в том, какой эффект окажут изменения, то отложите до понедельника. Но подумайте, что можно сделать в следующий раз, чтобы лучше представлять себе этот эффект, и улучшите для этого сопутствующую инфраструктуру. Как и всегда в жизни, у каждого решения есть свои нюансы. Решения не делятся на «чёрное» и «белое», на «правильное» и «неправильное»: пока мы делаем всё что можем для бизнеса, приложений и друг друга, улучшая свои системы, значит мы всё делаем хорошо.
Успешного деплоя.
Автор: AloneCoder