Стратегии обновления и планирование: rollout и rollback, graceful shutdown, nodeSelector, affinity, taints

Рейтинг: 68.5% · 14 голосов
Kubernetes для разработчиков: поды, деплойменты, сервисы, ingress, конфиги и отладка. Уроки по главам с обсуждением.
Ответить
Аватара пользователя
anton_k8s
Сообщения: 26
Зарегистрирован: 12 май 2026, 03:23

Стратегии обновления и планирование: rollout и rollback, graceful shutdown, nodeSelector, affinity, taints

Сообщение anton_k8s »

АкадемияKubernetes на практикеГлава 16 из 19
Оглавление курса (19)
  1. Зачем нужен Kubernetes и из чего состоит кластер
  2. Поднимаем локальный кластер: minikube и kind
  3. Поды: базовая единица запуска
  4. Deployment и ReplicaSet: управляем репликами
  5. Service: сетевой доступ к подам
  6. ConfigMap и Secret: выносим конфигурацию
  7. Ingress: пускаем трафик снаружи
  8. Хранилище: Volumes и PersistentVolumeClaim
  9. Namespaces, requests и limits
  10. Health checks: liveness и readiness пробы
  11. Отладка: почему под не стартует
  12. Helm: пакетный менеджер для Kubernetes
  13. Базовая безопасность: RBAC и доступы
  14. Job и CronJob: разовые и периодические задачи
  15. StatefulSet и DaemonSet: stateful-нагрузки и системные агенты
  16. Стратегии обновления и планирование: rollout и rollback, graceful shutdown, nodeSelector, affinity, taints (вы здесь)
  17. Автомасштабирование: HPA по метрикам, обзор VPA и Cluster Autoscaler
  18. Наблюдаемость: логи, метрики, events, обзор Prometheus и Grafana
  19. Безопасность глубже: securityContext, Pod Security Standards, NetworkPolicy, шифрование секретов
Деплой написан, выкатывается, работает. Дальше начинается взрослая жизнь: новые версии надо выкатывать без даунтайма, неудачные откатывать за минуту, поды гасить так, чтобы не рвать живые запросы, а еще объяснять планировщику, на какие ноды можно, а на какие нельзя. Все четыре темы связаны сильнее, чем кажется.

Rollout и rollback:

Deployment по умолчанию обновляется стратегией RollingUpdate: старые поды заменяются новыми порциями. Управляют процессом два параметра, по умолчанию оба 25%.

Код: Выделить всё

apiVersion: apps/v1
kind: Deployment
metadata:
  name: api
spec:
  replicas: 4
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1          # сколько подов можно создать сверх replicas
      maxUnavailable: 0    # сколько подов может быть недоступно
Связка maxSurge: 1 и maxUnavailable: 0 дает обновление без потери емкости: сначала поднимается новый под, проходит readiness, только потом гасится старый. Вторая стратегия, Recreate, сначала убивает все старые поды и лишь затем создает новые. Нужна редко, например когда две версии не могут одновременно держать один PVC в режиме ReadWriteOnce.

Код: Выделить всё

kubectl set image deploy/api api=registry.cyberlake.ru/api:1.8.3
kubectl rollout status deploy/api --timeout=120s
kubectl rollout history deploy/api
kubectl rollout undo deploy/api                  # на предыдущую ревизию
kubectl rollout undo deploy/api --to-revision=12
Флаг --record давно признан устаревшим, на него не полагаемся: причину изменения пишут руками в аннотацию kubernetes.io/change-cause, ее и показывает history.

Graceful shutdown:

При удалении пода kubelet шлет процессу SIGTERM, ждет terminationGracePeriodSeconds (по умолчанию 30 секунд) и добивает SIGKILL. Параллельно под выводится из endpoints сервиса. Слово "параллельно" ключевое: трафик может прилетать еще несколько секунд после SIGTERM, пока kube-proxy и внешние балансировщики обновят правила. Отсюда классический паттерн: короткая пауза в preStop плюс приложение, которое по SIGTERM перестает принимать новые запросы, но дорабатывает текущие.

