У каждого Pod есть IP-адрес. Но поды смертны: они пересоздаются, переезжают на другие узлы, получают новые IP. Как клиентам к ним обращаться? Ответ — Service.
Зачем нужен Service
Представь: у тебя 3 реплики бэкенда. Каждый Pod имеет свой IP. Frontend не знает эти IP заранее, и они меняются при каждом перезапуске.
Service — это стабильная абстракция над набором подов. Он имеет постоянный IP (ClusterIP) и DNS-имя. Запросы к Service автоматически балансируются между живыми подами.
Frontend → Service (стабильный IP: 10.96.45.12)
├── Pod 1 (10.244.1.5)
├── Pod 2 (10.244.2.8)
└── Pod 3 (10.244.3.2)
Service находит поды по selector (меткам). Поды с нужными метками — автоматически включаются в балансировку.
Типы Service
ClusterIP (по умолчанию)
Доступен только внутри кластера. Идеален для внутренней коммуникации между сервисами.
# service-clusterip.yaml
apiVersion: v1
kind: Service
metadata:
name: backend-service
spec:
type: ClusterIP
selector:
app: backend
ports:
- port: 80 # порт самого Service
targetPort: 8000 # порт контейнера
kubectl apply -f service-clusterip.yaml
kubectl get services
# NAME TYPE CLUSTER-IP PORT(S) AGE
# backend-service ClusterIP 10.96.45.12 80/TCP 1m
Из любого пода кластера: curl http://backend-service или curl http://10.96.45.12.
NodePort
Открывает порт на каждом узле кластера. Доступен снаружи через <NodeIP>:<NodePort>.
apiVersion: v1
kind: Service
metadata:
name: frontend-service
spec:
type: NodePort
selector:
app: frontend
ports:
- port: 80
targetPort: 3000
nodePort: 30080 # диапазон 30000–32767 (необязательно, можно не указывать)
# Доступ снаружи (например, в minikube)
minikube service frontend-service --url
# http://192.168.49.2:30080
Используй NodePort для быстрой отладки и dev-стендов. В production не рекомендуется.
LoadBalancer
Создаёт внешний балансировщик нагрузки через облачного провайдера (AWS ELB, GCP Load Balancer). Автоматически получает внешний IP.
apiVersion: v1
kind: Service
metadata:
name: api-service
spec:
type: LoadBalancer
selector:
app: api
ports:
- port: 80
targetPort: 8080
kubectl get services api-service
# NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
# api-service LoadBalancer 10.96.12.34 34.123.45.67 80:31234/TCP 3m
Основной тип для production в облаке. Но: каждый LoadBalancer стоит денег. Для многих сервисов лучше использовать Ingress (один балансировщик на все).
ExternalName
Алиас для внешнего DNS-имени. Полезен для миграции или подключения внешних сервисов.
apiVersion: v1
kind: Service
metadata:
name: external-db
spec:
type: ExternalName
externalName: db.example.com
DNS внутри кластера
K8s автоматически создаёт DNS-записи для каждого Service. Формат:
<service-name>.<namespace>.svc.cluster.local
Примеры обращения к сервисам:
# Из того же namespace
curl http://backend-service
# Из другого namespace
curl http://backend-service.production.svc.cluster.local
# Короткая запись из другого namespace
curl http://backend-service.production
DNS обеспечивает CoreDNS — компонент Control Plane. Pod автоматически настроен на использование внутреннего DNS.
kubectl expose: быстрое создание Service
# Создать Service для Deployment
kubectl expose deployment my-app --port=80 --target-port=8000
# Создать NodePort
kubectl expose deployment my-app --type=NodePort --port=80
# Создать LoadBalancer
kubectl expose deployment my-app --type=LoadBalancer --port=80
Сравнение типов
| Тип | Доступ | Когда использовать |
|---|---|---|
| ClusterIP | Только внутри кластера | Межсервисная коммуникация |
| NodePort | Внешний, через IP узла | Dev/тестирование |
| LoadBalancer | Внешний, через облачный LB | Production API в облаке |
| ExternalName | DNS-алиас | Внешние сервисы |
Проверка работы Service
# Детали Service
kubectl describe service backend-service
# Endpoints (живые поды за Service)
kubectl get endpoints backend-service
# NAME ENDPOINTS AGE
# backend-service 10.244.1.5:8000,10.244.2.8:8000,... 5m
# Временный Pod для отладки сети
kubectl run debug --image=busybox -it --rm -- wget -qO- http://backend-service
💬 Комментарии (0)
Комментариев пока нет
Станьте первым, кто поделится мнением об этой статье!