k8s

k8s中的dns

背景

下面我将以这个思维导图来总结一下k8s中的dns。
file

简介

Kubernetes中的Service通过虚拟ip地址或者endpoint为用户应用提供访问入口。然而这些ip地址和端口是动态分配的,如果用户重建一个服务,其分配的clusterlP和nodePort,以及LoadBalancerlP都是会变化的,这样再使用原来的ip地址就无法访问了。

Kubernetes提供了内置的域名服务,用户定义的服务会自动获得域名,而无论服务重建多少次,只要服务名不改变,其对应的域名就不会改变。

coreDNS

CoreDNS是一个基于内存的DNS,与其他controller类似的控制器。

查看coreDNS的pod

file

CoreDNS的实现原理是,控制器监听Service和Endpoint的变化并配置 DNS,客户端 Pod 在进行域名解析时,从 CoreDNS 中查询服务对应的地址记录。

  • 如果服务重建了,变化的也只是dns记录中的VIP,只要服务名和namespace没有变化,这个服务的域名就没有变化。svcl.ns1.svc.clusterdomain:VIP1。
  • pod测根据策略dnsPolicy,默认值是ClusterFirst,创建一个/etc/resolv.conf文件,文件中指定nameserver地址为coredns的地址,
    file

file

不同类型的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 都会以环境变量的形式设置到容器内。
    file
    这个属性是由pod的enableServiceLinks控制。
    file

可能遇到的问题

如果一个namespace中的service过多,可能会导致创建pod失败。

原因

由于创建pod会把同一ns中的service都以环境变量的形式存储到容器中,创建pod也是调用CRI的接口,再通过environment的参数传入的。service过多,启动容器的命令也就过长,但是Linux对命令行有限制,过长的话就把后面的截掉了,这样启动容器的命令就不完整,导致启动失败。
这时就需要修改enableServiceLinks参数为false。

实例

查看服务

k get svc

file

查看nginx pod中的dns记录。

k exec -it nginx-6cc88c7947-c4mpg -- bash
cat /etc/resolv.conf

file

  • nameserver:当pod要去查询域名的时候,去哪解析。地址是10.96.0.10。这个地址是kube-dns(coredns)的地址。
    file
  • 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

file

查询短名

file

自定义dns policy

pod模版中指定dnsPolicy为None,配置dnsConfig即可。
file

实践

Kubernetes中的服务也需要发布到企业 DNS,需要定制企业 DNS 控制器。

针对LoadBalancer类型的服务,在企业DNS中需要创建A/PTR/SRV记录,地址为LoadBalancer的vip。

针对headless service,如果podip可以对外访问,也需要在企业DNS上按需创建DNS记录。

服务在集群内通过CoreDNS寻址,在集群外通过企业DNS寻址,服务在集群内外有统一标识。

分类: k8s
0 0 投票数
文章评分
订阅评论
提醒
guest

0 评论
内联反馈
查看所有评论

相关文章

开始在上面输入您的搜索词,然后按回车进行搜索。按ESC取消。

返回顶部
0
希望看到您的想法,请您发表评论x