Код: Выделить всё

spec:
  terminationGracePeriodSeconds: 60
  containers:
  - name: api
    image: registry.cyberlake.ru/api:1.8.3
    lifecycle:
      preStop:
        sleep:              # нативный sleep, стабилен с Kubernetes 1.32,
          seconds: 5        # бинарь sleep в образе не нужен
Если процесс запущен через shell-форму ENTRYPOINT в Dockerfile, SIGTERM получит sh, а не приложение, и контейнер умрет по SIGKILL спустя весь grace period. Лечится exec-формой ENTRYPOINT.

nodeSelector и affinity:

nodeSelector решает простую задачу: вешаете лейбл на ноду через kubectl label, в спеке пода указываете ту же пару ключ-значение, и под планируется только на подходящие ноды. Когда нужны операторы, мягкие предпочтения или привязка к другим подам, берут affinity.

Код: Выделить всё

affinity:
  nodeAffinity:
    requiredDuringSchedulingIgnoredDuringExecution:
      nodeSelectorTerms:
      - matchExpressions:
        - key: topology.kubernetes.io/zone
          operator: In
          values: ["ru-central1-a", "ru-central1-b"]
  podAntiAffinity:
    preferredDuringSchedulingIgnoredDuringExecution:
    - weight: 100
      podAffinityTerm:
        labelSelector:
          matchLabels:
            app: api
        topologyKey: kubernetes.io/hostname
Хвост IgnoredDuringExecution в названии честный: правило проверяется только при планировании. Сменили лейблы на ноде, уже запущенные поды никто переселять не будет. Для равномерного размазывания реплик по зонам сейчас чаще используют topologySpreadConstraints, но anti-affinity по hostname для пары реплик по-прежнему рабочий вариант.

Taints и tolerations:

Лейблы притягивают поды, taint отталкивает: нода с taint не принимает поды без соответствующего toleration.

Код: Выделить всё

kubectl taint nodes gpu-1 dedicated=gpu:NoSchedule

# в спеке пода, которому туда можно:
tolerations:
- key: dedicated
  operator: Equal
  value: gpu
  effect: NoSchedule
Эффекты: NoSchedule запрещает планировать новые поды, PreferNoSchedule просит избегать, NoExecute еще и выселяет уже работающие поды без toleration. Именно taint node-role.kubernetes.io/control-plane:NoSchedule защищает control-plane ноды от рабочей нагрузки. Запомните: toleration это разрешение, а не приказ. Чтобы поды ехали на выделенные ноды и только туда, taint комбинируют с nodeSelector или nodeAffinity.

Типичные грабли:

rollout undo откатывает только шаблон пода. ConfigMap и Secret остаются новыми, и старый код с новым конфигом порой хуже, чем просто новая версия. Лечится версионированными именами (app-config-v42) или откатом релиза целиком через helm rollback.

maxUnavailable: 1 при replicas: 1 означает даунтайм на каждом деплое. Для маленьких приложений ставьте maxUnavailable: 0.

Если новый под не проходит readiness, rollout status будет ждать до spec.progressDeadlineSeconds (по умолчанию 600 секунд) и только потом упадет. В CI всегда задавайте --timeout.

Опечатка в nodeSelector или лейбл, которого нет ни на одной ноде, дает вечный Pending. kubectl describe pod покажет событие FailedScheduling с раскладкой, сколько нод и почему не подошло.

NoExecute на живой ноде мгновенно выселяет все поды без toleration. Кластер сам пользуется этим механизмом: на недоступную ноду вешается node.kubernetes.io/unreachable:NoExecute, а поды имеют дефолтный toleration на 300 секунд, поэтому переезд не мгновенный. Руками такой эффект на проде ставят осознанно, при выводе ноды, а не для эксперимента.

