Как мы меняли инфраструктуру облачного решения: от одной виртуальной машины к кластеру Kubernetes

Моя цель - предложение широкого ассортимента товаров и услуг на постоянно высоком качестве обслуживания по самым выгодным ценам.

Вот уже 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+ компаний, которые каждый день сфокусированы на основном бизнесе, а не поиске или разработке собственного ПО для решения обозначенных выше задач.

Источник: https://habr.com/ru/company/okdesk/blog/695786/


Интересные статьи

Интересные статьи

werf — это CLI-утилита с открытым кодом для сборки приложений и их деплоя в Kubernetes. С версией v1.2 она получила множество изменений и улучшений, которые мы так тщательно тестировали и дорабатывали...
Мы столкнулись с достаточно занятным поведением при работе с Headless-сервисом в Kubernetes. В нашем случае проблема возникла с mongos, но она актуальна для любого Headle...
В данной пошаговой инструкции мы подробно опишем весь процесс получения доступа к WhatsApp Business API через официального партнера Facebook — сервис Gupshup и подключени...
Can I just once again state my love for [WireGuard] and hope it gets merged soon? Maybe the code isn't perfect, but I've skimmed it, and compared to the horrors that are OpenVPN and IPS...
Лучшие практики Kubernetes. Создание небольших контейнеров Лучшие практики Kubernetes. Организация Kubernetes с пространством имен Лучшие практики Kubernetes. Проверка жизнеспособно...