Сегодня мы хотим поговорить о тонкостях деплоя в условиях, когда нужно регулярно выкатывать большое количество сервисов — как в продакшен, так и в инфраструктурные составляющие. Мы в Учи.ру в свое время столкнулись с потребностью максимально упростить процедуру деплоя, чтобы с ним мог справляться практически каждый разработчик. Мы создали решение, которое оказалось удобным и с которым мы продолжим жить, пока полностью его не перерастем. О том, как все это работает, какие сложности возникают, читайте под катом.
Могут ли разработчики производить деплой сервисов самостоятельно и нужно ли это делать? Этими вопросами активно задаются во многих компаниях, да и сами специалисты тоже. Недавно на глаза попался пост, в котором активно обсуждается негативное влияние высокой нагрузки и широкого спектра обязанностей на разработчиков.
В компании размером с одну команду у каждого члена обычно оказывается много задач, и это нормально. Однако с ростом бизнеса и сложности продукта специализация каждого человека становится уже. Конечно, узкая специализация не означает, что за пределами зоны компетентности не нужно больше ничего знать. Но и перегружать разработчиков нельзя, особенно если это несет риски для стабильности системы.
Поэтому, на наш взгляд, ответ на вопрос «Стоит ли деплоить разработчикам?» зависит от сложности процесса. Если вы регулярно выкатываете обновления для такого же количества систем, как в Учи.ру (с учетом всех инфраструктурных и сервисных решений, продакшена русского, англоязычного и других иноязычных брендов у нас больше сотни приложений, на которые приходится в среднем несколько релизов каждый день), процесс деплоя нужно максимально упрощать, оставаясь в рамках требований безопасности и целостности сервисов.
Только если процесс упрощен до такой степени, что 95% выкаток не требуют вообще никаких специальных знаний, можно поручать деплой разработчикам. Мы приняли для себя это как временное решение, которое было (и пока во многом остается) необходимо и полезно на определенном этапе развития компании. Но даже в этом случае нужно держать руку на пульсе, подразумевая возможность в любой момент подключить к вопросу тех людей, у которых есть эти самые специальные знания. Учитывая, что подобный опыт может быть полезен растущим компаниям, расскажем, как такая задача была решена в Учи.ру.
Съезжаем со стандартных рельсов Ruby
С самого начала мы использовали и до сих пор активно разрабатываем на Ruby on Rails. Стандартным инструментом развертывания в доконтейнерную эпоху был Capistrano — по большому счету набор скриптов, который подключается к удаленным серверам и выполняет необходимые для развертывания шаги: скачать изменения из репозитория, пересобрать статику, перезапустить веб-сервер — и так на каждом хосте.
Подход абсолютно нормальный (мы жили с ним несколько лет), и он полностью оправдывает себя при малых и средних масштабах команд. Но с ростом численности разработчиков, количества используемых серверов и с переходом на работу в кластере возникают различные препятствия.
Например, при росте объемов развертывания стал очевидным еще один минус Capistrano. Когда деплой происходит на клиентской стороне, гарантировать корректность работы скрипта в каждом конкретном случае оказалось сложно.
Приблизительно в это же время мы пришли к необходимости упаковывать наши приложения со всеми их зависимостями в контейнеры.
Первым этапом перехода можно назвать своеобразный симбиоз этих технологий — скрипт, очень напоминающий Capistrano, который собирает docker-образ в облаке и разворачивает его на хостах. Разумеется, это промежуточное решение, но оно позволило убедиться, что мы можем упаковать солидное по размерам приложение в контейнер и оно будет работать как раньше.
За контейнерами в облаке надо было следить — сформировалась потребность в кластеризации и распределении ресурсов. Для этого мы выбрали оркестратор Hashicorp Nomad. Возвращаясь к вопросу в начале статьи: разработчикам нужен был простой интерфейс для деплоев нового функционала, поэтому часть интерфейса, связанная с управлением серверами и docker-кластером, была скрыта. Но на отдельную команду инженеров по эксплуатации в тот момент не было ресурсов. Так и появилась идея максимально упростить процесс деплоя, чтобы он был доступен каждому разработчику, а также целиком происходил на стороне сервера после нажатия кнопки.
Своя платформа
Вдохновили нас на идеи автоматического деплоя сервисы Heroku. Получая инстанс в облаке Amazon, вы работаете с инфраструктурой (IaaS), а обращаясь к Heroku — с платформой (PaaS). Какое-то время назад Heroku был эталоном перехода к автоматизированному деплою в облаке. При работе с Heroku не нужны релизные инженеры, потому что размещение софта происходит автоматически. Однако хостить приложения сколько-нибудь приличных размеров в PaaS-решениях вроде Heroku стоит уже совсем неприличных денег.
Поэтому мы решили сделать свою платформу для упрощенного запуска docker-контейнеров в нашей собственной инфраструктуре. В результате был создан фронтенд для Nomad, который взял на себя следующие задачи:
- максимальное сокращение количества «крутилок» для разработчика, исключая неочевидные моменты, а также универсальные значения для наших облаков;
- перенос запуска деплоя с ноутбуков в облако;
- управление конфигурацией;
- управление секретами.
Созданный инструмент получил название Shaman, и мы до сих пор используем его. Он, конечно, далек от идеала. Например, в Heroku полностью реализовано абстрагирование работы с хранилищами данных. Конфигурирование там тоже работает лучше, чем у нас, по крайней мере, с точки зрения пользовательского опыта.
Но зато Shaman, разработанный для самих себя, отвечает конкретным требованиям компании. Он заточен на быстрое создание приложения, которое сразу впишется во всю инфраструктуру: мониторинг, раутинг, service mesh.
От прочих CI/CD-решений Shaman отличается тем, что практически не приходится конфигурировать сам процесс деплоя, выкатка новых версий происходит по одному и тому же зашитому сценарию. Это тулза, максимально удобная и понятная именно разработчику. Поэтому вместо выбора конвейеров доставки на продакшен и других параметров в Shaman нужно просто вбить нужные значения в набор полей и нажать на зеленую кнопку.
Проблемы? Решаем!
Пользуясь Shaman, разработчики проводят деплой как своих приложений, так и различного вспомогательного софта: хранилищ данных, шин, кешей. Развернуть можно что угодно, для чего есть docker-образ. И в 95% случаев вмешательство «специальных людей» не нужно для того, чтобы развернуть очередной, скажем, Redis.
Для оставшихся 5% есть несколько вариантов:
Если возникли какие-то проблемы с железом, к решению сразу подключается команда платформы. За счет настроенного мониторинга мы обычно узнаем о трудностях еще до запроса от разработчика и максимально быстро помогаем с ними справиться.
Когда проблемы все-таки произошли со сборкой приложения (процесс все равно не идеален, и баги возможны), чаще всего на помощь приходит кто-то из команды инфраструктуры, в основном, это сами разработчики Shaman.
А в случае невыловленных тестированием проблем с кодом приложение вернется разработчику. Автоматизированный деплой в Учи.ру устроен таким образом, что при критической ошибке обновление сразу прекратится. При этом пользовательский трафик не попадает на «плохие» контейнеры.
Вообще, для большинства проблем возможно максимально быстрое восстановление. Для этого предусмотрен механизм отката на предыдущую версию приложения. Сделать это можно за несколько минут, изменив тег docker-образа на более старый. Образы некоторое время не удаляются из реестров.
Достаточно нажать кнопку
Так как Shaman — это наша внутренняя система, мы не очень заморачивались ее продуктовой оберткой. Если бы это был продукт, можно было бы работать дальше над его юзабилити, улучшать интерфейс и писать дополнительные инструкции. Но в нашем случае достаточно того, что в плане деплоя все делается очень просто. После небольшого инструктажа абсолютное большинство разработчиков, которые вообще ничего не знают про деплой, могут нажать на зеленую кнопку — и система сама сделает то, что нужно.
Таким образом, наши разработчики одновременно не получают дополнительных обязанностей, но могут легко и просто деплоить обновленные сервисы самостоятельно — на серверной стороне и по стандартной схеме. Учитывая, что у нас может происходить выкатка нескольких десятков обновлений в день в нормальном режиме, а всего экосистема Учи.ру насчитывает более сотни компонентов, все это приводит к большой экономии времени, причем без участия релиз-инженеров.
Кстати, было бы очень интересно узнать, практикуете ли вы самостоятельный деплой в продуктив, каким образом это реализовано в вашей компании, а также какие плюсы и минусы у этого процесса видны с вашей стороны. Обмен опытом в этом вопросе очень важен, потому что помогает наладить оптимальные условия работы разработчиков.