Итог:

RollingUpdate с maxUnavailable: 0, readiness проба и аккуратная обработка SIGTERM вместе дают деплой без потерянных запросов. rollout undo спасает быстро, но помнит только про шаблон пода, конфиги ваша забота. nodeSelector, affinity и taints решают одну задачу с трех сторон: просто притянуть, гибко притянуть, оттолкнуть лишнее. В следующей главе займемся автомасштабированием: HPA по метрикам и что делать, когда нод перестает хватать.
👍5 ❤️4 🔥1 😄 🤔2
✔ Лучший ответ сформирован автоматически — legacyghost
anton_k8s писал(а):трафик может прилетать еще несколько секунд после SIGTERM, пока kube-proxy и внешние балансировщики обновят правила вот за это отдельное спасибо. на прошлой работе полгода ловили 502 на каждом деплое, грешили на nginx, на сеть, на что угодно. в итоге воткнули sleep 5 в preStop и все, тишина. а оказывается это документированное поведение, просто никто не читал
Перейти к ответу →
Аватара пользователя
legacyghost
Сообщения: 1
Зарегистрирован: 15 май 2026, 03:39

Re: Стратегии обновления и планирование: rollout и rollback, graceful shutdown, nodeSelector, affinity, taints

Сообщение legacyghost »

✔ Лучший ответ — сформирован автоматически
anton_k8s писал(а):трафик может прилетать еще несколько секунд после SIGTERM, пока kube-proxy и внешние балансировщики обновят правила
вот за это отдельное спасибо. на прошлой работе полгода ловили 502 на каждом деплое, грешили на nginx, на сеть, на что угодно. в итоге воткнули sleep 5 в preStop и все, тишина. а оказывается это документированное поведение, просто никто не читал
👍2 ❤️2 🔥 😄 🤔
Аватара пользователя
joe187
Сообщения: 2
Зарегистрирован: 04 июн 2026, 01:48

Re: Стратегии обновления и планирование: rollout и rollback, graceful shutdown, nodeSelector, affinity, taints

Сообщение joe187 »

вопрос по anti-affinity: у меня kind на ноутбуке, нода одна. preferred правило в таком случае просто молча игнорится или под зависнет в Pending? по логике preferred должен игнориться, но хочу убедиться, что я правильно понял разницу с required
👍 ❤️ 🔥2 😄 🤔1
Аватара пользователя
andrei11
Сообщения: 2
Зарегистрирован: 15 май 2026, 21:14

Re: Стратегии обновления и планирование: rollout и rollback, graceful shutdown, nodeSelector, affinity, taints

Сообщение andrei11 »

про NoExecute жиза. коллега в пятницу вечером решил 'пометить' прод ноду перед обслуживанием и влепил NoExecute вместо NoSchedule. 30 подов переехали разом, мониторинг покраснел, дежурный поседел. с тех пор у нас в раннере проверка на эффект taint в любом скрипте
👍 ❤️1 🔥 😄 🤔
Аватара пользователя
postgres_fan
Сообщения: 1
Зарегистрирован: 11 май 2026, 18:57

Re: Стратегии обновления и планирование: rollout и rollback, graceful shutdown, nodeSelector, affinity, taints

Сообщение postgres_fan »

не знал что rollout undo не трогает конфигмапы, это прям коварно. получается откатил под, а он читает уже новый конфиг и падает еще веселее. версионирование имен выглядит костылем, но видимо иначе никак, либо helm. кто как живет без хелма, отпишитесь
👍 ❤️ 🔥 😄 🤔
Ответить
← Предыдущая глава
StatefulSet и DaemonSet: stateful-нагрузки и системные агенты
Следующая глава →
Автомасштабирование: HPA по метрикам, обзор VPA и Cluster Autoscaler

Все главы курса «Kubernetes на практике»

Поделиться темой: ✈ Telegram VK

Вернуться в «Kubernetes на практике»

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и 1 гость