主题
第9章 Headless Service 与有状态服务
有些场景不需要负载均衡,而是需要直接访问每一个 Pod。这时就要用到 Headless Service。本章讲解 Headless Service 和 StatefulSet 的配合使用。
9.1 什么是 Headless Service
将 spec.clusterIP 设为 None,Service 不再分配 ClusterIP,kube-proxy 也不为其创建转发规则。
yaml
apiVersion: v1
kind: Service
metadata:
name: web-headless
spec:
clusterIP: None
selector:
app: web
ports:
- port: 80
targetPort: 80809.2 DNS 查询行为
普通 Service 的 DNS 查询返回 ClusterIP:
text
web-service.default.svc.cluster.local -> 10.96.123.45Headless Service 的 DNS 查询直接返回后端 Pod 的 IP 列表:
text
web-headless.default.svc.cluster.local -> 10.244.1.10, 10.244.1.11, 10.244.1.129.3 适用场景
- 需要客户端自己决定连接哪个后端(如自定义负载均衡、分片)。
- 有状态服务需要稳定的网络标识(配合 StatefulSet 使用)。
- 需要直接获取所有后端 Pod IP(如 Prometheus 服务发现)。
9.4 StatefulSet 与 Headless Service
StatefulSet 用于部署有状态应用(如 MySQL、Redis、Zookeeper、Kafka)。每个 Pod 拥有稳定的:
- 名称:
<statefulset-name>-<ordinal>,如web-0、web-1。 - 网络标识:
<pod-name>.<service-name>.<namespace>.svc.cluster.local。 - 存储:通过 volumeClaimTemplates 每个 Pod 拥有独立 PVC。
StatefulSet 示例
yaml
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: web
spec:
serviceName: web-headless
replicas: 3
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
spec:
containers:
- name: web
image: nginx:alpine
ports:
- containerPort: 80稳定的 DNS 名称
text
Pod: web-0
DNS: web-0.web-headless.default.svc.cluster.local
Pod: web-1
DNS: web-1.web-headless.default.svc.cluster.local这样,每个 Pod 都有一个不会随重建而改变的唯一网络标识。
9.5 Headless Service 与普通 Service 对比
| 特性 | 普通 Service | Headless Service |
|---|---|---|
| ClusterIP | 自动分配 | None |
| kube-proxy 规则 | 有 | 无 |
| DNS 返回 | ClusterIP | Pod IP 列表 / 有状态 Pod 名称 |
| 负载均衡 | 自动 | 客户端自己决定 |
| 适用场景 | 无状态微服务 | 有状态服务、自定义发现 |
9.6 本章小结
- Headless Service 不分配 ClusterIP,DNS 直接返回后端 Pod IP。
- 常用于有状态服务、自定义负载均衡、服务发现场景。
- StatefulSet + Headless Service 为每个 Pod 提供稳定的名称、网络和存储。
本章练习
- 创建一个 Headless Service 和 3 个 Pod,用
nslookup观察 DNS 返回。 - 创建一个 StatefulSet,验证每个 Pod 是否有稳定的 DNS 名称。
- 思考:什么场景下普通 Service 无法满足需求,必须使用 Headless Service?