在某些应用场景中,客户端应用不需要通过Kubernetes 内置Service 实现的负载均衡功能,或者需要自行完成对服务后端各实例的服务发现机制,或者需要自行实现负载均衡功能,此时可以通过创建一种特殊的名为“Headless” 的服务来实现。
Headless Service 的概念是这种服务没有入口访问地址(无ClusterIP 地址),kube-proxy 不会为其创建负载均衡转发规则,而服务名(DNS域名)的解析机制取决于该Headless Service 是否设置了Label Selector。
1. Headless Service 设置了Label Selector
如果Headless Service 设置了Label Selector ,Kubernetes 则将Label Selector 查询后端Pod 列表,自动创建Endpoint 列表,将服务名(DNS域名)的解析机制设置为:当客户端访问该服务名时,得到的是全部Endpoint 列表(而不是一个确定的IP地址)。
以下面的Headless Service 为例,其设置了Label Selector:
apiVersion: v1
kind: Service
metadata:
name: nginx
labels:
app: nginx
spec:
ports:
- port: 8080
clusterIP: None
selector:
app: nginx
创建该Headless Service:
[root@k8s-master ~]# kubectl create -f nginx-headless-service.yaml
service/nginx created
假设在集群中已经运行了2个副本nginx deployment ,查看他们的Pod IP 地址:
[root@k8s-master ~]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-deployment-64775df955-dzjps 1/1 Running 11 (3d1h ago) 36d 10.244.140.125 k8s-node-2 <none> <none>
nginx-deployment-64775df955-jk28d 1/1 Running 11 (3d1h ago) 36d 10.244.109.121 k8s-node-1 <none> <none>
查看该Headless Service 的详细信息,可以看到后端Endpoint 列表:
[root@k8s-master ~]# kubectl describe svc nginx
Name: nginx
Namespace: default
Labels: app=nginx
Annotations: <none>
Selector: app=nginx
Type: ClusterIP
IP Family Policy: SingleStack
IP Families: IPv4
IP: None
IPs: None
Port: <unset> 8080/TCP
TargetPort: 8080/TCP
Endpoints: 10.244.109.121:8080,10.244.140.125:8080
Session Affinity: None
Events: <none>
用nslookup 工具对Headless Service 名称尝试域名解析,将会看到DNS 系统返回的全部Endpoint 的IP地址,例如:
[root@k8s-master ~]# nslookup nginx.default.svc.cluster.local
Server: 169.169.0.100
Address: 169.169.0.100#53
Name: nginx.default.svc.cluster.local
Address: 10.244.109.121
Name: nginx.default.svc.cluster.local
Address: 10.244.140.125
当客户端通过DNS 服务名“nginx“(或其FQDN 全限定域名“nginx..svc.cluster.local”)和服务端口号访问该Headless 服务(URL=nginx:80) 时,将得到Service 后端Endpoint 列表10.244.109.121:8080 ,10.244.140.125:8080 ,然后由客户端程序自行决定如何操作,例如通过轮询访问各个Endpoint。
2. Headless Service 没有设置Label Selector
如果Headless Service 没有设置Label Selector,则Kubernetes 将不会自动创建对应的Endpoint 列表,DNS 系统会根据下列条件尝试对该服务名设置DNS 记录:
(1)如果Service 的类型为ExTernalName ,则对服务名的访问将直接被DNS 系统转换为Service 设置的外部名称(externalName)。
(2)如果系统中存在与Service 同名的Endpoint 定义,则服务名将被解析为Endpoint 定义中的列表,适用于ExTernalName类型的Service。