Что такое Service в Kubernetes
Поды в Kubernetes эфемерны: они часто перезапускаются, перемещаются на другие серверы и каждый раз получают совершенно новый динамический IP-адрес:
🟢 Junior Level
30-секундный ответ
Service (Сервис) — это абстрактный объект Kubernetes, предоставляющий единую стабильную точку входа (виртуальный IP-адрес и DNS-имя) и балансировщик нагрузки транспортного уровня (L4) для динамической группы подов.
Поды в Kubernetes эфемерны: они часто перезапускаются, перемещаются на другие серверы и каждый раз получают совершенно новый динамический IP-адрес:
- Если бы микросервисы обращались друг к другу напрямую по IP подов, любая перезагрузка ломала бы всю систему.
- Service решает эту проблему: сервис получает постоянный виртуальный адрес (ClusterIP), который никогда не меняется в течение всей жизни сервиса.
- Клиенты обращаются по стабильному имени (например,
http://order-service:8080), а Kubernetes автоматически перенаправляет и балансирует сетевые пакеты между здоровыми подами.
Наглядная аналогия из жизни
Представьте колл-центр крупного банка:
- Операторы поддержки — это поды (они уходят на перерыв, сменяются, их число растёт в часы пик).
- Service — это единый номер горячей линии (например,
8-800-100-00-00). - Клиенту не нужно знать домашний телефон или имя конкретного дежурного оператора. Клиент набирает один общий номер, а телефонная станция автоматически соединяет его с любым свободным оператором на линии.
Базовый пример манифеста Service
apiVersion: v1
kind: Service
metadata:
name: payment-service
spec:
type: ClusterIP # Доступен только внутри кластера
selector:
app: payment-service # Ищет все поды с меткой app=payment-service
ports:
- name: http
port: 80 # Порт, на котором Service слушает запросы
targetPort: 8080 # Порт внутри контейнера Pod (куда пересылать трафик)
Внутри кластера любое другое приложение обращается к нему по DNS:
curl http://payment-service:80/api/v1/pay
🟡 Middle Level
Как Service находит поды: Селекторы и Endpoints
Связь между Service и подами является слабосвязанной и строится на метках (Labels):
- В секции
spec.selectorсервис указывает критерии поиска (например,app: payment-service). - Kubernetes непрерывно сканирует поды с такими метками.
- IP-адреса всех подов, успешно прошедших проверку
readinessProbe, автоматически заносятся в дочерний системный объект —Endpoints(илиEndpointSlice): ```yaml apiVersion: v1 kind: Endpoints metadata: name: payment-service subsets:- addresses:
- ip: 10.244.1.15
- ip: 10.244.2.34 ports:
- port: 8080 ```
- addresses:
- Если под падает или зависает (readiness probe проваливается), контроллер мгновенно удаляет его IP из списка
Endpoints, и трафик перестаёт на него поступать.
Разрешение доменных имён (CoreDNS)
Каждый созданный Service автоматически регистрируется во встроенном DNS-сервере кластера (CoreDNS). Полное доменное имя (FQDN) имеет вид: \(\mathbf{<service\text{-}name>.<namespace>.svc.cluster.local}\)
- В рамках одного и того же Namespace достаточно обратиться по короткому имени:
http://payment-service. - При вызове из другого Namespace указывается двухкомпонентное имя:
http://payment-service.prod.
4 основных типа Service
| Тип | Где доступен | Для чего используется |
| :— | :— | :— |
| ClusterIP (дефолт)| Только внутри K8s кластера | Внутреннее межсервисное взаимодействие микросервисов. |
| NodePort | На выделенном порту каждого физического сервера (Node) | Локальное тестирование, отладка (диапазон 30000–32767). |
| LoadBalancer | В публичном интернете | Создаёт внешний балансировщик облачного провайдера (AWS NLB, GCP LB). |
| ExternalName | Внутри кластера как CNAME-алиас | Проброс внешних баз данных (например, db.rds.amazonaws.com) в DNS K8s. |
🔴 Senior Level
Как работает ClusterIP под капотом: Магия kube-proxy
Senior-инженер обязан понимать, что ClusterIP — это фиктивный виртуальный IP-адрес (Virtual IP / VIP).
- В кластере НЕТ физического сетевого интерфейса, которому был бы назначен этот IP.
- За обработку пакетов отвечает агент
kube-proxy, работающий на каждом сервере в одном из трёх режимов:
[ Пакет на ClusterIP:80 ]
│
▼
[ Ядро Linux: Netfilter / iptables / IPVS ]
│ (DNAT подмена IP назначения на лету)
▼
[ Реальный IP пода: 10.244.2.34:8080 ]
1. Режим iptables (по умолчанию в большинстве кластеров)
kube-proxyне перехватывает трафик сам. Он лишь транслирует конфигурацию сервисов в цепочки правилiptablesядра Linux в таблицеnat.- Для балансировки используется модуль ядра
statisticс вероятностным механизмом (Random Probability):- Для 3 подов первое правило срабатывает с вероятностью $1/3$, второе — $1/2$, третье забирает остаток.
- Проблема масштабирования: добавление и проверка правил требует линейного обхода $O(N)$. При $10\,000+$ сервисов пересчёт правил начинает утилизировать до 100% CPU одного ядра сервера.
2. Режим IPVS (IP Virtual Server)
- Использует транспортный L4-балансировщик, встроенный непосредственно в ядро Linux.
- Хранит соответствия в хэш-таблицах с константной сложностью поиска $O(1)$.
- Поддерживает сложные алгоритмы распределения:
round-robin,least connections,source hashing. Идеален для больших кластеров.
3. eBPF (Cilium CNI)
- Полностью исключает
kube-proxyи стекiptables/conntrack. - Программы eBPF перехватывают пакеты прямо на сетевом сокете ядра через интерфейс XDP (eXpress Data Path), обеспечивая минимально возможную задержку (Zero-overhead networking).
EndpointSlice API: Защита etcd от Watch Storm
В ранних версиях Kubernetes (до 1.21) все IP-адреса подов сервиса хранились в одном монолитном объекте Endpoints.
- Если у сервиса 5000 подов, то при падении всего одного пода пересылался весь объект размером 2 МБ на все узлы кластера.
- Это вызывало перегрузку API-сервера и
etcd(Watch Storm). - Современное решение —
EndpointSlice: K8s автоматически нарезает список эндпоинтов на компактные слайсы по 100 адресов в каждом. При смене одного пода обновляется только один слайс размером в пару килобайт.
Headless Service (clusterIP: None)
Если в спецификации указать clusterIP: None:
- Kubernetes НЕ выделяет виртуальный VIP и не настраивает правила балансировки в
kube-proxy. - При DNS-запросе к сервису CoreDNS возвращает полный список A-записей с реальными IP-адресами всех здоровых подов.
- Применение: распределённые Stateful-системы (Kafka, Cassandra, MongoDB), где Java-клиент должен сам управлять соединениями к конкретным нодам-лидерам и репликам.
4 Tricky Questions
1. Почему попытка отправить ICMP-запрос ping <ClusterIP> изнутри пода всегда завершается 100% потерей пакетов, хотя HTTP-запросы через curl работают мгновенно?
Ответ:
Виртуальный IP-адрес сервиса (ClusterIP) существует исключительно как правило подмены сетевых адресов (DNAT) в подсистеме ядра Netfilter (iptables или IPVS).
Эти правила настроены строго для протоколов TCP и UDP на определённых портах.
Протокол ICMP (на котором работает утилита ping) не имеет портов и не обрабатывается правилами трансляции сервиса. Поскольку интерфейса с таким IP физически не существует в природе, ядру некому доставить ICMP Echo Request, и пакет молча отбрасывается.
2. Как настроить Service в Kubernetes для подключения к внешней СУБД Oracle/PostgreSQL, расположенной вне кластера, используя внутренний Service Discovery?
Ответ:
Создаётся Service БЕЗ селектора (selector), и вручную объявляется объект Endpoints с тем же именем:
apiVersion: v1
kind: Service
metadata:
name: external-oracle-db
spec:
ports:
- port: 1521
---
apiVersion: v1
kind: Endpoints
metadata:
name: external-oracle-db
subsets:
- addresses:
- ip: 192.168.10.50 # IP физического сервера БД вне K8s
ports:
- port: 1521
Java-приложение внутри кластера использует стабильное имя jdbc:oracle:thin:@external-oracle-db:1521/XEPDB1. Если физический IP базы данных изменится, достаточно изменить манифест Endpoints без перезапуска и переконфигурации микросервисов.
3. В чём отличие port от targetPort в спецификации Service, и что произойдёт, если targetPort опущен?
Ответ:
port: это TCP/UDP порт, который открывает сам Service на своём виртуальном ClusterIP. Именно к этому порту обращаются клиенты внутри кластера.targetPort: это реальный порт в контейнере пода, на котором слушает процесс приложения (например, порт8080встроенного Tomcat в Spring Boot). Ядро Linux транслирует запросы сportнаtargetPort.- Если
targetPortне указан: Kubernetes по умолчанию считает, что значениеtargetPortстрого равно значениюport.
4. Почему использование свойства sessionAffinity: ClientIP в Service может сломать балансировку нагрузки в микросервисной архитектуре?
Ответ:
При включении sessionAffinity: ClientIP kube-proxy направляет все запросы от одного IP-адреса клиента на один и тот же фиксированный под в течение заданного тайм-аута.
В архитектуре с API Gateway (Ingress-контроллер, Spring Cloud Gateway) абсолютно все входящие запросы поступают к сервису с одного и того же IP-адреса шлюза.
В результате sessionAffinity привяжет весь входящий клиентский трафик к одному-единственному поду, перегружая его до падения по CPU/OOM, в то время как остальные поды сервиса будут простаивать с нулевой нагрузкой.
🎯 Шпаргалка для интервью
Главное о Service
- Суть: стабильный сетевой фасад (L4 VIP + DNS) для эфемерных подов.
- Поиск подов: через
spec.selectorпо меткам (Labels). - Связующий объект:
Endpoints/EndpointSlice(хранит IP живых подов). - DNS: доступен по имени
service-name(в том же namespace) или FQDNservice.namespace.svc.cluster.local. - Реализация: агент
kube-proxyчерез правила ядраiptables(по умолчанию) илиIPVS($O(1)$ для хайлоада). - Headless:
clusterIP: None— CoreDNS возвращает IP всех подов напрямую (для StatefulSet/Kafka).
Типы Service
| Тип Service | Область видимости | Назначение |
| :— | :— | :— |
| ClusterIP | Только внутри кластера K8s | Стандарт по умолчанию для межсервисного общения |
| NodePort | Порт 30000–32767 на всех нодах | Доступ без облачного балансировщика |
| LoadBalancer| Интернет (внешний облачный IP)| Продакшен точка входа через облачный LB |
| ExternalName| Внутренний CNAME редирект | Подключение внешних систем по домену |
Красные флаги на собеседовании (Чего говорить нельзя)
- ❌ «Service — это отдельный контейнер с Nginx, который крутится и проксирует трафик» — Service это абстракция, реализованная через правила ядра iptables/IPVS.
- ❌ «ClusterIP можно пропинговать утилитой ping» — виртуальный IP не отвечает на ICMP, только TCP/UDP.
- ❌ «Service балансирует HTTP-трафик по URL и заголовкам» — Service работает на L4 (TCP/IP). Маршрутизацией на L7 (HTTP-пути) занимается Ingress.