前言: 最近在基于K8S
开发平台的过程中遇到了有个问题没有弄懂,就是CoreDNS
的作用,就好像在Docker Swarm
里面,我们可以通过Service name
来访问一组容器,在K8S
里,我们想要通过name
来访问服务的方式就是在Deployment
上面添加一层Service
,这样我们就可以通过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
,他们之间可以互相访问,这样对于一些集群类型的应用就可以解决互相之间身份识别的问题了。
完整示例:
apiVersion: v1
kind: Service
metadata:
name: nginx
labels:
app: nginx
spec:
ports:
- port: 80
name: web
clusterIP: None
selector:
app: nginx
---
apiVersion: apps/v1beta1
kind: StatefulSet
metadata:
name: web
spec:
serviceName: "nginx"
replicas: 1
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.11
ports:
- containerPort: 80
name: web
volumeMounts:
- name: www
mountPath: /usr/share/nginx/html
nodeSelector:
node: kube-node3
volumes:
- name: www
hostPath:
path: /mydir
网友评论