1. 概述
在 Kubernetes 中,Service 是一种用于为一个或多个 Pod 提供统一访问入口的资源。它通过一个统一的 IP 和域名将一组 Pod 暴露给网络。当请求到达 Service 时,Kubernetes 的 kube-proxy 会将其转发到其中一个后端 Pod。
而 Headless Service 是一种特殊的 Service,它不分配 ClusterIP,这意味着它不会提供负载均衡能力,但可以直接暴露后端 Pod 的 IP 地址。这种特性在某些场景下非常有用,比如需要直接访问某个 Pod 的情况。
本文将介绍 Headless Service 的基本配置方式,并通过实际演示展示其典型应用场景。
2. 什么是 Headless Service
Headless Service 就是 不分配 ClusterIP 的 Service。在定义时,只需要将 spec.clusterIP
字段设置为 None
即可。
以下是一个 Headless Service 的 YAML 示例:
apiVersion: v1
kind: Service
metadata:
name: headless-svc
spec:
clusterIP: None
selector:
app: web
ports:
- protocol: TCP
port: 80
targetPort: 8080
创建完成后,可以使用如下命令验证其 clusterIP
是否为 None
:
$ kubectl get svc -o go-template='{{ .spec.clusterIPs }}' headless-svc
[None]
✅ 注意:Kubernetes 控制平面不会为 Headless Service 分配 ClusterIP。
3. Headless Service 的特性
普通 Service 在 DNS 解析时会返回一个固定的 ClusterIP,而 Headless Service 则会返回所有匹配 Pod 的 IP 地址列表。这使得我们可以直接访问特定 Pod,而不是通过负载均衡器。
举个例子:
- ✅ 普通 Service:DNS 返回单个 IP(ClusterIP)
- ✅ Headless Service:DNS 返回多个 IP(每个 Pod 的 IP)
这种机制非常适合需要访问具体 Pod 的场景,比如:
- 监控服务直接向每个 Pod 发送健康检查
- 状态类服务(如数据库)需要固定访问某个 Pod
4. 实战演示
接下来我们通过一个实际例子来演示 Headless Service 的使用。
4.1. 创建 Headless Service
首先创建一个 Headless Service:
$ kubectl apply -f - <<EOF
apiVersion: v1
kind: Service
metadata:
name: headless-svc-stateful
spec:
clusterIP: None
selector:
app: web-stateful
ports:
- protocol: TCP
port: 80
targetPort: 8080
EOF
4.2. 创建 StatefulSet
接下来创建一个 StatefulSet,部署三个 Pod:
$ kubectl apply -f - <<EOF
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: app-stateful
labels:
app: server-stateful
spec:
replicas: 3
selector:
matchLabels:
app: web-stateful
serviceName: headless-svc-stateful
template:
metadata:
labels:
app: web-stateful
spec:
containers:
- name: nginx
image: nginx:alpine
ports:
- containerPort: 80
EOF
✅ 注意:StatefulSet 必须指定 serviceName
,且必须指向已有的 Headless Service。
创建完成后,查看 Pod 状态:
$ kubectl get pods -l app=web-stateful
NAME READY STATUS RESTARTS AGE
app-stateful-0 1/1 Running 0 32m
app-stateful-1 1/1 Running 0 31m
app-stateful-2 1/1 Running 0 31m
4.3. 创建调试容器
为了测试 DNS 解析,我们需要一个包含 nslookup
的调试容器。可以使用 kubectl debug
命令创建一个临时容器:
$ kubectl debug -it app-stateful-0 --image=slongstreet/bind-utils:latest -- bash
Defaulting debug container name to debugger-2crmp.
$
4.4. 解析 Headless Service 的 IP
在调试容器中执行 DNS 查询:
$ nslookup headless-svc-stateful
Server: 10.96.0.10
Address: 10.96.0.10#53
Name: headless-svc-stateful.default.svc.cluster.local
Address: 10.244.0.11
Name: headless-svc-stateful.default.svc.cluster.local
Address: 10.244.0.12
Name: headless-svc-stateful.default.svc.cluster.local
Address: 10.244.0.10
✅ 结果说明:返回了三个 Pod 的 IP 地址。
4.5. 解析特定 Pod 的 IP
如果需要解析某个特定 Pod 的 IP,可以使用如下格式:
<Pod名称>.<Service名称>
例如查询 app-stateful-1
的 IP:
$ nslookup app-stateful-1.headless-svc-stateful
Server: 10.96.0.10
Address: 10.96.0.10#53
Name: app-stateful-1.headless-svc-stateful.default.svc.cluster.local
Address: 10.244.0.11
✅ 结果说明:只返回了 app-stateful-1
的 IP。
5. 总结
Headless Service 是 Kubernetes 中一种非常有用的 Service 类型,尤其适用于以下场景:
- 需要直接访问 Pod IP 的情况
- 使用 StatefulSet 部署有状态应用
- 需要对每个 Pod 进行独立健康检查
它通过 DNS 返回 Pod 列表的方式,使得服务发现更加灵活,避免了负载均衡带来的不确定性。
✅ Headless Service 的核心价值:
让服务发现更精细,让 Pod 地址可见。