Задача 1. Сколько endpoints у Service

Deployment на три реплики, Service поверх него — сколько адресов окажется в списке endpoints? Разбираем связь селектора, готовности подов и EndpointSlice.
Опубликовано:

Задача

В кластере развёрнут Deployment на 3 реплики и Service поверх него:

YAML
apiVersion: apps/v1
kind: Deployment
metadata:
  name: api
spec:
  replicas: 3
  selector:
    matchLabels:
      app: api
  template:
    metadata:
      labels:
        app: api
        version: v1
    spec:
      containers:
        - name: api
          image: api:1.0
          ports:
            - containerPort: 8080
          readinessProbe:
            httpGet:
              path: /ready
              port: 8080
---
apiVersion: v1
kind: Service
metadata:
  name: api
spec:
  selector:
    app: api
  ports:
    - port: 80
      targetPort: 8080
Нажмите, чтобы развернуть и увидеть больше

Все три пода в статусе Running. Но один из них ещё не прошёл readiness probe — приложение внутри прогревает кэш.

Вопрос: сколько адресов увидит kubectl get endpoints api?

Что кажется очевидным

«Три пода запущены, селектор совпадает — значит, три endpoints». Или, если человек уже обжигался: «два, потому что один не готов».

Второй ответ ближе, но неполон — и упускает главное.

Как это работает на самом деле

Service не знает про Deployment вообще. Между ними нет прямой связи. Работает это так:

  1. Service объявляет селектор по меткам (app: api).
  2. Отдельный контроллер (endpoints controller / endpointslice controller) следит за подами, чьи метки подходят под селектор.
  3. В список попадают не все подходящие поды, а только готовые — то есть те, у которых Ready в статусе True.

Ключевой момент, который многие упускают: RunningReady. Под может быть запущен, но не готов принимать трафик — ровно для этого и существует readiness probe. Пока она не прошла, под остаётся вне списка endpoints и трафик к нему не идёт.

Проверить разницу:

BASH
kubectl get pods -l app=api
# NAME                   READY   STATUS    RESTARTS   AGE
# api-7d4b8c9f5-abc12    1/1     Running   0          5m
# api-7d4b8c9f5-def34    1/1     Running   0          5m
# api-7d4b8c9f5-ghi56    0/1     Running   0          30s   ← Running, но не Ready
Нажмите, чтобы развернуть и увидеть больше

Колонка READY показывает 0/1 — контейнер запущен, но probe не пройдена.

Ещё одна тонкость: selector шире, чем кажется

Селектор Service — это app: api, и он не привязан к конкретному Deployment. Любой под с такой меткой в том же namespace попадёт в endpoints: под из другого Deployment, оставшийся под старой версии, случайно запущенный отладочный под.

Это регулярный источник загадочных багов: «почему часть запросов уходит на старую версию» — потому что где-то живёт под с той же меткой.

Endpoints и EndpointSlice

Исторически список адресов хранился в объекте Endpoints — одном на Service. При сотнях подов это создавало проблему: любое изменение переписывало весь объект целиком и рассылалось всем узлам.

Поэтому появился EndpointSlice — список нарезается на части (по умолчанию до 100 адресов в срезе), и изменение затрагивает только один срез. Сейчас это основной механизм, а Endpoints остаётся ради совместимости.

BASH
kubectl get endpointslices -l kubernetes.io/service-name=api
Нажмите, чтобы развернуть и увидеть больше

Ответ

Два. В endpoints попадут только те поды, которые прошли readiness probe. Третий появится там автоматически, как только станет Ready.

Но точный ответ звучит осторожнее: столько, сколько в namespace есть готовых подов с меткой app: api — и это число не обязано совпадать с числом реплик Deployment.

Что с этим делать


Дальше: Задача 2. Под удалён, трафик идёт.

Начать поиск

Введите ключевые слова для поиска статей

↑↓
ESC
⌘K Горячая клавиша