Borg: предшественник Kubernetes

Google уже больше десяти лет запускает контейнеризованные рабочие нагрузки в production. Сервисные задания, такие как веб-фронтенды и серверы с состоянием, инфраструктурные системы вроде Bigtable и Spanner, фреймворки пакетной обработки вроде MapReduce и MillWheel — почти всё в Google работает в контейнерах. Сегодня мы впервые рассказали о Borg, давно обсуждавшейся внутренней системе Google для управления кластерами, ориентированной на контейнеры, и опубликовали подробности на академической конференции по компьютерным системам Eurosys. Статью можно найти здесь.

История Kubernetes напрямую связана с Borg. Многие разработчики Google, работающие над Kubernetes, раньше занимались проектом Borg. Мы перенесли в Kubernetes лучшие идеи Borg и постарались устранить некоторые проблемные места, которые пользователи Borg отмечали на протяжении многих лет.

Чтобы дать представление об этой связи, вот четыре возможности Kubernetes, появившиеся благодаря нашему опыту работы с Borg:

  1. Поды (Pods). Под — это единица планирования в Kubernetes. Это ресурсная оболочка, в которой работает один или несколько контейнеров. Контейнеры, входящие в один Под, гарантированно планируются вместе на одну и ту же машину и могут совместно использовать состояние через локальные тома.

В Borg есть похожая абстракция — alloc (сокращение от resource allocation, «выделение ресурсов»). Типичные сценарии использования alloc в Borg включают запуск веб-сервера, который создаёт логи, рядом с лёгким процессом сбора логов, отправляющим эти логи в кластерную файловую систему (похоже на fluentd или logstash); запуск веб-сервера, который отдаёт данные из дискового каталога, заполняемого процессом, читающим данные из кластерной файловой системы и подготавливающим их для веб-сервера (похоже на систему управления контентом); а также запуск пользовательских функций обработки рядом с шардом хранилища. Поды не только поддерживают эти сценарии, но и предоставляют среду, похожую на запуск нескольких процессов в одной VM: пользователи Kubernetes могут размещать в одном Поде несколько расположенных рядом и взаимодействующих процессов, не отказываясь от простоты модели развертывания «одно приложение на контейнер».

  1. Сервисы (services). Хотя основная роль Borg состоит в управлении жизненным циклом задач и машин, приложениям, работающим в Borg, полезны и многие другие кластерные сервисы — например, для нейминга и балансировки нагрузки. Kubernetes позволяет назначать имена и балансировать нагрузку через абстракцию сервисов: сервис имеет имя и сопоставляется с динамическим набором Подов, определённым селектором меток (см. следующий раздел). Любой контейнер в кластере может подключиться к сервису по его имени. Внутри Kubernetes подключения к сервису автоматически балансируются между Подами, соответствующими селектору меток; также система отслеживает, где эти Поды работают, когда со временем они перепланируются из-за сбоев.

  2. Метки (labels). Контейнер в Borg обычно является одной репликой в наборе одинаковых или почти одинаковых контейнеров, соответствующих одному уровню интернет-сервиса (например, фронтенды для Google Maps) или рабочим процессам пакетного задания (например, MapReduce). Такой набор называется Job, а каждая реплика — Task. Хотя Job — очень полезная абстракция, у неё есть ограничения. Например, пользователи часто хотят управлять всем сервисом (состоящим из множества Job'ов) как единой сущностью или единообразно управлять несколькими связанными экземплярами своего сервиса, например для отдельных canary- и stable-релизов. Другой возможный сценарий — это пользователи, которым часто нужно думать о подмножествах задач внутри Job и управлять ими — самый распространённый пример встречается во время плавных обновлений, когда разным подмножествам Job требуются разные конфигурации.

Kubernetes позволяет определять множества более гибко, чем Borg, организуя поды с помощью меток — произвольных пар ключ-значение, которые пользователи добавляют к подам (и фактически к любым объектам в системе). Пользователи могут создавать группы, эквивалентные Borg Jobs, добавляя к подам метку “job:<jobname>”, а также могут использовать дополнительные метки, чтобы помечать имя сервиса, экземпляр сервиса (production, staging, test) и в целом любое подмножество своих подов. Запрос по меткам (так называемый “label selector”) используется, чтобы выбрать набор подов, к которому должна применяться операция. Вместе метки и контроллеры репликации (replication controllers) обеспечивают очень гибкую семантику обновлений, а также выполнение операций, эквивалентных Borg Jobs.

  1. IP-per-Pod. В Borg все задачи на машине используют IP-адрес этого хоста и, следовательно, совместно используют пространство портов хоста. Это позволяет Borg работать с обычной сетью, но создаёт ряд дополнительных сложностей для разработчиков инфраструктуры и приложений: Borg должен планировать порты как ресурс; задачи должны заранее объявлять, сколько портов им нужно, и принимать в аргументах запуска, какие порты использовать; Borglet (агент узла) должен обеспечивать изоляцию портов; а системы именования и RPC должны работать не только с IP-адресами, но и с портами.

Благодаря появлению программно-определяемых оверлейных сетей, таких как flannel, или сетей, встроенных в публичные облака, Kubernetes может назначать каждому поду и сервису собственный IP-адрес. Это устраняет инфраструктурную сложность управления портами и позволяет разработчикам выбирать любые нужные им порты, вместо того чтобы требовать от программ адаптации к портам, выбранным инфраструктурой. Последний момент критически важен для простого запуска готовых open source-приложений в Kubernetes, потому что с подами можно обращаться почти так же, как с виртуальными машинами или физическими хостами: им доступно всё пространство портов и не нужно учитывать ситуацию, когда они могут делить одну физическую машину с другими подами.

По мере роста популярности микросервисных архитектур на основе контейнеров уроки, которые Google извлёк из эксплуатации таких систем внутри компании, вызывают всё больший интерес у внешнего DevOps-сообщества. Раскрывая некоторые внутренние механизмы нашей системы управления кластерами Borg и создавая систему управления кластерами следующего поколения одновременно как open source-проект (Kubernetes) и как общедоступный размещённый сервис (Google Container Engine), мы надеемся, что этот опыт принесёт пользу более широкому сообществу за пределами Google и поможет развивать состояние технологий в области планирования контейнеров и управления кластерами.