背景
下面我将以这个思维导图来总结一下k8s中的dns。
简介
Kubernetes中的Service通过虚拟ip地址或者endpoint为用户应用提供访问入口。然而这些ip地址和端口是动态分配的,如果用户重建一个服务,其分配的clusterlP和nodePort,以及LoadBalancerlP都是会变化的,这样再使用原来的ip地址就无法访问了。
Kubernetes提供了内置的域名服务,用户定义的服务会自动获得域名,而无论服务重建多少次,只要服务名不改变,其对应的域名就不会改变。
coreDNS
CoreDNS是一个基于内存的DNS,与其他controller类似的控制器。
查看coreDNS的pod
CoreDNS的实现原理是,控制器监听Service和Endpoint的变化并配置 DNS,客户端 Pod 在进行域名解析时,从 CoreDNS 中查询服务对应的地址记录。
- 如果服务重建了,变化的也只是dns记录中的VIP,只要服务名和namespace没有变化,这个服务的域名就没有变化。svcl.ns1.svc.clusterdomain:VIP1。
- pod测根据策略dnsPolicy,默认值是ClusterFirst,创建一个/etc/resolv.conf文件,文件中指定nameserver地址为coredns的地址,
不同类型的dns记录
普通 Service
ClusterlP、nodePort、LoadBalancer类型的Service都拥有APIServer分配的ClusterlP,CoreDNS 会为这些 Service 创建 FQDN。
格式为 $svcname.$namespace.svc. $clusterdomain:clusterlP 的A记录及PTR(ip–>域名)记录,并为端口创建SRV记录。
Headless Service
无头服务,是用户在Spec显式指定ClusterlP为 None 的Service,对于这类 Service, APIServer不会为其分配ClusterlP。CoreDNS为此类 Service 创建多条A记录,并且目标为PodIP。
另外,每个pod会拥有一个FQDN。格式为$podname.$svcname.$namespace.svc.$clusterdomain 的A记录指向PodiP。
由于没有ClusterlP,kube-proxy不会为这个service做任何的路由转发,也就是说kube-proxy和headless service无关。
ExternalName Service
此类Service用来引用一个已经存在的域名,CoreDNS会为该Service创建一个Cname记录指向目标域名。
Kubernetes中的域名解析
- Kubernetes Pod 有一个与 DNS 策略相关的属性 DNSPolicy,默认值是 ClusterFirst。
- Pod 启动后的 /etc/resolv.conf 会被改写,所有的地址解析优先发送至 CoreDNS。
- 当 Pod 启动时,同— Namespace 的所有 Service 都会以环境变量的形式设置到容器内。
这个属性是由pod的enableServiceLinks控制。
可能遇到的问题
如果一个namespace中的service过多,可能会导致创建pod失败。
原因
由于创建pod会把同一ns中的service都以环境变量的形式存储到容器中,创建pod也是调用CRI的接口,再通过environment的参数传入的。service过多,启动容器的命令也就过长,但是Linux对命令行有限制,过长的话就把后面的截掉了,这样启动容器的命令就不完整,导致启动失败。
这时就需要修改enableServiceLinks参数为false。
实例
查看服务
k get svc
查看nginx pod中的dns记录。
k exec -it nginx-6cc88c7947-c4mpg -- bash
cat /etc/resolv.conf
- nameserver:当pod要去查询域名的时候,去哪解析。地址是10.96.0.10。这个地址是kube-dns(coredns)的地址。
- options ndots:5。5代表着域名里有几个“.”,5个以下的是短名。
- search default.svc.cluster.local svc.cluster.local cluster.local openstacklocal。
- 比如两个服务在同一个namespace,不希望每次调用都写这么长的域名,希望通过短名的方式访问。
- 如果域名是短名,会按照search中的先后顺序依次在短名后添加后缀。
查询长域名
进入到集群中的一个pod中,我这里是Wordpress,ns不是default。
curl nginx.default.svc.cluster.local
查询短名
自定义dns policy
pod模版中指定dnsPolicy为None,配置dnsConfig即可。
实践
Kubernetes中的服务也需要发布到企业 DNS,需要定制企业 DNS 控制器。
针对LoadBalancer类型的服务,在企业DNS中需要创建A/PTR/SRV记录,地址为LoadBalancer的vip。
针对headless service,如果podip可以对外访问,也需要在企业DNS上按需创建DNS记录。
服务在集群内通过CoreDNS寻址,在集群外通过企业DNS寻址,服务在集群内外有统一标识。