Вот уже 7 лет мы развиваем Okdesk — облачную help desk систему для малого и среднего бизнеса.
В свое время мы начали с одной виртуальной машины у провайдера.
Постепенно сервис взрослел, менялись приоритеты, задачи и проблемы, с которыми мы сталкивались. Сегодня Okdesk живет уже на третьей версии инфраструктуры.
В этой заметке мы расскажем о том, как и почему эволюционировала архитектура Okdesk. А во второй части поста — почему мы перешли на Kubernetes, каких результатов это позволило добиться и что планируем делать дальше.
Поддерживая бизнес-критичную систему для сотен клиентов, мы стараемся идти на шаг впереди — менять архитектуру еще до того, как старый подход изживет себя окончательно.
В статье нет rocket science, так как в компании и бизнесе мы придерживаемся мнения, что каждый должен заниматься своим делом.
Работа Okdesk построена не на супер-совершенных технологиях, а на бизнесовой составляющей — взаимодействии с клиентами и понимании их потребностей. Для этого нам не требуются квантовые вычисления или иные хайповые решения. Наоборот, мы стараемся использовать проверенные и зарекомендовавшие себя инструменты, которые соответствуют нашим текущим бизнес-требованиям.
Версия 1. Виртуальная машина
Запуская сервис, мы старались как можно быстрее выйти на рынок, поэтому построили инфраструктуру, исходя из принципа наименьшей достаточности. Это была виртуалка в дата-центре на Западе, на которой крутилось само приложение и СУБД (дело было еще до выхода законодательства, запрещающего хранить пользовательские данные за границей). Для стабильной работы MVP этого было более чем достаточно.
Когда к Okdesk подключились на платной основе первые 15 клиентов, мы разнесли приложение и СУБД по разным виртуальным машинам. Но идеологически инфраструктура осталась той же. Мониторили мы ее через ping-admin (инструмент отправляет http-запросы и предупреждает, если ответ отличается от ожидаемого) и на всякий случай регулярно бэкапились в облачный сервис другого поставщика.
Первой версии не хватало надежности. Несмотря на это за время ее работы доступность сервиса не падала ниже 99.97% — это 2 часа простоев в год, считая плановые остановки. Но это не значит, что гипотетически сервис не мог бы упасть на 2 часа и более. Просто нам удалось этого избежать.
Параллельно с подключением новых клиентов мы наращивали ресурсы виртуальной машины. Но вместе с клиентской базой росли и риски в первую очередь для репутации. В какой-то момент мы поняли, что упади сервис на несколько часов, это повлияет на бизнес уже сотни компаний, и суммарно это могут быть миллионные убытки. Так мы начали планировать вторую версию инфраструктуры.
Версия 2. Дублирование серверов
На втором этапе мы пытались перейти от недостаточно надежного решения к более стабильному (чуть более стабильному, чем на тот момент требовал бизнес). В базовых требованиях мы:
ограничили максимальное время неработоспособности сервиса до 15 минут (даже если дата-центр взорвался, не говоря уже о банальном выходе из строя одного сервера);
допустили потерю клиентских данных не более чем за несколько секунд, даже если падает СУБД на продакшне.
Для этого мы дублировали приложение и СУБД на резервный сервер, который вынесли в другой дата-центр (физически расположенный в другом месте) и настроили репликацию данных.
Переключение с основного на резервный сервер в случае аварии должно было выполняться вручную через route 53 от Amazon и занимать не более 5 минут.
Для мониторинга инфраструктуры к уже использовавшемуся ping-admin мы добавили Monit и Scoutapp. Первый собирает базовые метрики сервера, а второй помогает профилировать производительность. Позже Monit расширили клиент-серверным инструментом, который умеет мониторить бизнес-параметры и рисовать картинки.
Вторую версию инфраструктуры мы строили уже в соответствии с законом о защите персональных данных, поэтому размещали сервера в России — на площадке Servers.ru. Подробнее о том переходе можно прочитать в нашей старой статье.
Вторая версия инфраструктуры не требовала глубоких знаний в администрировании. Мы ее создали и первое время поддерживали собственными силами. Впоследствии начали привлекать к обслуживанию подрядчиков. После серии попыток сотрудничать с разными компаниями, остановились на Фланте.
Вторая версия инфраструктуры с небольшими доработками просуществовала чуть более 4 лет. Фактически, это были разрозненные сервера, управлять которыми было довольно сложно из-за обилия ручных процедур. Сервис продолжал развиваться и у нас появилась потребность в бесшовном деплое, раздельной обработке разных типов запросов (например, чтобы API запросы не влияли на работу веб-версии), запуске сторонних приложений. Так мы пришли к необходимости проектировать третью версию инфраструктуры.
Версия 3. Kubernetes
При планировании перехода с первой на вторую версию инфраструктуры мы ограничивались парой бизнес-метрик, описывающих клиентский опыт. Но наш сервис стал более зрелым, количество клиентов стало измеряться сотнями, мы соответственно настроили бизнес-процессы, связанные с его развитием, что повлияло на список требований.
Базовые "клиентские" метрики для проектирования третьей версии
С точки зрения клиентского сервиса мы хотели снизить последствия отключения одного сервера приложений. При падении сервера до переключения на резервную инфраструктуру запросы от клиентов не обрабатывались и нас это не устраивало.
Чтобы полного прекращения обслуживания не происходило, логично раздробить сервис на много мелких серверов или нод. В этом случае падение одного такого сервера (или ноды) обернется не прекращением обработки запросов, а временной потерей мощности. Аналогичную “конструкцию” логично собрать и в резервном дата-центре.
Дробление серверов приложений несет за собой проблемы сквозного мониторинга и сбора логов, балансировки нагрузки, а также синхронизации данных и конфигураций между серверами (и отдельно экземплярами приложений на этих серверах). С конфигурированием у нас и так во второй версии были определенные сложности — очень многие операции, включая парковку доменов, выполнялись вручную, что было чревато ошибками. Все это хотелось автоматизировать, чтобы исключить человеческий фактор.
Тот же подход с дроблением хотелось применить к БД. Но необходимо было учитывать, что запросы из одного дата-центра в другой идут долго и кратно увеличивают время выполнения пользовательского запроса. Поэтому сервер приложений всегда должен обращаться на реплику базы, которая находится в том же дата-центре. Как правило, для этого используют мастер-слейв архитектуру, в рамках которой запись всегда ведется на один мастер-сервер, который шлет копии на слейвы в режиме реального времени. При этом между дата-центрами сервера БД должны распределяться таким образом, чтобы “под боком” у мастера (в том же дата центре) всегда был как минимум один слейв. Так не придется обращаться при “падении” мастера в другой дата-центр, а заодно при необходимости туда можно отправлять на обработку медленные запросы.
Простота развития
С точки зрения дальнейшего развития сервиса мы хотели бесшовный деплой, чтобы конечные клиенты не замечали перезагрузку веб-сервера при выкатке очередных изменений. Почему-то у многих решений на рынке обновления до сих пор сопровождаются остановками. На наш взгляд это прошлый век, а в B2B сегменте, поскольку мы работаем с критичной для бизнеса системой, это особенно важный аспект.
Вторая версия архитектуры ограничивала нас тем, что деплоить приходилось вечером, когда трафик на сервис минимальный. Но иногда у нас возникала необходимость вывести в прод некоторые изменения утром. И пока мы жили на второй версии, приходилось терпеть до вечера.
Также мы хотели облегчить запуск других приложений в настроенном окружении, например, бота в Telegram. Это приложение взаимодействует с API Okdesk и требует определенных ресурсов для своей работы. Необходимо было, чтобы инфраструктура поддерживала интеграцию этого и других приложений каким-то типовым образом, чтобы нам не приходилось каждый раз заново все настраивать.
Легкое управление
Помимо глобальных пожеланий, мы хотели чуть больше возможностей для управления инфраструктурой. В частности, мы хотели влиять на балансировку трафика или изолировать запросы разного типа друг относительно друга, заранее выделяя на них определенный объем ресурсов. Стандартный кейс, где это нужно — мобильное приложение для выездных специалистов. Его используют не только в городах с хорошим покрытием связью, но и там, где мобильный интернет не быстрый. Запросы на загрузку “тяжелых” фотоотчетов о выполненных работах или на полнотекстовый поиск могут “подвешивать” сервис, поэтому их необходимо изолировать от “быстрых” загрузок карточек заявок и т.п.
Какие были варианты кроме Kubernetes?
В теории мы могли развернуть нашу инфраструктуру на нескольких серверах, используя балансировщики нагрузки и настройку параметров серверов и приложений вручную или через Ansible / Chef.
Но такой путь не решает никаких проблем, кроме непосредственно дробления серверов. Удовлетворение остальных требований либо невозможно, либо требует внедрения сторонних инструментов, которые усложняют систему и плодят зоопарк, требующий взаимной интеграции.
На тот момент наш подрядчик, Флант, уже несколько лет специализировался на Kubernetes. Это опенсорсная платформа для управления сервисами в контейнерах с огромной экосистемой.
Флант набрал в этой области большую экспертизу и даже успел разработать свои надстройки, облегчающие управление (они много писали про свои разработки на Хабре: 1, 2, 3). Именно они предложили нам развернуть все на Kubernetes. Честно говоря, мы и сами присматривались к более современным технологиям. Так что выбор был сделан.
Миграцию со второй на третью версию обеспечивал Флант. Он же предложил комплект инструментов — собственный Deckhouse для упрощения контроля, Graylog для сбора логов со всех нод, стандартные в Kubernetes Grafana и Prometheus для мониторинга.
Итоги переезда на Kubernetes
В целом переезд оказался несколько сложнее и дольше, чем мы ожидали. Но мы добились того, чего хотели — получили отказоустойчивый сервис, развернутый на нескольких физических серверах, который автоматически перезапускается в случае нештатных ситуаций. Достигли доступности 99.99%.
Мы можем легко вводить в эксплуатацию новые сервера — после установки минимального ПО Kubernetes делает все сам. Таким образом суммарное время запуска сервера сократилось в 10 раз.
Пользуемся бесшовным деплоем, автоматической парковкой доменов через добавление одной строки в конфиг и т.п. Отселили обработку “тяжелых” запросов в отдельные песочницы, за счет чего ускорили “легкие” запросы.
Не стоит думать, что Kubernetes дает какой-то выигрыш по железу. Дополнительный слой абстракции требует мощностей, которые в общем случае зависят от сложности реализуемой логики. А у нас она сложна — только припаркованных доменов больше 160 штук, и каждый из них требует собственного конфига. Общий объем конфигурации — несколько тысяч строк.
Кроме того, мы понимаем, что вряд ли сможем вырастить полноценную экспертизу по Kubernetes внутри компании, поэтому остаемся завязанными на обращение к подрядчикам. С этим придется смириться. Но Kubernetes уже стал стандартом отрасли, поэтому мы все-таки решились на миграцию и не пожалели.
Есть много вещей, которые хотелось бы улучшить — и мы планируем над этим работать совместно с подрядчиком. В ближайшее время собираемся:
Найти альтернативный дата-центр для размещения резерва. Сейчас они физически находятся в разных дата-центрах, но обслуживаются одним поставщиком услуг, что означает существование общих точек отказа. Мы хотим избавиться от этого риска.
Оптимизировать потребление ресурсов Kubernetes. В современных реалиях наращивать мощности будет сложно, поэтому после завершения активной фазы развития инфраструктуры мы попробуем немного “отжать” сервис и Kubernetes.
Глубже погрузить сотрудников в понимание третьей версии архитектуры — какие есть базовые компоненты, как они друг с другом взаимодействуют, как хранятся конфигурационные файлы и какие вещи в коде сервиса поддерживают Kubernetes. Все это необходимо документировать и озвучивать внутри компании.
В завершении хотелось бы отметить, что если ваша компания ищет функциональную систему автоматизации процессов сервиса, техподдержки и выездного обслуживания с надежной и отказоустойчивой архитектурой, то вы знаете что найти ее можно у нас, в Okdesk. Присоединяйтесь к 800+ компаний, которые каждый день сфокусированы на основном бизнесе, а не поиске или разработке собственного ПО для решения обозначенных выше задач.