Headless Service 是一种很特殊的 Service 用法:它不分配 ClusterIP,而是把 DNS 结果更直接地指向 Pod 级别。它最适合那些需要明确知道“自己在和哪个副本说话”的系统,尤其是数据库、复制集群和其他有状态服务。

一个 Service 怎么才算 headless

关键字段其实很简单:

clusterIP: None

一旦这样配置,Kubernetes 就不会再给它一个普通的虚拟 IP 来做传统意义上的负载均衡,而是更强调 Pod 级别的 DNS 发现。

什么时候该用 Headless Service

  • StatefulSet 场景下需要稳定副本身份
  • 数据库主从或多成员拓扑需要精确定位实例
  • 集群成员之间依赖固定 peer 发现
  • 客户端自己要感知或控制具体副本

如果你只想做普通集群内访问,大多数时候普通的 ClusterIP Service 更简单、更合适。

最小示例

apiVersion: v1
kind: Service
metadata:
  name: mysql
spec:
  clusterIP: None
  selector:
    app: mysql
  ports:
    - port: 3306
      targetPort: 3306

创建后,客户端可以解析类似这样的地址:

mysql-0.mysql.default.svc.cluster.local

为什么它和 StatefulSet 天然连在一起

StatefulSet 负责给副本稳定名字,Headless Service 负责让这些名字在 DNS 层变得真正可用。

所以这两个主题天然是一起看的:

  • kubernetes-quickstart-statefulset.md 讲的是稳定身份和顺序
  • 这篇讲的是客户端和节点怎么真正发现这些身份

Headless Service 不会替你做什么

这里最容易出错。

Headless Service 不会

  • 像普通 ClusterIP 那样帮你做常规负载均衡
  • 自动保证所有返回的地址都“逻辑上可用”
  • 帮你修复 selector 错误或 readiness 错误

它主要改变的是“服务发现方式”,不是“自动兜底逻辑”。

真出问题时先检查什么

别一上来就怀疑 DNS 或 CoreDNS,先看对象关系:

kubectl get svc -n <ns> <svc> -o yaml
kubectl get pods -n <ns> -l app=mysql -o wide
kubectl get endpoints -n <ns> <svc> -o wide
kubectl get endpointslices -n <ns> -l kubernetes.io/service-name=<svc>

如果 selector 没选中、Pod 不 Ready、endpoints 不对,DNS 再正常也帮不了你。

Headless 和普通 Service 的区别

普通 Service 更适合:

  • 客户端只需要一个稳定服务名
  • 后端副本可互换
  • 流量应该自动分散

Headless 更适合:

  • 客户端必须知道具体副本是谁
  • 业务自己处理拓扑和连接分配
  • 副本身份是协议或集群行为的一部分

一个很实用的心智模型

普通 Service 更像是在说:

“把流量打到这组应用上。”

Headless Service 更像是在说:

“告诉我现在到底有哪些具体 Pod 存在。”

YAML 只差一点点,运维思路其实差很多。

常见故障模式

DNS 能解析,但流量还是不通

通常不是 DNS 本身坏了,而是返回的 Pod 还没 Ready,或者客户端错误地以为它还能得到普通负载均衡体验。

没有有效 endpoints

大多数时候就是 selector、labels 或 readiness 问题。

Stateful 应用在发布时拓扑异常

这往往意味着应用确实依赖固定成员关系,但 rollout 顺序、readiness 或拓扑假设没有设计好。

FAQ

Q: Headless Service 是不是只能配 StatefulSet? A: 不是,但 StatefulSet 是最典型、最自然的搭配场景,因为它提供稳定副本身份。

Q: Headless Service 会帮我做负载均衡吗? A: 不会按普通 ClusterIP 的方式帮你做。它主要是暴露副本级别的 DNS 身份。

Q: 为什么我应该先看 endpoints,而不是先抓 DNS 日志? A: 因为大多数 Headless 问题,本质上是 selector、readiness 或 endpoints 关系不对,而不是 DNS 实现本身坏了。

下一步阅读

  • 接着读 kubernetes-quickstart-statefulset.md,理解稳定身份是怎么来的
  • 再读 kubernetes-quickstart-service.md,对比普通 Service 的工作方式
  • 如果你还要把状态和存储串起来,继续看 kubernetes-quickstart-pv-pvc.mdkubernetes-quickstart-storageclass.md

收个尾

Headless Service 的价值,在于它少做了一层抽象。这让有状态系统更容易获得明确的副本身份,但也意味着你必须更认真地思考 selector、readiness、客户端行为和拓扑假设。

参考链接