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 层变得真正可用。

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

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 endpointslice -n <ns> -l kubernetes.io/service-name=<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 能解析,但流量还是不通

通常问题出在返回的 Pod 还没 Ready,或客户端把 Headless Service 当成了普通负载均衡入口。

没有有效 endpoints

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

Stateful 应用在发布时拓扑异常

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

DNS 与副本身份的三个判断

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

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

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

继续补齐有状态链路

使用前 DNS 验收

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

参考链接