Kubernetes中的HeadlessService

tech2024-10-29  9

Kubernetes中的HeadlessService

前言:

最近在基于K8S开发平台的过程中遇到了有个问题没有弄懂,就是CoreDNS的作用,就好像在Docker Swarm里面,我们可以通过Service name来访问一组容器,在K8S里,我们想要通过name来访问服务的方式就是在Deployment上面添加一层Servic,这样我们就可以通过Service name来访问服务了,那其中的原理就是和CoreDNS有关,它将Service name解析成Cluster IP,这样我们访问Cluster IP的时候就通过Cluster IP作负载均衡,把流量分布到各个POD上面。 我想的问题是CoreDNS是否会直接解析POD的name,在Service的服务里,是不可以的,因为Service有Cluster IP,直接被CoreDNS解析了,那怎么才能让它解析POD呢,有大牛提出了可以使用Headless Service,所以我们就来探究一下什么是Headless Service。 Headless Service也是一种Service,但不同的是会定义spec:clusterIP: None,也就是不需要Cluster IP的Service。 我们首先想想Service的Cluster IP的工作原理:一个Service可能对应多个EndPoint(Pod),client访问的是Cluster IP,通过iptables规则转到Real Server,从而达到负载均衡的效果。具体操作如下所示:

案例

# kubectl get svc NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE nginx-service 10.107.124.218 192.168.128.158 80/TCP,443/TCP 1d # kubectl describe svc nginx-service Name: nginx-service Namespace: default Labels: Selector: component=nginx Type: ClusterIP IP: 10.107.124.218 External IPs: 192.168.128.158 Port: nginx-http 80/TCP Endpoints: 10.244.2.9:80 Port: nginx-https 443/TCP Endpoints: 10.244.2.9:443 Session Affinity: None No events. # nslookup nginx-service.default.svc.cluster.local 10.96.0.10 Server: 10.96.0.10 Address: 10.96.0.10#53 Name: nginx-service.default.svc.cluster.local Address: 10.107.124.218

从上面的结果中我们可以看到虽然Service有2个endpoint,但是dns查询时只会返回Service的地址。具体client访问的是哪个Real Server,是由iptables来决定的。

那么我们再来看看Headless Service的效果呢?

# kubectl get service NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE nginx None 80/TCP 1h # kubectl describe service nginx Name: nginx Namespace: default Labels: app=nginx Selector: app=nginx Type: ClusterIP IP: None Port: web 80/TCP Endpoints: 10.244.2.17:80,10.244.2.18:80 Session Affinity: None No events. # nslookup nginx.default.svc.cluster.local 10.96.0.10 Server: 10.96.0.10 Address: 10.96.0.10#53 Name: nginx.default.svc.cluster.local Address: 10.244.2.17 Name: nginx.default.svc.cluster.local Address: 10.244.2.18

根据结果得知dns查询会如实的返回2个真实的endpoint。

所以,顾名思义,Headless Service就是没头的Service。有什么使用场景呢?

第一种:自主选择权 有时候client想自己来决定使用哪个Real Server,可以通过查询DNS来获取Real Server的信息。第二种:Headless Services还有一个用处(PS:也就是我们需要的那个特性) Headless Service的对应的每一个Endpoints,即每一个Pod,都会有对应的DNS域名;这样Pod之间就可以互相访问。我们还是看上面的这个例子。 # kubectl get statefulsets web NAME DESIRED CURRENT AGE web 2 2 1h kubectl get pods web-0 1/1 Running 0 1h web-1 1/1 Running 0 1h # nslookup nginx.default.svc.cluster.local 10.96.0.10 Server: 10.96.0.10 Address: 10.96.0.10#53 Name: nginx.default.svc.cluster.local Address: 10.244.2.17 Name: nginx.default.svc.cluster.local Address: 10.244.2.18 # nslookup web-1.nginx.default.svc.cluster.local 10.96.0.10 Server: 10.96.0.10 Address: 10.96.0.10#53 Name: web-1.nginx.default.svc.cluster.local Address: 10.244.2.18 # nslookup web-0.nginx.default.svc.cluster.local 10.96.0.10 Server: 10.96.0.10 Address: 10.96.0.10#53 Name: web-0.nginx.default.svc.cluster.local Address: 10.244.2.17

如上,web为我们创建的StatefulSets,对应的pod的域名为web-0,web-1,他们之间可以互相访问,这样对于一些集群类型的应用就可以解决互相之间身份识别的问题了。

总结

带Headless Services的pod可以通过以下域名进行访问。这个有什么用呢?这可以在k8s中部署数据库集群时使用,比如启动一个3节点的etcd集群,启动时便可以通过以下方式指定3个pod的具体地址。

<PodName>.<ServiceName>.<NamespaceName>.svc.cluster.local
最新回复(0)