В 2024 году компания Uber завершила важный технологический переход — миграцию своей статeless платформы управления контейнерами с Apache Mesos на Kubernetes. Этот шаг стал неотъемлемой частью стратегии компании по обеспечению масштабируемости, надежности и безопасности инфраструктуры, а также интеграции с индустриальными стандартами. Переход сопровождался серьезными техническими вызовами, которые повлияли не только на архитектуру вычислительной платформы, но и на принципы работы внутренних процессов и взаимодействия с разработчиками. Одной из главных мотиваций перехода стало устаревание Mesos, который был снят с поддержки внутри Uber еще в 2021 году. Сообщество вокруг данного проекта перестало активно развивать кодовую базу, что ограничивало компании возможности внедрения новых функций, исправления ошибок и обновления безопасности.
В то же время Kubernetes, получивший статус индустриального стандарта среди систем оркестрации контейнеров, предлагал активное сообщество, постоянные обновления и интеграцию с облачными провайдерами. Именно эти качества обеспечивали долгосрочную стабильность и гибкость технологической инфраструктуры Uber. Uber является одной из крупнейших компаний в мире с точки зрения масштабов обработки данных и вычислительных ресурсов. Платформа управляет более чем 50 вычислительными кластерами в нескольких регионах, включая как собственные дата-центры, так и облачные сервисы таких провайдеров, как Oracle Cloud и Google Cloud. Каждый кластер насчитывает от 5,000 до 7,500 хостов, что обеспечивает обработку около 250,000 ядер и поддержку порядка 50,000 подов одновременно.
В совокупности, инфраструктура поддерживает около 4,000 различных сервисов с 3 миллионами ядер, что приводит к 100,000 развертываний ежедневно и порядка 1,5 миллиона запусков контейнеров каждый день. В таком масштабе переход на новую систему оркестрации требовал не просто стандартных процедур миграции, а глубокого переосмысления принципов работы и структур управления. На фоне общепринятой индустриальной практики разбиения больших вычислительных ресурсов на множество небольших кластеров, Uber решил двигаться в обратном направлении, концентрируя ресурсы в больших кластерных инсталляциях с 5,000-7,500 узлов каждый. Это позволяло максимизировать использование ресурсов и минимизировать операционные затраты, но в то же время предъявляло жесткие требования к производительности компонентов Kubernetes, таким как API сервер и планировщик. Для обеспечения стабильной работы Kubernetes на таких масштабах команда Uber разработала продвинутый набор инструментов для нагрузочного тестирования.
Это позволило им проверить работу кластеров с 7,500 узлами и 200,000 подов, обеспечивая скорость планирования порядка 150 подов в секунду. Были проведены ключевые оптимизации, включая настройку параметров QPS (запросов в секунду) и параллелизма в контроллерах и планировщике, внедрение приоритизации API-запросов для ограничения тех, которые наиболее затратны с точки зрения ресурсов, а также переход от JSON-кодирования к более эффективному Proto-кодированию. Дополнительно был оптимизирован плагин планировщика Pod Topology Spread для ускорения обработки распределения нагрузки. Интеграция новых Kubernetes-кластеров с внутренней экосистемой Uber требовала глубокой перестройки существующих сервисов и инструментов. Поскольку Mesos и Kubernetes имеют фундаментально разные архитектуры, большинство взаимоотношений — включая CI/CD процессы, систему обнаружения сервисов, безопасность, жизненный цикл хостов и телеметрию — пришлось разрабатывать заново.
Центральным элементом в этом процессе стал собственный слой федерации под названием Up, который выступал абстракцией над кластерными технологиями и позволял разработчикам работать с сервисами без необходимости учитывать детали реализации кластеров. Автоматизация миграционного процесса имела ключевое значение в успешной реализации масштабного перехода. Ввиду колоссальных объемов — порядка 3 миллионов ядер — ручной перенос был невозможен. Система Up позволяла параллельно размещать Kubernetes-кластеры и Mesos-кластеры в одних и тех же зонах, используя функцию выбора кластера и балансируя нагрузку между ними. При этом сервисы автоматически перераспределялись с Mesos на Kubernetes без потребности вовлечения разработчиков, что обеспечивало прозрачность для конечных пользователей и корректное сосуществование рабочих нагрузок на обеих платформах на протяжении миграционного периода.
Работа с обеспечением технологического паритета между Mesos и Kubernetes была критически важной для того, чтобы сервисы сохраняли тот же уровень безопасности развертываний, удобства эксплуатации и скорости доставки новых версий. Для этого Uber разработал собственные кастомные компоненты, которые восполняли пробелы функционала и обеспечивали дополнительные возможности. К примеру, особенности хранения и доступа к артефактам контейнера, таким как дампы памяти или логи, были изначально устроены в Mesos через локальные тома и специализированные UI-эндпоинты. В Kubernetes эти тома удаляются с удалением пода, а стандартный UI не предоставлял необходимого уровня прозрачности. Чтобы восполнить этот пробел, Uber внедрил боковой контейнер (sidecar) и демон для загрузки артефактов, которые при завершении основного контейнера сжимают и отправляют данные в blob-хранилище, сохраняя возможность диагностики и отладки.
Еще одной ключевой особенностью стала поддержка стратегии постепенного масштабирования, позволяющей избежать сбоев и ошибок при резких изменениях рабочей нагрузки. Внутренние сервисы Uber обладали высокой чувствительностью к резким изменениям масштабов, которые могли привести к длительным конвергенциям в распределенных системах или полной потере доступности отдельных частей приложения. В Kubernetes отсутствуют нативные средства управления скоростью масштабирования, поэтому был разработан кастомный контроллер ресурсов с конфигурациями, управляющими масштабированием поэтапно, мелкими партиями. Такой подход обеспечил стабильность работы при изменениях нагрузки и снизил риски для бизнес-критичных приложений. Для ускорения развертываний, особенно крупногабаритных контейнеров, в инфраструктуру Kubernetes были интегрированы CloneSet — расширение, позволяющее обновлять контейнеры «на месте», бесшовно патча обновляя существующие поды вместо их полного пересоздания.
Также была внедрена система предварительной загрузки образов контейнеров на узлы кластера, что существенно уменьшило время простоев при стартах новых версий. Интерфейс Kubernetes, переданный в исходном виде, не справлялся с нагрузками в таких масштабах: интерфейс часто зависал или становился неотзывчивым. Компания провела ряд оптимизаций UI, введя механизмы кеширования и структурных улучшений, что позволило обеспечить высокую отзывчивость и удобство эксплуатации для операторов и разработчиков. В ходе миграции команда столкнулась с некоторыми непредвиденными трудностями и нюансами. К примеру, инструмент мониторинга кластера из коробки не давал полной картины состояния фрагментации ресурсов, а также влияния активных подов друг на друга.
Для этого был разработан собственный инструмент мониторинга развёртываний и процессов в кластере, позволяющий детально анализировать производительность и выявлять узкие места. Также возникли проблемы с процессом согласования (reconciliation) информеров Kubernetes — систем, которые сигнализируют о событиях в кластере и обновляют внутренние представления состояния. По умолчанию они перепроигрываются каждые 8-10 часов, что вызывало пропуски событий во время смены лидера контроллера, что могло задерживать развёртывания на несколько часов. В качестве решения была реализована собственная частотная политика, которая форсировала обновления больших объектов не реже чем каждые 15 минут. Еще одним аспектом стали улучшения в области быстрого и надежного отката неудачных обновлений.
Иногда стандартный таймер прогресса развертывания было сложно интерпретировать, а отсутствие включенных healthchecks вызывало ложные сигналы и замедляло реагирование на проблемы. Для оперативного обнаружения проблем команда ввела эвристики, основанные на количестве перезапусков контейнеров, что позволяло моментально откатывать развёртывания при появлении значительного количества нестабильных подов. По состоянию на середину 2024 года Uber полностью завершил миграцию всех общих stateless сервисов с Mesos на Kubernetes. Процесс занял полтора года, включал несколько стратегических пауз для устранения различных проблем и стабилизации системы. После решения выявленных проблем ход миграции существенно ускорился — в пиковые недели плавно переносилось свыше 300,000 ядер вычислительных ресурсов.