Kubernetes CoreDNS 详解

CoreDNS


kube-proxy是运行在每个节点上面的,每个节点上面的kube-proxy其实都是按照同样的规则配置了负载均衡的,比如iptables和ipvs规则,也即是集群上面所有节点它的负载均衡是完全一致的,那么同样集群里面的A服务访问B服务这样的场景,在任何节点上面行为都是一样的。

这样就相当于在每个节点上面都配置了负载均衡的规则,来达到集群层面的分布式负载均衡。

任何的一个客户端要去访问一个服务,它的负载均衡策略在客户端这一层就做掉了,不需要去额外的负载均衡器里面再去做网络地址转换,因为数据包再出去的时候就已经实现了整个的负载均衡。

针对不同类型的service,ClusterIP类型,NodePort,LoadBalance类型。

它本身是基于内存的DNS,不落盘,早期kube-dns是落盘的,那么效率不太好,在集群启动的时候就启动了这样一个dns服务,但是dns服务里面没有任何的记录,这些记录从哪来?

在core dns里面还有控制器,控制器在启动的时候就会去读取集群所有的service的信息,endpoint信息,pod信息,它会将这些dns的映射关系转化为dns配置,service_name+namespace+svc+clusterdomin就是真正服务的域名。

任何的服务都会以这种模式,名称规则去创建域名。

coredns通过控制器来扫描当前集群的endpoint信息和service信息,来决定域名配置,哪个域名指向哪个虚拟IP。

pod这边怎么去解析呢?在pod里面有一个属性叫做DNS Policy,这个DNS Policy的默认值叫做ClusterFirst,也就是当我们去定义pod的时候这个属性你可以不去定义,如果属性不定义那么默认就是ClusterFirst,如果不去定义的话,它默认就是ClusterFirst,那么在你的pod启动之后,它就会帮你创建/etc/resolv.conf这个文件。

在这个文件里面就会去指定说我的nameserver是哪个coredns的地址,然后它会去做一些相应的配置,以便支持你这个域名服务发现。

不同类型服务的DNS记录


Headless是一个无头服务,你显示的声明了clusterIP为none,针对headless servcie那么kube-proxy不会做任何的路由转发和数据包的地址转换,因为它没有一个虚拟IP,所以kube-proxy和headless service没有任何的关系,那么headless service是怎么使用的呢?

dns会去辅助headless servcie,为服务创建地址记录,和普通的service不同的是,它这个地址记录会指向pod IP,是直接访问到pod IP的。

external name:我一个外部的服务域名,在内部通过别名去访问,所谓的别名就是在DNS里面称为Cname,她在本地的DNS里面为外部的服务创建一个cname,你访问这个cname,事实上最终这个dns就会转到外部的这个dns查询,最终请求到这个真实域名所对应的IP地址里面。

来看看具体的clusterfirst的dnsploicy做了什么事情,最终的作用体现在resolve。conf里面。

第一个就是nameserver(域名去哪个DNS查询),当pod发生域名查询的时候,这个域名去哪解析,这个是coreDns的clusterIP。coredns pod里面运行了内存状态的域名服务器和控制器,这个控制器负责往域名服务器里面刷记录。

Kubernetes当中的域名解析


你会看到有很多关于和service相关的一些环境变量,也就是说当我pod启动的时候,这个pod在启动的时候,kubernetes会去读取当前namespace里面所有已存在的service的信息,service对里面地址和端口信息都会以环境变量的方式存放到这个pod里面,做域名服务发现的时候,一方面可以基于dns去查询。

 

 pod里面enableservicelinks这个属性,它默认是true,那么这个属性默认为true的结果就是所有的这种service的信息都会以环境变量的形式export到这个pod里面去

 同一个namespace里面建立了几千的service,最后发现namespace里面的pod创建不出来,是因为kubernetes在启动容器的时候,它最终还是通过cri的接口,通过runc的命令去启动这些容器进程,所有的环境变量其实是在这套启动命令里面的一些参数,它通过enviorment参数传递进去的,当一个namespace里面有数千个个service的时候,它的命令行就变的超长了,linux对应用进程启动时候,参数的长度是有限制的,超长之后就要将后面的截取掉了,这样就使得启动命令不完整,这样的话容器就启动不起来了。

很多场景其实就是一个namespace里面很多service,在早期版本里面无法解决,后面支持了enableservicelinks这个属性,如果不希望通过环境变量来获取这些服务的信息,我们只需要将其置为false,里面的环境变量就看不到这些服务的信息了。

这样一个namspace建立多少service都不影响pod的启动。

自定义DNSPolicy


有些场景下,某些用户它的应用需要自定义DNSPolicy,比如它有自己的nameserver,它有自己的searchdomain,你可以在你的pod里面定义dnspolicy为none,然后加上自己的dnsconfig,

交个朋友 一起学习 一起玩耍


我的微信号 wxid_hsq9rbukl3m522  或者扫码

我的视频号:JhonWick约翰威克

猜你喜欢

转载自blog.csdn.net/qq_34556414/article/details/126329918