Джобы, ячейки и Borgmaster
Ведущие сразу объясняют формат: весь прошлый месяц клуб читал книгу про подходы, используемые в Kubernetes, — иногда хорошие, иногда не очень, — и логичным продолжением показалось разобрать прародителя Kubernetes. White paper 2015 года описывает архитектуру и устройство кластерного менеджера после более чем десяти лет эксплуатации в дата-центрах Google по всему миру. Главная абстракция — джоб: он состоит из множества тасок, таска — из множества обычных процессов, и всё это выполняется на голом железе. Виртуализации в Borg нет, и Вова напоминает почему: в начале двухтысячных, когда Borg начинался, виртуализация на x86 ещё не была стандартом де-факто, а Google уже вложился в железо и не хотел терять эти инвестиции. Участники добавляют, что инфраструктура собиралась из того, что было, и осталась крайне гетерогенной, а статья постоянно возвращается к нежеланию плодить фрагментацию: она усложняет расчёты планировщика, а серверов уже под сотню тысяч.
Кластеры авторы называют ячейками: для анализа взяли десяток-полтора, отфильтровав технические и совсем мелкие — меньше пяти тысяч машин. Медиана, по словам авторов, около десяти тысяч машин, но есть ячейки и в сотни тысяч, а уменьшать их смысла нет: большие удобнее плотно упаковывать, и один SRE-инженер в одиночку управляет десятками таких ячеек. Центральное звено — Borgmaster: он ведёт шедулинг, управляет ресурсами и жизнью джобов, хранит состояние через Paxos и реплицирован пять раз, причём реплики держат состояние в памяти и подхватывают работу, если мастер упал. На машинах живут агенты borglet, аналог kubelet: мастер опрашивает их, и если состояние снять не удалось, задачи переезжают. Одно из дизайн-решений участники сравнивают со static stability из статей Amazon — потерявшая связь машина продолжает выполнять свои задачи и убивает их только после восстановления связи, когда они уже подняты в другом месте. Общее впечатление: Borg скорее убьёт и перезапустит, чем будет чинить, и это норма для системы, где всегда что-то обновляется.
Приоритеты, флейворы и плотность упаковки
Шедулинг участники сравнивают с задачей о рюкзаке: разложить предметы разного размера так, чтобы конфигурация вышла лучшей, — NP-полная задача, ради которой в Borg и появились эвристики. Приоритеты делятся на prod и non-prod, и это не привычное деление окружений: non-prod — такие же боевые нагрузки, только асинхронные, вроде батч-джобов и пакетных выгрузок, которым разрешено доедать так называемые slack-ресурсы. Планировщик учитывает то, чего Kubernetes из коробки не умеет: какое железо нужно нагрузке, чувствительна ли она к задержкам, где на нодах уже лежат кэши нужных пакетов; в Kubernetes ради этого пришлось бы всерьёз размечать все ноды. Отсюда и забавная деталь из статьи: уже зашедуленная задача стартует секунд двадцать-двадцать пять, и около 80% этого времени уходит на копирование пакетов, поэтому артефакты раздаются не из одного центра, а между машинами — участник вспоминает не то торрентоподобный, не то древовидный алгоритм.
История упаковки — это история экспериментов: сначала новые нагрузки размазывали по всем машинам, потом перешли на плотный best fit, но получили простаивающие машины и батчевые задачи, которым уже не досталось остатков у плотно занятых соседей; в итоге выбрали комбинированный вариант и подкрутили параметры. Участники отмечают, что жёстких политик в статье почти нет — почти всё проверяется экспериментом. Фиксированных флейворов у Google тоже нет: авторы посчитали, что если ввести их, как вспоминает участник, от половины CPU и гигабайта памяти с удвоением и округлением запроса вверх, железа понадобится процентов на двадцать больше. Зато работает возврат ресурсов: примерно раз в 300 секунд borglet отправляет мастеру статистику потребления джоба, и мастер может отнять часть выданного, а нагрузку с низким приоритетом рядом с более важной могут просто выселить. В Kubernetes такого нет, поэтому low-latency и батч разводят по разным кластерам; на масштабах Google пара процентов утилизации — это миллионы долларов.
Симуляция, изоляция и уроки Borg
Почти все выводы авторы получают не на живом кластере, а на симуляторе — фейковом мастере, который загружает в себя весь стейт и лог изменений, поднимает заглушки вместо агентов borglet и проигрывает случившееся при других настройках. Утилизацию меряют через compaction: насколько можно ужать ячейку, выкинув часть машин, чтобы размещённые нагрузки всё ещё поместились, — тот же рюкзак, который сужается, пока вещи остаются прежними. Данные берут за один конкретный день и прогоняют многократно; один эксперимент потребовал 200 тысяч ядер, и участники замечают, что даже на масштабах Google это нетривиально, а у многих компаний столько ядер нет. Эвристики нужны именно поэтому: без кэширования score для ноды, классов эквивалентности задач и случайной выборки части нод шедулинг может не сойтись и за трое суток, с ними холодный старт занимает около 200 секунд, а обычное решение, по памяти участника, — примерно полсекунды. Симуляции показали и то, что разносить приложения по отдельным маленьким ячейкам не стоит: железа понадобится на десятки процентов больше.
Изоляцию Borg строит средствами самой Linux-системы, а виртуальные машины в статье появляются лишь как security-песочница для внешних нагрузок вроде App Engine и Compute Engine: гостевая машина запускается как процесс KVM внутри задачи Borg. Ссылок в статье больше восьмидесяти, половина из них в связанных работах: Apache Mesos, Omega, которую делали на смену Borg, но которая не прижилась, и сам Kubernetes, тогда только начинавший путь. Уроки авторы делят на хорошее и плохое, и ведущие шутят, что «злого» в этой тройке не нашлось. Плохое — отсутствие лейблов, один физический IP на машину, где живёт от 9 до 25 задач с вечной дракой за порты, и 230 параметров, поверх которых пришлось строить автоматизацию для тех, кто не хочет в них разбираться. Хорошее — alloc, прообраз подов, и подробная интроспекция. В финале участники отвечают на исходный вопрос: утилизация и гибкость перевешивают удобство Kubernetes, на Borg уже запущено всё, включая BigTable, а обоюдоострый меч такой сложности работает только с очень квалифицированными инженерами.
Что стоит унести с собой
- 01Borg работает с джобами из тасок прямо на голом железе: виртуализации нет, потому что в начале двухтысячных она не была стандартом, а фрагментация усложняет расчёты планировщика.
- 02Плотность важнее удобства: prod и non-prod живут в одной ячейке, borglet раз в 300 секунд сдаёт статистику потребления, и мастер отнимает лишнее — на масштабах Google пара процентов утилизации стоит миллионов.
- 03Почти все цифры статьи получены на симуляторе: compaction на данных одного дня показывает, до скольких машин ужмётся ячейка, а без эвристик шедулинг может не сойтись и за трое суток.
- 04Уроки Borg прямо видны в Kubernetes: лейблы вместо знания, спрятанного в мастере, свой IP у пода вместо драки за порты и API с контроллерами вместо монолитного мастера.