Не так давно мы в департаменте информационных систем (далее – ДИС) ИТМО начали выстраивать новую инфраструктуру для деплоя наших проектов. Образовательным организациям обычно с бюрократической точки зрения сложно прийти к масштабным внедрениям. Нам повезло ― мы смогли путем проб и ошибок выбрать удобные проверенные технологии и реализовать единую среду, которая задала формат взаимодействия между администраторами и разработчиками.
В общей сложности подбор инструментов и их внедрение заняли полтора года. Конечно, иногда был непросто: наступали на “грабли” и возвращались, чтобы выбрать более удачный путь. И это несмотря на то, что в общих чертах было изначально понятно, куда двигаться.
Проанализировав свой опыт, мы решили поделиться основными предпосылками и выводами. Хочется надеяться, что это облегчит внедрение тем, кто пойдет аналогичной дорогой.
В рамках университетского блога мы вводим новую рубрику по DevOps, в которой Lead DevOps инженер ДИС Михаил Рыбкин расскажет, как вместе с командой внедрил платформу деплоя для разработчиков.
Кому это может быть полезно
Наш рассказ в первую очередь ориентирован на те компании, в которых есть выделенная команда администрирования и большое количество проектов (сервисов или микросервисов). Основной критерий ― это работа с большим объемом запускаемого софта и количеством команд разработки.
Как построен рассказ
Повествование будет разбито на несколько частей. Первая часть ― постановка задачи, выбор фундамента и установка базовых правил-гайдлайнов. Возможно, кто-то найдет информацию из этой статьи очевидной и понятной, но она нужна, чтобы "синхронизировать часы" на старте нашего пути.
Следующие части будут рассказывать о конкретных инструментах: архитектуре, абстракциях, алгоритмах работы. Каждый пост будет самостоятельным рассказом, в то же время вместе они составят единое руководство. Возможно, вам нужны не все описанные нами инструменты. В этом случае отдельные части повествования можно пропустить. По мере выхода статей мы добавим все ссылки в конце этого текста.
Итак, к делу.
Как звучала задача
Чтобы сформулировать задачу, для начала нужно понять проблему. Дело в том, что с недавних пор, у нас в департаменте ведется разработка и внедрение новых крупных сервисов. Начиналось все в духе стартапа: разработчики, придумывая новый функционал, тут же его писали и выпускали, однако когда кода стало слишком много, появилась проблема в его сопровождении ― программисты должны были не только реализовывать новые функции, но и поддерживать растущую инфраструктуру, на которой были развернуты их сервисы. В итоге на запуск нового сервиса уходило порой несколько недель, и каждая команда выстраивала свои процессы по-своему, что приводило местами к крайне неоптимальной архитектуре. В какой-то момент было принято решение вынести работу с окружениями на отдельную команду, так и началась эта история.
Нам была поставлена задача выдать разработчикам удобный инструментарий для деплоя и забрать проблемы эксплуатации и вопросы оптимизации под свое крыло.
Основные KPI ― time-to-market (время запуска нового сервиса от момента написания кода до момента выхода в продакшн) и uptime (время непрерывной работы).
Первое, что стало понятно ― с темпами роста объемов кода нам нужно было сразу убирать прямую зависимость между количеством поддерживаемых приложений и объемом внимания администраторов. В идеале, для развертывания нового проекта разработчик вообще не должен связываться с администратором.
Планируя новую инфраструктуру, мы для себя выделили три основных направления развития:
Observability – "прозрачность" операций. В любой момент времени нам нужно понимать, в каком состоянии, под какой нагрузкой и с какими ошибками работает каждое из развернутых приложений. На этапе формирования задачи разработчикам приходилось самостоятельно придумывать, как наблюдать за действиями пользователей, собирать аналитику приложений и отслеживать ошибки. Мы должны были придумать и предложить общую удобную схему, которая повысит прозрачность работы. Для этого мы вывели четыре параметра ― метрики, логи, ивенты и сообщения об ошибках.
Security. Как и любая крупная компания, иногда мы сталкиваемся с атаками на наши сервисы, причем не только внешними, но и внутренними (утечки доступов, привилегий и т.д.). Поэтому при проектировании новой инфраструктуры нельзя было обойти стороной вопрос безопасности, методы работы с ней нужно закладывать в самый фундамент системы. Задача осложнялась тем, что нам нужно было не только предусмотреть методы борьбы с известными нам атаками, но и оставить возможности для отработки новых, тех, с которыми мы до этого не сталкивались.
Automation. Все операции сопровождения разработки, которые можно автоматизировать, должны быть автоматизированы. Причем речь не только про развертывание (т.е. доставку кода в окружение), но и про эксплуатацию. Взаимодействие нужно было построить так, если какой-то сервис падает из-за ошибки, которую можно было заранее предусмотреть, администратор для ее решения не требовался ― в системе должен быть заложен конкретный алгоритм действий, по которому она попытается исправить проблему в автоматическом режиме.
Еще одним важным аспектом инфраструктуры, который нужно было заложить на старте, стала ее модульность. Идеального инструмента, решающего свою задачу без компромиссов, не существует, поэтому нам важно было оставить возможность менять части системы, не переделывая всю платформу.
Последнее, что нам оставалось сделать до старта ― реализовать простой и удобный канал связи с разработчиками развертываемых нами сервисов, чтобы мы могли заранее их предупреждать обо всех изменениях в системе, сервисных работах и возможных инцидентах.
Задача понятна, перейдем к решению.
Подбор фундамента, или как мы пришли к Kubernetes
Для построения такой инфраструктуры нужен мощный фундамент. Все наши новые проекты разрабатываются и запускаются в докер-контейнерах на нескольких серверах, соответственно, нам нужна была платформа, которая помогла бы нам этим всем управлять ― оркестратор. Их на рынке не так много, варианты перед нами были следующие:
Docker swarm ― логическое развитие экосистемы docker. Большое преимущество в простоте внедрения ― все наши контейнеры уже были декларативно описаны с помощью утилиты docker-compose, которая лежит в основе конфигурации docker swarm. Однако, решение предполагает ручную поддержку при эксплуатации, что для нас критично, учитывая, что количество серверов будет только расти, нагрузка на администраторов будет возрастать в прямой пропорции.
Nomad ― оркестратор от Hashicorp, компании, известной своими Enterprise-инструментами. Достаточно простой в освоении, очень гибкий и легкий, но он также предполагает ручную поддержку, что нам не очень подходит.
Kubernetes ― детище CNCF (Cloud Native Computing Foundation ― фонд облачных вычислений, основанный и поддерживаемый крупнейшими игроками индустрии: Google, Apple, Microsoft, AWS, Cisco и другие), самый известный оркестратор. Его тяжело освоить, но у него есть огромное преимущество: он изначально заточен под использование в качестве управляемого облачным провайдером сервиса. Это значит, не нужно тратить время и силы команды администрирования на поддержку его в рабочем состоянии, за это отвечает облако.
В итоге мы остановили свой выбор на Kubernetes, а дальше нас ждал тяжелый путь освоения инструмента ― его абстракций, гайдлайнов использования. Более подробно о них мы расскажем в одной из следующих статей.
Выбор Kubernetes также сопровождался принятием решения об использовании управляемого оркестратора от облачного провайдера. У ИТМО есть собственный дата-центр, где крутятся корпоративные системы. В этом есть определенные преимущества, но Kubernetes ― слишком масштабная система для ручного администрирования, поэтому мы решили не разворачивать его своими силами. Аренда очень хорошо вписалась в концепцию минимизации трудозатрат администраторов, а освободившееся от обслуживания серверов время можно направить в оптимизацию и развитие инфраструктуры.
Канал коммуникации
Дополнительно для связи между разработчиками и администраторами мы создали канал в Telegram. У нас давно назревала потребность выработать некий единый формат ведения диалога. Теперь если возникают какие-то сложности с любой из сторон, о них можно оперативно информировать. Например, мы можем оперативно писать туда об инцидентах или предстоящих обновлениях сопутствующих сервисов (когда нужно, чтобы команда конкретного приложения была на связи в определенное время).
Этот канал диалога по важности для нас оказался чуть ли не на уровне самого Kubernetes, потому что мы не можем изменять платформу, не предупредив разработчиков. В нашей парадигме взаимоотношений мы не диктуем им свои правила. Наша задача скорее в том, чтобы дать им инструменты для реализации своих потребностей, мы должны сделать так, чтобы разработчикам было удобно и комфортно пользоваться нашей инфраструктурой (чтобы у них не возникало желания пытаться по-своему все разворачивать, увеличивая разнородность применяемых решений).
Логика работы
Сейчас разработчики ДИС ИТМО имеют постоянный доступ к автоматизированному деплою. Можно в любой момент (хоть посреди ночи) запустить новый сервис или отредактировать параметры запуска своего приложения ― выдать ему больше ресурсов, изменить параметры входа, etc. Мы к этому долго шли и наконец достигли этого.
Для удобства эксплуатации мы разделили все запускаемые проекты на базовые группы. В одну группу объединяются проекты, которые разрабатываются одной командой, или те, которые должны запускаться вместе в одном ЦОДе (у нас их несколько). Каждая группа получает свой namespace в нужном ей кластере, свой гит-репозиторий конфигурации и свою группу для репозиториев с кодом (об этом подробнее читайте в следующих статьях). При этом группы проектов друг о друге ничего не знают.
Идея отдельных групп позволяет уменьшить скоуп ошибок. Например, у каждой группы ― свой gateway, соответственно, если при его обновлении возникнут проблемы, затронуты будут не все наши проекты, а только те, которые в нее входят. Еще одно преимущество групп состоит в организационной составляющей. Создание группы запрашивают тимлиды команд, соответственно, за каждой группой есть ответственный за нее человек, и у нас есть четкое понимание, кого предупреждать в случае сервисных работ или инцидентов.
Сейчас у нас запущено 5 кластеров kubernetes ― две пары девелоп-продакшн в разных ЦОДах и сервисный кластер, в котором крутятся инструменты поддержки деплоя (хранилище секретов, базы логов, мониторингов, etc).
Для визуализации происходящего в кластерах мы используем Lens. Это бесплатный IDE для работы с кластерами. У Kubernetes есть собственный терминальный инструмент kubectl, но на больших масштабах комфортнее работать с картинкой.
Еще одним важным инструментом для работы с несколькими кластерами для нас является KubeContext (или подобные). Он позволяет удобно выбирать, в какой именно кластер применять текущие изменения.
Также советуем всем ознакомиться с концепцией 12-факторного приложения, которая описывает важные для работы проектов гайдлайны.
Что в итоге
Платформа уже запущена. В общей сложности на запуск мы потратили полтора года. Хотя уже какое-то время идет “боевая” эксплуатация, мы продолжаем дорабатывать систему крупными мазками: оптимизировать, улучшать и перестраивать.
Не все инструменты мы внедрили корректно с первого раза ― кое-что пришлось переразвернуть. Отсюда и родилась идея этого цикла статей. Мы хотим показать, на какие "грабли" можно наступить в процессе создания инфраструктуры развертывания, и какие соображения учесть при их обходе.
Например, тот факт, что некоторые проекты лучше деплоить вместе в группах (и по какому принципу их выбирать) ― это вроде бы очевидный момент, но его необходимо проговорить для новичков в Kubernetes. И если это не учесть на старте, потом очень много времени уйдет на то, чтобы перевернуть все так, чтобы было удобно.
Будем надеяться, что наши последователи потратят на это не полтора года, а вполне реалистичные для бизнеса несколько месяцев.
В следующий раз поговорим о сервисах доставки кода и деплоя. Если Kubernetes ― это фундамент нашей системы, то эти сервисы ― своего рода первый этаж.