Ответ
Основное отличие — в модели доступа и балансировки нагрузки.
Обычный сервис (например, ClusterIP):
- Служит единой точкой входа (статический виртуальный IP-адрес) для группы подов.
- Выполняет балансировку нагрузки (по умолчанию, round-robin) между подами.
- DNS-имя сервиса резолвится в этот один виртуальный IP.
- Идеален для stateless-приложений (веб-серверы, API), где любой под может обработать запрос.
Headless-сервис (Headless Service):
Создается путем установки clusterIP: None в спецификации.
- Не имеет виртуального IP-адреса и не балансирует нагрузку.
- Его DNS-имя возвращает список всех A-записей (IP-адресов) подов, отобранных селектором сервиса.
- Позволяет клиенту подключаться напрямую к конкретному поду, что критически важно для stateful-приложений.
Пример использования для StatefulSet (например, база данных):
# Headless Service для кластера PostgreSQL
apiVersion: v1
kind: Service
metadata:
name: postgres
spec:
clusterIP: None # Делаем сервис headless
selector:
app: postgres
ports:
- port: 5432
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: postgres
spec:
serviceName: "postgres" # StatefulSet привязан к этому headless-сервису
replicas: 3
selector:
matchLabels:
app: postgres
template:
metadata:
labels:
app: postgres
spec:
containers:
- name: postgres
image: postgres:15
Что это дает:
- Каждый под получает стабильное DNS-имя:
postgres-0.postgres.default.svc.cluster.local,postgres-1.postgres...и т.д. - Запрос
nslookup postgres.default.svc.cluster.localвернет все 3 IP-адреса подов. - Приложение может использовать эту информацию для прямого подключения к мастер-ноде (
postgres-0) или для организации репликации между инстансами. Я использовал headless-сервисы для развертывания кластеров Redis Sentinel и Elasticsearch, где каждый инстанс должен знать обо всех остальных.