欢迎加入本站的kubernetes技术交流群,微信添加:加Blue_L。
kubernetes会为每个service对象创建dns记录,这个操作是由dns插件完成的,基本上所有集群都会使用coredns作为dns插件。
kubernetes中的服务是区分命名空间的,nginx这个域名在默认情况下是使用本pod所在namespace解析的,如pod所在的namespace为default,则默认解析为nginx.default。下列是一个示例pod的resolv文件配置
[root@master1 ~]# kubectl exec -it nginx-deployment-66b6c48dd5-95c7f -- cat /etc/resolv.conf
nameserver 172.17.0.10
search default.svc.cluster.local svc.cluster.local cluster.local
options ndots:5
服务对象分为普通服务和无头服务,无头服务是指spec.clusterIP=None的,其他服务则为普通服务。
如果service是一个普通服务对象,则会为其创建一个dns A记录(ipv6则为AAAA记录),该记录的ip地址是在kube-controller-manager的--service-cluster-ip-range
参数指定的网段内,该网段和pod网段以及节点网段都不在一个网段内。
如果service是一个无头服务,则会创建一些列dns A记录,记录的ip地址是pod的ip。
k8s还会为服务对象的每个命名端口创建srv记录。如_my-port-name._my-port-protocol.my-svc.my-namespace.svc.cluster-domain.example。对于普通服务,解析到my-svc.my-namespace.svc.cluster-domain.exampl加端口号。对于无头服务会为每个pod创建一个类似的记录。auto-generated-name.my-svc.my-namespace.svc.cluster-domain.example加端口号。
通常情况下,会为所有pod创建如下类型的dns解析:
pod-ip-address.my-namespace.pod.cluster-domain.example -> pod-ip
kubectl run aaaa --image=nginx
[root@master1 ~]# nslookup 10-248-5-2.default.pod.cluster.local 172.17.0.10
Server: 172.17.0.10
Address: 172.17.0.10#53
Name: 10-248-5-2.default.pod.cluster.local
Address: 10.248.5.2
通常情况下,会为deployment和daemonset的pod,且通过service进行暴露的话,则会创建下列dns解析:
pod-ip-address.deployment.my-namespace.svc.cluster.local -> pod-ip
针对deployment进行测试
kubectl create deployment nginx --image=nginx
kubectl expose deployment nginx --port 80
[root@master3 ~]# nslookup nginx.default.svc.cluster.local 172.17.0.10
Server: 172.17.0.10
Address: 172.17.0.10#53
Name: nginx.default.svc.cluster.local
Address: 172.17.184.200
# 基于deployment(或daemonset)的解析规则
[root@master3 ~]# nslookup 10-248-213-77.nginx.default.svc.cluster.local 172.17.0.10
Server: 172.17.0.10
Address: 172.17.0.10#53
Name: 10-248-213-77.nginx.default.svc.cluster.local
Address: 10.248.213.77
# 来看pod是否也同样有解析
[root@master3 ~]# kubectl get pod -owide | grep nginx
nginx-6799fc88d8-gfpkp 1/1 Running 0 5m34s 10.255.136.159 worker3 <none> <none>
[root@master3 ~]# nslookup 10-255-136-159.default.pod.cluster.local 172.17.0.10
Server: 172.17.0.10
Address: 172.17.0.10#53
Name: 10-255-136-159.default.pod.cluster.local
Address: 10.255.136.159
[root@master3 ~]#
但是针对statefulset规则不同,statefulset可以直接通过pod名(主机名)解析
apiVersion: v1
kind: Service
metadata:
name: nginx
labels:
app: nginx
spec:
ports:
- port: 80
name: web
clusterIP: None
selector:
app: nginx
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: web
spec:
selector:
matchLabels:
app: nginx # has to match .spec.template.metadata.labels
serviceName: "nginx"
replicas: 3 # by default is 1
template:
metadata:
labels:
app: nginx # has to match .spec.selector.matchLabels
spec:
terminationGracePeriodSeconds: 10
containers:
- name: nginx
image: k8s.gcr.io/nginx-slim:0.8
ports:
- containerPort: 80
name: web
[root@master3 ~]# kubectl apply -f statefulset.yaml
[root@master3 ~]# kubectl get pod -owide | grep web-0
web-0 0/1 ImagePullBackOff 0 57s 10.248.213.77 worker1 <none> <none>
[root@master3 ~]# nslookup nginx.default.svc.cluster.local 172.17.0.10
Server: 172.17.0.10
Address: 172.17.0.10#53
Name: nginx.default.svc.cluster.local
Address: 10.255.136.159
# 使用主机名解析,普通服务和无头服务都可以
[root@master3 ~]# nslookup web-0.nginx.default.svc.cluster.local 172.17.0.10
Server: 172.17.0.10
Address: 172.17.0.10#53
Name: web-0.nginx.default.svc.cluster.local
Address: 10.248.213.77
使pod的域名可解析。
kubernetes设计中,满足该条件则可以通过dns解析到pod的ip地址:被service选中的pod有hostname和subdomain配置。如果被service选中的pod没有hostname配置,但是有subdomain配置时,pod的ip仅可以作为无头服务的A纪录返回,如果hostname和subdomain都有配置,则应创建pod的dns记录(因为这时候endpoint才会有hostname字段)。
下面是测试pod配置或不配置subdomain时,分别创建普通服务和无头服务的测试(基于kubernetes 1.22和coredns 1.8.4):
# pod对象
apiVersion: v1
kind: Pod
metadata:
name: busybox
labels:
app: busybox
spec:
hostname: busybox
subdomain: default-subdomain
containers:
- image: busybox
command:
- sleep
- "3600"
imagePullPolicy: IfNotPresent
name: busybox
restartPolicy: Always
# service对象
apiVersion: v1
kind: Service
metadata:
name: default-subdomain
spec:
selector:
app: busybox
type: ClusterIP
ports:
- port: 80
# 有subdomain,没有创建服务时pod解析
[root@master3 ~]# nslookup busybox.default-subdomain.default.svc.cluster.local 172.17.0.10
Server: 172.17.0.10
Address: 172.17.0.10#53
** server can't find busybox.default-subdomain.default.svc.cluster.local: NXDOMAIN
# 有subdomain,创建普通服务,service解析到clusterIP,pod可以解析,endpoint有hostname
[root@master3 ~]# nslookup default-subdomain.default.svc.cluster.local 172.17.0.10
Server: 172.17.0.10
Address: 172.17.0.10#53
Name: default-subdomain.default.svc.cluster.local
Address: 172.17.33.97
[root@master3 ~]# nslookup busybox.default-subdomain.default.svc.cluster.local 172.17.0.10
Server: 172.17.0.10
Address: 172.17.0.10#53
Name: busybox.default-subdomain.default.svc.cluster.local
Address: 10.248.213.79
[root@master3 ~]#
[root@master3 ~]# kubectl get ep default-subdomain -oyaml | grep -C 1 hostname
- addresses:
- hostname: busybox
ip: 10.248.213.79
# 有subdomain,创建无头服务,service解析的pod地址列表,pod可解析,endpoint有hostname
[root@master3 ~]# nslookup default-subdomain.default.svc.cluster.local 172.17.0.10
Server: 172.17.0.10
Address: 172.17.0.10#53
Name: default-subdomain.default.svc.cluster.local
Address: 10.248.213.79
[root@master3 ~]# nslookup busybox.default-subdomain.default.svc.cluster.local 172.17.0.10
Server: 172.17.0.10
Address: 172.17.0.10#53
Name: busybox.default-subdomain.default.svc.cluster.local
Address: 10.248.213.79
[root@master3 ~]# kubectl get ep default-subdomain -oyaml | grep -C 1 hostname
- addresses:
- hostname: busybox
ip: 10.248.213.79
[root@master3 ~]#
# 无subdomain,创建普通服务,service解析到clusterIP,pod不可解析,endpoint无hostname
[root@master3 ~]# nslookup default-subdomain.default.svc.cluster.local 172.17.0.10
Server: 172.17.0.10
Address: 172.17.0.10#53
Name: default-subdomain.default.svc.cluster.local
Address: 172.17.74.211
[root@master3 ~]# nslookup busybox.default-subdomain.default.svc.cluster.local 172.17.0.10
Server: 172.17.0.10
Address: 172.17.0.10#53
** server can't find busybox.default-subdomain.default.svc.cluster.local: NXDOMAIN
[root@master3 ~]# kubectl get ep default-subdomain -oyaml | grep -C 1 hostname
[root@master3 ~]#
# 无subdomain,创建无头服务,service解析到pod地址列表,pod不可解析,endpoint无hostname
[root@master3 ~]# nslookup default-subdomain.default.svc.cluster.local 172.17.0.10
Server: 172.17.0.10
Address: 172.17.0.10#53
Name: default-subdomain.default.svc.cluster.local
Address: 10.248.213.79
[root@master3 ~]# nslookup busybox.default-subdomain.default.svc.cluster.local 172.17.0.10
Server: 172.17.0.10
Address: 172.17.0.10#53
** server can't find busybox.default-subdomain.default.svc.cluster.local: NXDOMAIN
[root@master3 ~]# kubectl get ep default-subdomain -oyaml | grep -C 1 hostname
[root@master3 ~]#
kubernetes中,对于statefulset的pod,kubernetes在创建的时候会自动设置相关字段
func initIdentity(set *apps.StatefulSet, pod *v1.Pod) {
updateIdentity(set, pod)
// Set these immutable fields only on initial Pod creation, not updates.
pod.Spec.Hostname = pod.Name
pod.Spec.Subdomain = set.Spec.ServiceName
}
对于deployment的pod是不会自动设置hostname和subdomain的,因此我们无法通过dns解析到pod。但是我们可以通过修改coredns配置,加上endpoint_pod_names参数使deployment的pod name(同hostname)可解析为pod ip。开启此参数之后,coredns判断如果endpoint没有hostname字段,则会使用pod的name(不开启的话,则返回“-”分割的ip地址的记录),所以针对上面busybox中无subdomain情况,pod也可解析。
func endpointHostname(addr object.EndpointAddress, endpointNameMode bool) string {
if addr.Hostname != "" {
return addr.Hostname
}
if endpointNameMode && addr.TargetRefName != "" {
return addr.TargetRefName
}
if strings.Contains(addr.IP, ".") {
return strings.Replace(addr.IP, ".", "-", -1)
}
if strings.Contains(addr.IP, ":") {
return strings.Replace(addr.IP, ":", "-", -1)
}
return ""
}
kubernetes代码中下面的判读决定是否要创建endpoint的hostname
func ShouldSetHostname(pod *v1.Pod, svc *v1.Service) bool {
return len(pod.Spec.Hostname) > 0 && pod.Spec.Subdomain == svc.Name && svc.Namespace == pod.Namespace
}
开启endpoint_pod_names后测试
[root@master3 ~]# kubectl create deployment web --image=nginx
[root@master3 ~]# kubectl expose deployment web --port=80
[root@master3 ~]# nslookup web.default.svc.cluster.local 172.17.0.10
Server: 172.17.0.10
Address: 172.17.0.10#53
Name: web.default.svc.cluster.local
Address: 172.17.138.248
[root@master3 ~]# nslookup web-96d5df5c8-29ps6.web.default.svc.cluster.local 172.17.0.10
Server: 172.17.0.10
Address: 172.17.0.10#53
Name: web-96d5df5c8-29ps6.web.default.svc.cluster.local
Address: 10.255.136.160
[root@master3 ~]# kubectl get pod -owide | grep web
web-96d5df5c8-29ps6 1/1 Running 0 3m16s 10.255.136.160 worker3 <none> <none>
[root@master3 ~]# kubectl get pod web-96d5df5c8-29ps6 -oyaml | grep -i subdomain
[root@master3 ~]# kubectl get pod web-96d5df5c8-29ps6 -oyaml | grep -i hostname
[root@master3 ~]# kubectl get ep web -oyaml | grep -i hostname
# 无hostname和subdomain配置的裸pod
[root@master3 ~]# kubectl get pod busybox -oyaml | grep -i hostname
[root@master3 ~]# kubectl get pod busybox -oyaml | grep -i subdomain
[root@master3 ~]# nslookup default-subdomain.default.svc.cluster.local 172.17.0.10
Server: 172.17.0.10
Address: 172.17.0.10#53
Name: default-subdomain.default.svc.cluster.local
Address: 10.255.136.155
[root@master3 ~]# nslookup busybox.default-subdomain.default.svc.cluster.local 172.17.0.10
Server: 172.17.0.10
Address: 172.17.0.10#53
Name: busybox.default-subdomain.default.svc.cluster.local
Address: 10.255.136.155
针对deployment的pod设置hostname和subdomain讨论还在开放中: