Pod, реплики, пробы и Service

О лекции

Под — единица деплоя: контейнеры делят сеть и тома. ReplicaSet держит нужное число подов. Service шлёт трафик только на Ready. Liveness и readiness отвечают на разные вопросы.

Контейнеры и оркестрация docker kubernetes собеседование

Под — один или несколько контейнеров. У них общая сеть: app и sidecar видят друг друга на localhost. Общие тома. IP пода смертный: рестарт или переезд на другую ноду — адрес другой.

Клиенты поэтому ходят не в под, а в Service. В один под не кладут два разных приложения «просто так». Sidecar — помощник к основному процессу, не второй сервис рядом.

Deployment описывает желаемую версию. ReplicaSet держит N копий. kubelet на ноде запускает контейнеры. Горизонталь — это N подов, не «большой контейнер».

Пример. Три реплики api — три пода. Упал один — ReplicaSet поднимет четвёртый, чтобы снова было три. Пользователь ходит на Service, не на IP умершего пода.

Реплики и Service

Service типа ClusterIP даёт стабильный адрес и DNS вроде api.default.svc. Трафик идёт на поды, которые Ready. Не Ready — в балансировке нет.

Новый под не получает запросы, пока не станет Ready. Rolling update поднимает новые и снимает старые. Если readiness слишком мягкий — пользователь ловит 502. Если слишком строгий — живые процессы стоят без трафика.

Три пробы

Startup — «мне ещё можно медленно стартовать». Пока не успех, liveness не убивает. Нужно JVM, прогреву, миграциям.

Liveness — «процесс завис, перезапусти». kubelet убивает контейнер. Проба должна быть дешёвой. Не ходить во внешнюю базу.

Readiness — «трафик пока не клади, но не убивай». Под выходит из Service. Процесс жив. Прогрев кэша, нет соединения, ещё читаем конфиг — типичные причины.

Пример. База лежит. Если liveness ходит в базу, все поды рестартятся разом. Шторм соединений, база не встаёт. Readiness в том же случае просто снимет трафик. Процессы ждут.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: api
spec:
  replicas: 3
  template:
    spec:
      containers:
        - name: api
          image: registry.example/api@sha256:abc123
          ports:
            - containerPort: 8080
          startupProbe:
            httpGet: {path: /healthz, port: 8080}
            failureThreshold: 30
            periodSeconds: 2
          readinessProbe:
            httpGet: {path: /readyz, port: 8080}
            periodSeconds: 5
          livenessProbe:
            httpGet: {path: /healthz, port: 8080}
            periodSeconds: 10

Readiness режет трафик Service. Liveness не зависит от внешней БД.

Что не класть в liveness

Liveness, завязанный на чужую БД, — самоубийство кластера. Все реплики рестартятся из‑за соседа. Readiness на зависимость спорнее, но хотя бы не убивает процесс.

Проба не должна гонять полный user journey. Она не должна быть тяжелее обычного запроса.

  • Startup — не убивать, пока медленно стартуем.
  • Liveness — убить зависшее. Дешёвая локальная проверка.
  • Readiness — снять с балансировки. Процесс жив.
Типичная ошибка

Одна ручка на liveness и readiness, внутри запрос в Postgres. База деградировала — kubelet рестартит весь Deployment. Вторая — нет startupProbe у медленного старта: liveness убивает контейнер на каждой выкатке.

На собеседовании

Liveness убивает мёртвое. Readiness снимает с Service. Startup даёт время родиться. В image — digest, не latest. Liveness не проверяет соседей.