Как Asana использует Kubernetes

Kate

Administrator
Команда форума
В Asana мы используем Kubernetes для развертывания сервисов и управления ими независимо от монолитной инфраструктуры. Поначалу у нас были некоторые проблемы, и чтобы стандартизировать создание и обслуживание приложений Kubernetes, мы создали фреймворк с незамысловатым названием KubeApps. В последние два года наша команда по инфраструктурной платформе вносила улучшения в KubeApps, чтобы упростить развертывание сервисов в Asana. Здесь мы расскажем, какие проблемы мы хотели решить в Kubernetes и как мы это сделали с помощью фреймворка KubeApp.

Введение​


Мы уже рассказывали о legacy-системе деплоймента в Asana — наша основная инфраструктура организована как монолит инстансов AWS EC2 с кастомными скриптами конфигурации для каждого сервиса. Никакого масштабирования у нас не было: отправляешь новый код в монолит — переконфигурируй все хосты. Чтобы добавить новый сервис, нужен был новый набор кастомных скриптов конфигурации. Все это было сложно обслуживать, плюс был риск увеличить нестабильность деплоев в монолите.


Когда мы обдумывали инфраструктуру для Luna2, решили использовать Kubernetes, чтобы деплоить сервисы и управлять ими независимо от монолита. Оркестрация контейнеров пошла хорошо, и остальные инженеры захотели использовать Kubernetes для других систем Asana. Мы доработали эти инструменты, чтобы и другие команды могли собирать и деплоить сервисы в контейнерах.


Kubernetes в Asana​


С Kubernetes управлять сервисами стало гораздо проще, ведь у нас есть четкие границы между процессами и окружениями, где они выполняются. В итоге разработчики приложений могут собирать и обновлять одни сервисы, не боясь навредить другим.


Расширять инфраструктуру за пределы монолита EC2 стало, конечно, проще, но Kubernetes пока не решал всех наших проблем (примечание: В Kubernetes есть Cloud Controller Manager, который управляет нодами, настраивает маршруты между контейнерами и интегрируется с компонентами облачной инфраструктуры).


  • Управление ресурсами AWS никак не связано с Kubernetes. Разработчикам надо было заранее создавать ASG и готовить их для контейнеров Docker и любых других ресурсов, которые могут понадобиться приложению.
  • Мы тратили слишком много времени на инструментирование во всех сервисах, например, для сборки метрик и настройки разрешений для секретов, причем мы постоянно делали одно и то же — настраивали ELB, управляли группами конфигурации для каждого приложения...
  • Continuous delivery в Kubernetes не встроена. На уровне абстракции Kubernetes логика приложения должна быть упакована в образы, доступные в container registry.

Чтобы решить эти проблемы и стандартизировать создание и обслуживание приложений Kubernetes, мы создали фреймворк с незамысловатым названием KubeApps. Изначально мы задумали KubeApp для обработки всех аспектов развертывания — от сборки необходимых ресурсов до обновления DNS во время деплоя и плавного перехода между версиями кода. Каждый KubeApp определяется набором требований к «железу», определений подов и спецификаций сервиса.


Конфигурация как код​


Все конфигурации KubeApp существуют в виде Python-кода, поэтому поддерживают программно созданные конфигурации и обеспечивают согласованность с помощью общих библиотек. С этими конфигурациями мы можем объявлять и настраивать внешние ресурсы, необходимые для KubeApp.


На схеме показаны спецификации примера веб-приложения и способ его представления в системе конфигурации KubeApp. Деплоймент запрашивает оборудование, ELB и сборки образов. Мы предоставляем дефолтные спецификации для обработки конфигураций DNS и включаем определения подов для обработки метрик и логирования.



Образы Docker с continuous deployment​


Код приложения пакуется в Docker-образы с помощью образов Bazel или традиционных Dockerfile. Наш KubeApps собирает и отправляет эти образы в рамках пайплайна CD, так что образы для любого сервиса доступны в нашем registry.


Для сборки зависимостей и управления ими в большинстве случаев мы используем Bazel. Это особенно удобно с контейнеризованными приложениями, потому что таким образом мы объявляем зависимости и упаковываем сторонние библиотеки в исполняемые файлы. Так мы получаем детерминированные выходные данные при настройке контейнерных окружений для каждого приложения.


