Kubernetes Headless Service 与 StatefulSet 详解
Headless Service 介绍
Headless Service(无头服务)是 Kubernetes 中的一种特殊 Service 类型,它不会为 Pod 分配集群 IP,也不会进行负载均衡或代理请求。
主要特点
- 无集群 IP:与常规 Service 不同,Headless Service 没有集群 IP 地址
- 直接 DNS 解析:DNS 查询会返回所有匹配的 Pod IP 地址列表,而不是单个 Service IP
- 每个 Pod 有独立 DNS 记录:每个 Pod 会获得一个唯一的 DNS 名称
创建 Headless Service
通过将 clusterIP
字段设置为 None
来创建 Headless Service:
apiVersion: v1
kind: Service
metadata:
name: my-headless-service
spec:
clusterIP: None
selector:
app: my-app
ports:
- protocol: TCP
port: 80
targetPort: 9376
使用场景
- 需要直接与特定 Pod 通信而不是通过代理
- 需要知道所有 Pod 的 IP 地址
- StatefulSet 需要稳定的网络标识
Headless Service 与 StatefulSet 的联系
Headless Service 与 StatefulSet 是 Kubernetes 中为有状态应用设计的两个紧密相关的概念。
协同工作机制
-
稳定的网络标识:
- StatefulSet 为每个 Pod 提供有序的、稳定的标识(如 web-0, web-1, web-2)
- Headless Service 为这些 Pod 提供可解析的 DNS 名称(如 web-0.my-headless-service.namespace.svc.cluster.local)
-
DNS 记录:
- 每个 StatefulSet Pod 通过 Headless Service 获得唯一的 DNS 名称
- 这些名称在 Pod 重启或重新调度时保持不变
-
有序部署和扩展:
- StatefulSet 保证 Pod 按顺序创建和扩展(0, 1, 2,…)
- Headless Service 确保每个 Pod 有稳定的网络标识与之对应
为什么 StatefulSet 需要 Headless Service
-
直接 Pod 访问:有状态应用通常需要直接访问特定的实例,而不是通过负载均衡器
-
稳定的网络拓扑:即使 Pod 重新调度到其他节点,DNS 名称保持不变
-
Peer 发现:在集群应用中(如数据库),Pod 需要发现并相互通信
示例配置
典型的 StatefulSet 与 Headless Service 配合使用的配置:
apiVersion: v1
kind: Service
metadata:
name: mysql
labels:
app: mysql
spec:
ports:
- port: 3306
name: mysql
clusterIP: None
selector:
app: mysql
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: mysql
spec:
serviceName: "mysql" # 引用上面的 Headless Service
replicas: 3
selector:
matchLabels:
app: mysql
template:
metadata:
labels:
app: mysql
spec:
containers:
- name: mysql
image: mysql:5.7
ports:
- containerPort: 3306
name: mysql
实际应用中的 DNS 解析
对于上述配置,Kubernetes DNS 会创建以下记录:
mysql-0.mysql.namespace.svc.cluster.local
→ Pod 0 的 IPmysql-1.mysql.namespace.svc.cluster.local
→ Pod 1 的 IPmysql-2.mysql.namespace.svc.cluster.local
→ Pod 2 的 IPmysql
(SRV 记录) → 所有 3 个 Pod 的列表
总结
Headless Service 和 StatefulSet 共同为 Kubernetes 中的有状态工作负载提供了稳定的网络标识和发现机制。这种组合特别适合需要以下特性的应用:
- 稳定的、可预测的 Pod 名称
- 持久化存储
- 有序部署和扩展
- 需要直接 Pod 到 Pod 通信的场景