сеньорчикОткрыть в Telegram
← вся теориятеория к собесу · Kubernetes

Поды и контроллеры Kubernetes

Виды нагрузок

Поднял в кластере рядом два вида нагрузки. Под тут - это запущенный экземпляр приложения, а реплика - один из нескольких одинаковых таких экземпляров. У обычного развёртывания поды получили имена stateless-799d7679bb-czgb6 и stateless-799d7679bb-s2qwl - случайные хвосты. У набора с состоянием имена оказались stateful-0 и stateful-1. Удалил stateful-0 - вернулся под с ТЕМ ЖЕ именем. Удалил под развёртывания - пришёл новый со случайным именем.

Стержень: вид нагрузки выбирается по тому, взаимозаменяемы ли экземпляры и нужен ли им личный диск и постоянное имя.

// Формулировки: «чем StatefulSet отличается от Deployment?», «когда нужен DaemonSet?», «как запускать разовые задачи?»

Взаимозаменяемые и именованные

Развёртывание рассчитано на одинаковые взаимозаменяемые экземпляры. Имена случайны, порядок запуска не гарантирован, поды поднимаются все разом. Это подходит приложениям без собственного состояния: любой экземпляр обслужит любой запрос.

Набор с состоянием даёт три вещи, которых нет у развёртывания. Стабильные имена по номерам, за счёт чего у каждого экземпляра есть постоянный сетевой адрес по имени. Личный том - хранилище данных снаружи пода, - который переживает пересоздание и подключается обратно к экземпляру с тем же номером. И порядок: поды поднимаются по очереди с нулевого, а гасятся в обратном порядке.

// Нужно это ровно там, где экземпляры НЕ взаимозаменяемы: базы с репликацией, очереди, кластеры с выбором главного. Для обычного веб-сервиса набор с состоянием - лишняя сложность: он медленнее обновляется и болезненнее переживает падение узла.

развёртывание
одинаковые взаимозаменяемые поды со случайными именами
набор с состоянием
стабильные имена по номерам, личные тома, строгий порядок запуска

По одному на узел и разовые задачи

Набор по узлам ставит ровно один под на каждый узел кластера и сам добавляет его на новые узлы. Это форма для инфраструктурных вещей: сборщик логов, агент мониторинга, сетевой компонент. Число реплик тут не задают - оно равно числу узлов по определению.

Разовая задача запускает под и следит, чтобы он ДОШЁЛ ДО КОНЦА успешно. Отличие от развёртывания принципиальное: там под, завершившийся с нулевым кодом, будет перезапущен, потому что желаемое состояние - «работает». В разовой задаче успешное завершение и есть цель. Ей задают число попыток при неудаче и предел времени.

// Задача по расписанию - та же разовая, но запускаемая по календарю. Две настройки, которые спасают от боли: политика на случай, когда предыдущий запуск ещё идёт (пропустить, запустить рядом или заменить), и предел времени выполнения. Без них повторяется классика планировщика: задача накладывается сама на себя, пока не кончатся ресурсы.

набор по узлам
ровно один под на каждом узле; для агентов и сборщиков
разовая задача
под должен успешно завершиться; завершение - это цель, а не сбой

Обновление и откат

При обновлении развёртывание не гасит всё разом. Оно создаёт новый набор реплик и переводит поды по чуть-чуть. Две настройки задают темп: сколько подов можно поднять СВЕРХ нормы и сколько можно держать недоступными. По умолчанию у меня стояло по 25% на обе.

Замерил, как это выглядит на четырёх репликах. Через 2 секунды после команды: готово 3 из 4, актуальной версии 2, доступно 3. Через 8 секунд: актуальных уже 4, доступно 3. Через 10 секунд: 4 из 4 готовы, все актуальные. Доступность ни разу не опустилась ниже трёх из четырёх - именно это и обещают настройки.

// Откат работает потому, что старый набор реплик не удаляется, а остаётся с нулём подов. Команда отката просто наполняет его обратно. История версий хранится, у меня после одного обновления в ней было две записи. ⚠Но обещание «без простоя» держится только при работающей пробе готовности - это регулярный запрос, по ответу на который кластер решает, можно ли пускать на под трафик. Без неё кластер считает под готовым сразу после старта процесса и переводит на него трафик раньше, чем приложение способно отвечать.

максимум сверх нормы
сколько подов разрешено поднять поверх заданного числа во время обновления
максимум недоступных
сколько подов разрешено держать недоступными во время обновления

Как отвечать: «Чем StatefulSet отличается от Deployment и когда он нужен?»

Тремя вещами, и все три я проверял на стенде. Стабильные имена: у развёртывания поды получили случайные хвосты, а у набора с состоянием - номера, ноль и один. Устойчивость этих имён: я удалил нулевой под, и вернулся под ровно с тем же именем, тогда как у развёртывания взамен удалённого пришёл под с новым именем. Плюс личный том, который переживает пересоздание и подключается обратно к экземпляру с тем же номером, и строгий порядок запуска и остановки. Нужно это там, где экземпляры не взаимозаменяемы: базы с репликацией, очереди, кластеры с выбором главного узла. Для обычного веб-сервиса это лишняя сложность - обновляется медленнее и хуже переживает падение узла, а взамен даёт свойства, которые сервису без состояния не нужны.

Ответ называет ровно три отличия с проверенными примерами и заканчивается тем, когда этого делать НЕ надо. Второе не менее важно: набор с состоянием часто ставят по привычке.