По одному кластеру на KubeApp​


При использовании Kubernetes нужно решить, как делить сервисы между кластерами (примечание: некоторые соображения о компромиссах при выборе числа кластеров приводятся в этой статье на learnk8s.io: Проектирование кластеров Kubernetes: сколько их должно быть?). Деплоить сервисы в один кластер Kubernetes — это экономично и удобно в плане администрирования, потому что сервисы используют одни ресурсы мастер-ноды, а такие операции, как апгрейд версий Kubernetes и деплойменты, нужно выполнять всего один раз. Но модель с одним кластером не особо хороша для мультитенантности, а кластер становится единой точкой отказа. Один кластер Kubernetes ограничен в плане масштабирования, так что при достижении определенного размера неплохо было бы его разделить.


В Asana каждый KubeApp деплоится в своем кластере Kubernetes через AWS EKS. Такой подход гарантирует безопасность и устойчивость приложения. Каждый кластер отвечает за один сервис, так что можно не волноваться о состязании за ресурсы между сервисами, а если кластер упадет, пострадает всего один сервис.


Управлять несколькими кластерами сложновато, потому что дефолтные инструменты Kubernetes могут взаимодействовать только с одним кластером за раз. Поэтому мы создали инструменты для управления несколькими кластерами одновременно в KubeApps. Еще мы обнаружили, что такая модель позволяет владельцам отдельных KubeApp независимо управлять кластером (апгрейдить ноды, масштабировать деплои и т. д.)


Процесс развертывания KubeApp​


image



Для развертываний KubeApp мы используем центральный хаб управления, который мы назвали kubecontrol. Его можно настроить для обновления вручную или автоматически, через cron. Развертывание KubeApp включает несколько шагов:


  1. Для обновления или создания KubeApp мы вводим команды в kubecontrol.
  2. Из спецификаций приложения мы запрашиваем набор ресурсов, необходимых для KubeApp (Auto Scaling Groups, спотовые инстансы и т. д.). Создается новый кластер EKS.
  3. Мы делаем запрос к сервису сборки образов, чтобы собрать образ docker с определенной версией кода. Сборщик образов компилирует код для KubeApp и отправляет образ в ECR (Elastic Container Registry), если его там еще нет.
  4. После сборки всех ресурсов мы передаем спецификации компонентов кластеру Kubernetes, чтобы он получил нужные контейнеры docker от ECR и задеплоил их на нодах.

Полное обновление KubeApps — это blue-green деплой, для которого нужно запустить и настроить новый кластер EKS в AWS. Убедившись, что новый KubeApp работает, мы переключаем нагрузку на новый кластер и сносим старый. В KubeApps можно делать rolling апдейт, при котором обновляются образы на запущенном кластере. Это позволяет быстро и незаметно переходить с одной версии кода на другую без запуска целого нового кластера.


Консоль управления KubeApp​


До недавнего времени единственным способом прямого мониторинга или управления KubeApp было ssh-подключение к kubecontrol и взаимодействие с приложением через CLI. Искать информацию о деплоях было непросто, так что пользователям приходилось изучать логи, чтобы понять, когда в KubeApp была развернута определенная версия кода. Чтобы внести больше ясности, мы создали KubeApp Management Console (KMC), которая отвечает за запись информации о прошлых деплоях. Мы хотим использовать эту консоль как централизованный веб-интерфейс, в котором пользователи могут взаимодействовать с KubeApps.


Что собой представляет KubeApps сегодня и что будет дальше​


Сейчас у нас больше 60 KubeApp в Asana, которые поддерживают самые разные рабочие нагрузки — от управления релизами до распределенного кэширования. Пока мы сохраняем монолит инстансов EC2, но уже переделываем эти сервисы в контейнеры в KubeApps.


Команда инфраструктурной платформы продолжает активную работу над KubeApps. В будущем мы планируем поддерживать больше архитектур (ARM64) и провайдеров инфраструктуры (AWS Fargate). Еще мы планируем создать инструменты для более удобной разработки в KubeApps, чтобы их можно было запускать в песочницах и локальных окружениях. Благодаря этим и другим изменениям фреймворк KubeApps можно будет приспособить для любой рабочей нагрузки, которая может нам понадобиться.


Источник статьи: https://habr.com/ru/company/southbridge/blog/555524/
 
Сверху