К основному содержимому
к выпуску
Конспект выпуска2023Fellow

Kubernetes Patterns — введение и базовые паттерны

Клуб начинает читать Kubernetes Patterns — книгу, которую выбрали слушатели, — и разбирает интро и первые шесть глав. Александр Поломодов, Илья Зонов и коллеги зовут в гости Стаса, который руководит платформенной командой и строит большие кластеры под веб-сервисы: примитивы, предсказуемые требования, декларативный деплой, пробы, lifecycle и размещение подов.

Code of Architecture · книжный клуб7 минут

Конспект сокращён относительно полного выпуска; примеры и оценки передают опыт и позиции участников.

Основная линия материала
01

Книга для разработчиков и примитивы

Разбирают второе издание, вышедшее, по словам ведущих, в этом же году; за регистрацию его раздаёт Red Hat. Всю книгу планируют пройти за четыре выпуска, сегодня — интро и первые шесть глав. Ведущим понравилось, что это, кажется, первая книга клуба, где написано, что она в первую очередь для разработчиков, которые будут писать под Kubernetes и с этим жить, — архитекторов авторы, впрочем, тоже не исключают. Стас добавляет, что первые части полезны и тем, кто хочет понять, как устроены сами компоненты Kubernetes, и предупреждает: некоторые паттерны опасно отдавать в руки пользователям большой мультитенантной системы — книга и сама пишет, что этим можно выстрелить себе в ногу. Из книги берут главную оговорку: платформа не решит всех проблем — мусор, положенный в контейнер, при масштабировании станет распределённым мусором. На картинке с иерархией паттернов снизу лежит чистый код: клуб уже разбирал книгу про него и Learning Domain-Driven Design Влада Хононова.

Дальше — быстрый проход по примитивам. Образы и контейнеры авторы сравнивают с классами и объектами, под — с композицией контейнеров, а FROM в Dockerfile участники с натяжкой называют наследованием реализации и предупреждают: метафоры полезны, пока не начинаешь гнаться за полным совпадением. Композиция на уровне пода нужна, чтобы не собирать комбайн из одного бинаря: рядом с приложением с бизнес-логикой живёт тулинг, который отдаёт метрики. Под — единица управления жизненным циклом группы контейнеров на одном хосте с общими ресурсами, а сервисы отвечают за discovery и трафик, потому что поды всё время падают и стартуют в новых местах. Стас уточняет про метаданные: лейблы — идентификаторы для поиска, по ним сервисы находят поды, которым лить трафик, а аннотации — метаданные, которые вытаскивает автоматизация на кластере; параллель с обычным селектом проводит уже другой участник. Список рекомендованных лейблов появился на сайте не сразу. Неймспейсы дают группировку, квоты и, если так спроектировать платформу, границу безопасности; для capacity planning, предупреждает Стас, их гранулярность не так удобна, как хотелось бы, а кластер на потребителя дороже.

02

Предсказуемые требования: ресурсы и приоритеты

Foundational patterns авторы формулируют как минимум, который должно выполнять приложение; местами это пересекается с манифестом двенадцати факторов, придуманным в Heroku. Структура глав нравится — проблема, решение, обсуждение, — но один из ведущих замечает, что решение иногда просто описывает механизм Kubernetes, частично закрывающий проблему. Отдельная претензия к жанру: книга уверяет, что она не инструкция, и отсылает к другим книгам, а примеров и почти туториалов в ней много. Участники вспоминают банду четырёх, где после проблемы и решения код придумывали сами, а примеры были на давно умершем Smalltalk — и книга всё равно переиздаётся. YAML здесь читается легко, особенно если когда-то сдавал сертификационный экзамен. Первый паттерн — Predictable Demands: приложение должно явно зафиксировать требования и зависимости, чтобы планировщик нашёл ему место, а команда могла заниматься capacity planning. На него ушло сорок минут выпуска, а паттерн ещё не закончился.

Зависимости бывают рантаймовые — файловая система и порты; конкретный порт на ноде нужен редко, и Стас вспоминает приложения с очень высокой нагрузкой и базы под управлением операторов, ради которых иногда приходится выставлять конкретный под. Главное в главе — ресурсы. Память несжимаема, поэтому книга советует ставить реквест и лимит одинаковыми: вернуть память можно только убийством пода, тогда как процессор восстановится к следующему циклу. Стас объясняет, почему это принципиально: нехватка CPU оборачивается подтормаживанием для пользователя, а превышение памяти на ноде роняет сначала системные компоненты Kubernetes, потом операционную систему, и хост может просто зависнуть. Лимиты заодно лечат рестартом приложения с утечками памяти. От комбинации реквестов и лимитов зависит QoS-класс: их три, гарантированные поды не двигаются, best effort вытесняются первыми. Приоритеты подов — про очередь размещения, а не про ресурсы; пользователям их обычно не дают, потому что соседу слишком легко насолить. Сам Стас на приоритетах разводил обычные и GPU-нагрузки: на входе механизм смотрит, какой ресурс запрошен, и редкая нагрузка получает место на нужной ноде.

03

Деплой, пробы и размещение подов

Декларативный деплой закрывает ручные шаги релиза. Из коробки есть rolling update, когда новые поды стартуют, а старые ещё принимают трафик, и recreate, когда сначала гасят всё, чтобы не было коллизий версий и схем. Recreate один из ведущих считает странным способом: обычно коллизии решают тем, что старая и новая версии умеют жить вместе, а миграции катятся в обе стороны. Стас возражает, что для приложения, которое разбирает очередь, а не отвечает на запросы, паттерн вполне жизнеспособен. Отсюда разговор о самой декларативности: вместо императивных команд есть описание желаемого состояния и контроллер, который к нему сводит. Blue-green требует вдвое больше ресурсов и нативной поддержки не имеет. Канарейку Стас называет золотым стандартом: в их платформе её ещё нет, но будет, причём тулинг не приносит главного — выбора метрик, отсечек и времени проверки. Тут же звучит замечание, что канарейка пересекается с метриками их A/B-платформы.

Пробы: liveness приводит к рестарту, readiness убирает под из сервиса, а startup вынесли отдельно ради долго стартующих приложений — его, вспоминают участники, пропихивали любители Java. Проверять можно HTTP-вызовом или командой, а у Spring актуатор отдаёт пробы из коробки; смысл в том, чтобы показать не пинг с двумястами, а работоспособность приложения. Стас добавляет дизайнерское соображение: приложение не должно деградировать вслед за зависимостями — пусть покажет пустой список, но не развалится, — и во внешние зависимости из проб лучше не ходить, чтобы не наесться таймаутов. К managed lifecycle выпуск подходит уже на минус двух минутах; этот паттерн — про сигналы: SIGTERM, SIGKILL по таймауту, preStop и postStart, у которого порядок относительно старта приложения не гарантирован; отсюда картинка 2016 года про восходящий и нисходящий каналы между контейнером и платформой. В automated placement привязку к конкретной ноде авторы называют крайним случаем и советуют начинать с nodeSelector, node affinity и taints, а анти-аффинити подов уменьшает область поражения при потере ноды.

Выводы

Что стоит унести с собой

  1. 01Kubernetes не панацея: мусор в контейнере при масштабировании превращается в распределённый мусор, а базовые паттерны — это то, что должен сделать сам разработчик: зафиксировать ресурсы и объявить зависимости.
  2. 02Лейблы — идентификаторы для поиска, аннотации — метаданные для автоматизации; на этом различии держатся сервисы, которые выбирают поды по лейблам.
  3. 03Память несжимаема, поэтому реквест и лимит лучше ставить равными: вернуть её можно только убийством пода, а процессор восстановится к следующему циклу.
  4. 04Приоритеты и ручки шедулера опасно раздавать жителям мультитенантного кластера: соседу легко насолить, поэтому в платформе они остаются у администраторов.

Источники