На чём валятся

  • Берут набор с состоянием для сервиса без состояния и получают медленное обновление.
  • Ждут от развёртывания стабильных имён подов.
  • Запускают разовые задачи развёртыванием: завершившийся под будет перезапущен.
  • Не ставят задаче по расписанию предел времени и политику наложения запусков.
  • Обещают обновление без простоя, не настроив пробу готовности.

Проверьте себя

Пять вопросов из банка по этой подтеме. Всего их 7, остальные разбираются в тренажёре.

  1. #dvo_k8s_workloads1 / 5
    Реплик 4, maxSurge: 1, maxUnavailable: 0. Что это даёт при обновлении?
    A)Обновление идёт разом: все поды пересоздаются параллельно
    B)В момент выкатки живёт максимум 5 подов и не меньше 4 готовых
    C)Один под простаивает, зато выкатка идёт вдвое быстрее
    D)Старые поды остаются, пока не пройдёт ручное подтверждение
    показать ответ и разбор
    +B)В момент выкатки живёт максимум 5 подов и не меньше 4 готовых

    // разбор: maxSurge — сколько подов сверх желаемого числа разрешено поднять, maxUnavailable — сколько готовых можно потерять. Нули по недоступности означают: сначала поднимаем новый под и ждём readiness, только потом гасим старый. Ёмкость под нагрузкой не проседает, но нужна свободная квота на ноде и выкатка идёт медленнее. Обратная настройка (surge 0, unavailable 1) экономит ресурсы ценой просадки.

  2. #dvo_k8s_workloads2 / 5
    Под db-1 из StatefulSet удалили вручную. Что будет дальше?
    A)Вернётся под с тем же именем и тем же PVC
    B)Контроллер создаст под db-3, старый том останется висеть
    C)Реплика не восстановится, пока не пересоздать весь StatefulSet
    D)Под вернётся, но с новым пустым томом из шаблона
    показать ответ и разбор
    +A)Вернётся под с тем же именем и тем же PVC

    // разбор: Идентичность в StatefulSet держится на порядковом индексе: контроллер поднимет ровно db-1 и подключит его прежний PersistentVolumeClaim — данные на месте. PVC живут отдельно от подов и не удаляются вместе с ними (а по умолчанию остаются и после удаления самого StatefulSet). Отсюда типовая уборка после экспериментов: удалить набор и отдельно почистить тома.

  3. #dvo_k8s_workloads3 / 5
    Разработчик создал голый Pod (не Deployment). Нода перезагрузилась — пода больше нет. Почему Deployment вёл бы себя иначе?
    A)Голый Pod без Deployment запускать в кластере вообще запрещено
    B)Deployment хранит под на диске, поэтому тот переживает ребут
    C)Pod без Deployment не получает IP и потому и исчезает
    D)Голый Pod никто не пересоздаёт; Deployment держит число реплик
    показать ответ и разбор
    +D)Голый Pod никто не пересоздаёт; Deployment держит число реплик

    // разбор: Голый Pod не управляется контроллером: если его нода умирает или его удаляют, пересоздавать некому. Deployment (через свой ReplicaSet) постоянно сводит фактическое число реплик к желаемому — умер под/нода, планируется замена на другой ноде. Это и есть самолечение, нужное сервисам. Голые поды — для разовых/отладочных задач.

  4. #dvo_k8s_workloads4 / 5
    Нужно, чтобы агент сбора логов работал ровно по одному экземпляру на каждой ноде, включая новые. Какой контроллер?
    A)Deployment с числом реплик, равным текущему числу нод
    B)DaemonSet: по одному поду на ноду, на новых — автоматически
    C)StatefulSet тоже ставит по поду на каждую ноду
    D)CronJob, который периодически раскладывает поды по нодам
    показать ответ и разбор
    +B)DaemonSet: по одному поду на ноду, на новых — автоматически

    // разбор: DaemonSet запускает ровно один под на каждой (матчащей) ноде и автоматически добавляет его на любую новую ноду — то, что нужно для узловых агентов (сбор логов/метрик, CNI, storage). Deployment с replicas=N не гарантирует один-на-ноду (планировщик может сложить их вместе) и не реагирует на смену числа нод; StatefulSet — про стабильную идентичность и хранилище, а не про раскладку по нодам.

  5. #dvo_k8s_workloads5 / 5
    Ночной CronJob иногда идёт дольше часа, и запуски начинают наслаиваться, плодя параллельные джобы. Чем это управлять?
    A)concurrencyPolicy: Forbid/Replace — не поверх идущего
    B)Уменьшить schedule, чтобы запуски шли реже одного в час
    C)Выставить backoffLimit: 0 — тогда параллель и пропадёт
    D)Поднять activeDeadlineSeconds, чтобы джоба падала быстрее
    показать ответ и разбор
    +A)concurrencyPolicy: Forbid/Replace — не поверх идущего

    // разбор: Наслоение запусков CronJob регулирует concurrencyPolicy: Allow (по умолчанию) разрешает параллель; Forbid пропускает новый запуск, если предыдущий ещё идёт; Replace убивает текущий и стартует свежий. Для долгих джоб, которым нельзя пересекаться, — Forbid или Replace. startingDeadlineSeconds отвечает за пропущенные запуски, backoffLimit/activeDeadlineSeconds — за ретраи и таймаут, а не за конкуренцию.

дальше

Теорию прочитали. Навык ставится повторением

В Сеньорчике эта подтема идёт в ежедневных сессиях: движок возвращает её, пока ответы не станут уверенными, и ведёт прогресс отдельно по каждой подтеме. Теория внутри тоже бесплатна, лимит только на количество вопросов в день.