Kubernetes DNS
DNS介绍
介绍
kubernets的所有资源.包括Service,Pod都有生命周期,会频繁的销毁和创建.这些资源的IP地址也会随之动态变化.所以Kubernetes使用DNS实现通过资源名解析IP地址.
DNS服务器
Kubernetes集群安装了默认的Core-dns组件(通过Pod方式运行).以及kube-dns的service.
1
|
[root@k8s-master ~]$kubectl get pods -n kube-system | grep dns
|
pod容器内部dns解析
创建一个临时的pod容器,测试DNS解析效果.下面的命令临时运行了一个busybox的镜像
1
|
[root@k8s-master ~]$kubectl run -it dns-test --rm --image=busybox:1.28.4 -- sh
|
不要使用latest版本的镜像,其dns解析有问题.最好使用1.28.4版本的
下方是Pod容器的内部dns服务器信息
1
|
/ # cat /etc/resolv.conf
|
resolv.conf 配置文件说明
nameserver:指明DNS服务器地址.也就是上文提到的kube-dns 的service
search:当原始域名不能被DNS解析时,resolver会将该域名加上search指定的参数,重新请求DNS,直到被正确解析或试完search指定的列表为止 options:dns配置
ndots:5:所有DNS查询中,如果“.”的个数少于5个,则会根据search中配置的列表依次在对应域中先进行搜索,如果没有返回,则最后再直接查询域名本身
为了了解search和ndots 的概念,我们先要了解FQDN的概念.FQDN(Fully qualified domain name)即完整域名。一般来说如果一个域名以.结束,就表示一个完整域名。比如www.abc.xyz.就是一个FQDN,而www.abc.xyz则不是FQDN。了解了这个概念之后我们就来看search和options ndots。
如果一个域名是FQDN,那么这个域名会被转发给DNS服务器进行解析。如果域名不是FQDN,那么这个域名会到search搜索解析,还是通过一个例子说明,比如访问abc.xyz这个域名,因为它并不是一个FQDN,所以它会和search域中的值进行组合而变成一个FQDN,以上文的resolv.conf为例,这域名会这样组合:
1
|
abx.xyz.default.svc.cluster.local.
|
然后这些域名先被kube-DNS解析,如果没有解析成功再由宿主机的DNS服务器进行解析。
而ndots是用来表示一个域名中.的个数在不小于该值的情况下会被认为是一个FQDN。简单说这个属性用来判断一个不是以.结束的域名在什么条件下会被认定为是一个FQDN.上面的示例中ndots为5,也就是说如果一个域名中.的数量大于等于5,即使域名不是以.结尾,也会被认定为是一个FQDN。比如:域名是abc.xyz.xxx.yyy.zzz.aaa这个域名就是FQDN.
之所以会有search域主要还是为了方便k8s内部服务之间的访问。比如:k8s在同一个namespace下是可以直接通过服务名称进行访问的,其原理就是会在search域查找,比如上面的resolv.conf中jplat、oms-dev着两个其实都是这两个pod所在的namespace的名称。所以通过服务名称访问的时候,会和search域进行组合,这样最终域名会组合成servicename.namespace.svc.cluster.local。而如果是跨namespace访问,则可以通过servicename.namespace这样的形式,在通过和search域组合,依然可以得到servicename.namespace.svc.cluster.local。
DNS解析
解析对象
Kubernetes集群中的每个Service资源都会被指派一个DNS名称.客户端Pod的DNS搜索列表默认是搜索自己的namespace 名称空间内的资源.
例如上文的resolv.conf 文件内的search搜索列表为search default.svc.cluster.local svc.cluster.local cluster.local localdomain .此时Pod可以直接搜索default 名称空间下的所有Service:
例如.使用上面的临时busybox容器解析my-svc的Service
1
|
/ # nslookup my-svc
|
上面的IP地址10.96.51.58 表示成功解析到该Service的IP.my-svc.default.svc.cluster.local这个就是该Service的FQDN完全限定域名.
其中:
default —表示名称空间,我们的名称空间名字就是默认的default
svc —————-表示资源类型,这里是Service
cluster.local –k8s集群域名
也可以解析其他名称空间内的资源,比如解析kube-system 名称空间下的DNS服务器的Service.(DNS服务器本身也会被指定一个DNS名称).就可以通过<svc-name>.<namespace-name> 实现.比如下面解析kube-system名称空间下的kube-dns的Service
1
|
/ # nslookup kube-dns.kube-system
|
实际上DNS解析的是完全FQDN域名,只不过后面一部分内容default.svc.cluster.local 可以省略罢了.默认就是解析当前名称空间下的资源
1
|
/ # nslookup my-svc
|
在kubernetes官网中也提到:
假设在 Kubernetes 集群的名字空间 bar 中,定义了一个服务 foo。 运行在名字空间 bar 中的 Pod 可以简单地通过 DNS 查询 foo 来找到该服务。 运行在名字空间 quux 中的 Pod 可以通过 DNS 查询 foo.bar 找到该服务。
Service A记录
对于普通的Service资源.会以<service-name>.<namespace-name>.svc.cluster.local这种形式被分配一个DNS A记录.也就是上文中的my-svc的10.96.51.58这个IP地址.
如果是对于无头服务(headless service).这种service没有IP.但是也会以上面的形式被指派一个DNS的A记录.只不过这种记录和普通Service不同,而是被解析成对应服务的POD集合的Pod的IP.客户端使用标准的负载均衡策略从这组Pod中进行选择.
例如下面创建一个headless的svc.和普通svc的区别在于clusterIP的值为None.
1
|
[root@k8s-master ~]$cat deployment-kubia-v1.yaml
|
headless服务一般用于statefulset资源.不能用于deployment控制器
创建该文件后查看hsq-openapiservice:
1
|
[root@k8s-master ~]$kubectl describe svc hsq-openapi
|
headless类型服务的DNS解析
仍然使用上文中的busybox测试容器.解析hsq-openapi service 的A记录.可以看到解析的结果返回了2个pod的IP地址列表.对于这种类型的service.和普通的service不同.他解析出来的是POD的ip地址列表
1
|
/ # nslookup hsq-openapi
|
Pod的A记录
一般而言,Pod会对应如下DNS名字解析: pod-ip-address.<namespace-name>.pod.cluster.local 例如对于上面例子中的iP为10.100.36.69 的Pod.对应的DNS名称为:
1
|
/ # nslookup 10-100-36-69.default.pod.cluster.local #DNS名称
|
k8s默认的DNS策略
k8s提供了5种DNS策略,如下:
Default: Pod 从运行所在的节点继承名称解析配置。ClusterFirst: 与配置的集群域后缀不匹配的任何 DNS 查询(例如 “www.kubernetes.io”) 都将转发到从节点继承的上游名称服务器。集群管理员可能配置了额外的存根域和上游 DNS 服务器。ClusterFirstWithHostNet:对于以 hostNetwork 方式运行的 Pod,应显式设置其 DNS 策略ClusterFirstWithHostNet。None: 此设置允许 Pod 忽略 Kubernetes 环境中的 DNS 设置。Pod 会使用其dnsConfig字段 所提供的 DNS 设置。
k8s默认使用的DNS策略是ClusterFirst,这点需要注意,也就是说域名解析会优先使用集群的DNS(kube-DNS)进行查询,如果k8s的DNS解析失败,会转发到宿主机的DNS进行解析。

浙公网安备 33010602011771号