Спор о книге, Job и CronJob
Разговор начинается со спора о том, кому адресована книга: гость первой части считал, что часть возможностей звучит скорее как антипаттерны, и Миша с ним согласен — Kubernetes для него большая сложная машина, которую платформе стоит отдавать наружу дозированно, местами закрывая собственными абстракциями. Ему возражают: поведенческие паттерны полезны всем, кто не управляет сотнями кластеров и не держит десятки тысяч запросов в секунду. Один из ведущих делит паттерны на обязательные — health-чеки и graceful shutdown, без которых гарантии платформы не работают, — и ситуативные, а SRE-гость добавляет, что знать все объекты кластера полезно хотя бы ради быстрого MVP: это экономит время и деньги. Первый паттерн, Job, закрывает короткоживущие процессы: сделать работу, завершиться и не занимать ресурсы; пример из практики — накатка миграций перед деплоем, а голый под годится лишь для разработки, потому что за результатом следишь сам. Ключевые параметры — completions и parallelism: при пяти completions и parallelism 2 поды идут парами, пока не отработают все пять.
На completions 1 и parallelism больше единицы авторы предлагают строить очередь, но координацию придётся держать внутри приложения — так не делал никто из участников, а один из них добавляет, что следующим сопровождающим такая конструкция будет неочевидна; indexed Job показывают на нарезке видеофайла, где каждый под берёт свой кусок. CronJob собран из Job, и главу авторы выводят через путь от cron на одной машине, который становится единой точкой отказа, к сервису с лидер-элекшеном ради задачи, копирующей файлы раз в сутки. Из параметров разбирают concurrency policy и startingDeadlineSeconds: если задача не стартовала вовремя, данные могли протухнуть. Оговорок хватает — точность расписания составляет минуту, а много крон-джобов сами нагружают кластер шедулингом и выделением адресов, так что иногда проще держать один демон с внутренним тикером. Один из участников вспоминает стартап, где поехали отчёты: cron запускался каждые десять минут, база выросла, задача стала работать дольше, а примитивов, которые есть в CronJob, тогда не было.
DaemonSet и синглтон-сервис
Общая мораль про периодические задачи: о них забывают, люди уходят, а похороненная джоба продолжает что-то делать. DaemonSet описывают через явную параллель с юниксовыми демонами: по поду на каждой ноде или на выбранном наборе нод для инфраструктурных задач — сборщиков логов и метрик, агентов трассировок, прокси на каждой машине. По словам участников, раньше у демонов был отдельный шедулер, обеспечивавший приоритет, а с какой-то версии его заменили общим: привязка к ноде осталась, зато подъехали node affinity и единая точка управления ресурсами. Миша подтверждает, что у них это чисто платформенная история и разработчик не может сам запустить что-то на всём кластере. Из боли называют дисбаланс: приложение на одной ноде пишет слишком много логов, агент на ней страдает, а лимиты приходится поднимать сразу всем.
Синглтон-сервис некоторые считают антипаттерном, и Александр честно говорит, что не хотел бы обеспечивать такие гарантии средствами Kubernetes: задача сводится к active/passive, где ReplicaSet не гарантирует единственную копию, а StatefulSet сначала убеждается, что предыдущая остановилась. Возражение из зала: люди постоянно тащат планировщики, умеющие работать только в одном экземпляре, особенно когда из старого монолита нарезают микросервисы, — и многие думают, что делают распределённый лок, а делают ровно этот синглтон. У одного из участников в компании есть белый список: чтобы жить с одной репликой, нужно письменно доказать, почему иначе нельзя. Второй вариант — лидер-элекшн внутри приложения через внешний сервис с локами и лизами: вспоминают ZooKeeper, Consul и Redis, а также контроллер вокруг одного Apache-проекта, который выбирает лидера через ConfigMap. Нижнюю границу живых подов держит pod disruption budget.
Состояние, discovery и self awareness
Со stateless всё привычно: twelve-factor app и Heroku, стадо вместо домашних животных, ReplicaSet как кубик под Deployment и сервис, который подбирает поды по лейблам, а не по деплойменту; хранилище к ReplicaSet прицепить можно, но том будет один на все поды. Со stateful начинаются проблемы: люди захотели заносить в кластер MongoDB и MySQL, авторы выписывают четыре требования — хранилище, сеть, идентичность и порядок, — но признают, что семантики StatefulSet часто мало, и отправляют читать про операторы, которых пользователю чужой платформы всё равно никто развернуть не даст. Участники замечают, что описание проблемы здесь непривычно длинное, обходные пути вроде отдельных папок на реплике выглядят как штурм идей, а книге не хватает пометок «это не целевое решение». Отдельный сюжет — почему базы вернулись в кластер: их стало слишком много, а мониторинг, discovery и сам механизм оператора мало отличаются от обычного деплоймента.
Главу про service discovery комментирует Миша, и отношение у него злое: красиво, но пользоваться в таком виде почти нечем. За дефолтным ClusterIP стоит kube-proxy, который правит iptables, — поэтому ping не работает, а балансировки на практике нет: клиент открывает постоянное соединение в один под, и из десяти подов работают шесть, а то и четыре. Headless-сервис отдаёт все адреса подов и позволяет балансировать на клиенте, но клиенты кешируют DNS и долго стучатся в погашенный под; NodePort в продакшене не советуют из-за портов на нодах и потерянного реального IP клиента; без L7-балансировки за Ingress обойтись не выходит, а nginx, по опыту участников, zero downtime из коробки не даёт. Последний паттерн, self awareness, — про то, как приложение узнаёт имя пода и ноды через Downward API: смонтированные файлы обновляются вслед за лейблами, переменные окружения нет, и это безопаснее похода в API, который приложения умеют укладывать одновременными запросами. Кто-то из участников вспоминает боевик с Джеки Чаном 1998 года про героя, которому нужно выяснить, кто он такой. Через неделю — конфигурация и структурные паттерны.
Что стоит унести с собой
- 01Тип Job задаётся сочетанием completions и parallelism: очередь на completions 1 построить можно, но координация ложится на приложение, а indexed Job раздаёт куски работы по индексу.
- 02CronJob избавляет от собственного планировщика, но точность расписания — минута, а большое число крон-джобов само становится нагрузкой на кластер.
- 03At-most-one даёт не ReplicaSet, а StatefulSet; альтернатива — лидер-элекшн через внешний сервис с локами, и многие принимают за распределённый лок обычный синглтон.
- 04ClusterIP работает на четвёртом уровне и балансировки не даёт: постоянные соединения прибивают клиента к одному поду, поэтому нужен headless-сервис или L7-балансировщик.