Kubernetes DNS支持

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Kubernetes DNS支持相关的知识,希望对你有一定的参考价值。

参考技术A Kubernetes DNS 在集群中会启动dns pod(coredns)和service(kube-dns)。集群中的container使用kube-dns service进行dns解析。

在集群中,每个service都会分配一个域名,默认一个pod会查找他自己namespace和集群中的default域。如:在bar namespace中分配一个service foo,运行在bar namespace中的pod可以通过foo查找这个服务,运行在quux namespace中的pod需要foo.bar查找这个服务

一个正常的service (非headless)会被分配一个dns A记录,如:my-svc.my-namespace.svc,cluster.local.被解析到集群中的serivce ip上。

测试DNS解析服务:

创建服务kubectl create service nodeport redis --tcp=6379:6379

 kubectl get service

NAME        TYPE        CLUSTER-IP    EXTERNAL-IP  PORT(S)          AGE

kubernetes  ClusterIP  10.96.0.1      <none>        443/TCP          2d13h

redis        NodePort    10.101.45.89  <none>        6379:32082/TCP  13s

运行测试pod kubectl run busybox --rm -ti --image=busybox /bin/sh

/ # nslookup redis

Server: 10.96.0.10

Address: 10.96.0.10:53

Name: redis.default.svc.cluster.local

Address: 10.101.45.89

/ # nslookup redis.default.svc.cluster.local.

Server: 10.96.0.10

Address: 10.96.0.10:53

Name: redis.default.svc.cluster.local

Address: 10.101.45.89

/ # nslookup kube-dns.kube-system.svc.cluster.local.

Server: 10.96.0.10

Address: 10.96.0.10:53

Name: kube-dns.kube-system.svc.cluster.local

Address: 10.96.0.10

可以发现域名被解析了。

Headless 服务,会解析一出来一个pod的ip list.客户端自己选择IP。

SRE解析记录格式为:_my-port-name._my-port-protocol.my-svc.my-namespace.svc.cluster.local

对于无头服务,这将解析为多个答案,每个答案对应支持该服务的pod,并包含表单auto-generate -name.my- namespace - pace. svg .cluster.local的pod端口号和域名

每个pod都会分配一个:pod-ip-address.my-namespace.pod.cluster.local记录。比如一个pod在default namespace的IP为 1.2.3.4 ,它将有一个1-2-3-4.default.pod.cluster.local.记录。

/ # nslookup 10-32-0-3.default.pod.cluster.local.

Server: 10.96.0.10

Address: 10.96.0.10:53

Name: 10-32-0-3.default.pod.cluster.local

Address: 10.32.0.3

pod的hostname&subdomain也会有一个记录:foo(hostname).bar(subdomain).my-namespace.svc.cluster.local

POD里的DNS策略可以对每个pod进行设置,他支持四种策略default,ClusterFirst,ClusterFirstWithHostNet,None:

default: 表示 Pod 里面的 DNS 配置继承了宿主机上的 DNS 配置。简单来说,就是该 Pod 的 DNS 配置会跟宿主机完全一致。也就是和node上的dns配置是一样的

ClusterFirst:相对于上述的 Default,ClusterFirst 是完全相反的操作,它会预先把 kube-dns(或 CoreDNS)的信息当作预设参数写入到该 Pod 内的 DNS 配置。ClusterFirst 是默认的pod设置,若没有在 Pod 内特别描述 PodPolicy, 则会将 dnsPolicy 预设为 ClusterFirst.不过ClusterFirst 还有一个冲突,如果你的 Pod 设置了 HostNetwork=true,则 ClusterFirst 就会被强制转换成 Default。

ClusterFirstWithHostNet:如果pod是桥接的模式, dnsPolicy 将设置为ClusterFirstWithHostNet,他将同时解决default和ClusterFirst的DNS解析。

None: 表示会清除 Pod 预设的 DNS 配置,当 dnsPolicy 设置成这个值之后,Kubernetes 不会为 Pod 预先载入任何自身逻辑判断得到的 DNS 配置。因此若要将 dnsPolicy 的值设为 None,为了避免 Pod 里面没有配置任何 DNS,最好再添加 dnsConfig 来描述自定义的 DNS 参数

以下为pod DNS策略为none,然后自定义DNSpod

service/networking/custom-dns.yaml

apiVersion: v1

kind: Pod

metadata:

  namespace: default

  name: dns-example

spec:

  containers:

    - name: test

      image: nginx

  dnsPolicy: "None"

  dnsConfig:

    nameservers:

      - 1.2.3.4

    searches:

      - ns1.svc.cluster.local

      - my.dns.search.suffix

    options:

      - name: ndots

        value: "2"

      - name: edns0

09-kubernetes中的域名解析流程

参考技术A

从Kubernetes 1.11版本开始,Kubernetes集群的DNS服务由CoreDNS提供。CoreDNS是CNCF基金会的一个项目,是用Go语言实现的高性能、插件式、易扩展的DNS服务端。CoreDNS解决了KubeDNS的一些问题,例如dnsmasq的安全漏洞、externalName不能使用stubDomains设置,等等。

CoreDNS支持自定义DNS记录及配置upstream DNS Server,可以统一管理Kubernetes基于服务的内部DNS和数据中心的物理DNS。

CoreDNS没有使用多个容器的架构,只用一个容器便实现了KubeDNS内3个容器的全部功能。

从kubernetes官方提供的 coredns.yml 文件中,不难看出coredns服务配置至少需要一个ConfigMap、一个Deployment和一个Service共3个资源对象。ConfigMap coredns 主要配置文件Corefile的内容:

其中主要有二个地方来解析配置
1、这段配置的意思是cluster.local后缀的域名都是kubernetes内部域名,coredns会监控service的变化来修改域名的记录

2、如果coredns没有找到dns记录,则去找 /etc/resolv.conf 中的 nameserver 解析

接下来使用一个带有nslookup工具的Pod来验证DNS服务能否正常工作:

通过nslookup进行测试。
查找defaul命名空间存在的ng-deploy-80服务

如果某个Service属于不同的命名空间,那么在进行Service查找时,需要补充Namespace的名称,组合成完整的域名。下面以查找kubernetes-dashboard服务为例,

众所周知, DNS 服务器用于将域名转换为 IP (具体为啥要转换建议复习下 7 层网络模型). Linux 服务器中 DNS 解析配置位于 /etc/resolv.conf , 在 Pod 中也不例外,

DNS 策略可以逐个 Pod 来设定。当前kubernetes支持这4中DNS 策略

如果我们不填dnsPolicy, 默认策略就是 ClusterFirst 。
kubelet 在起 pause 容器的时候,会将其 DNS 解析配置初始化成集群内的配置。配置: 它的 nameserver 就是指向 coredns 的

k8s里面有4种DNS策略, 而coredns使用的DNS策略就是Default, 这个策略的意思就是继承宿主机上的/etc/resolve.conf, 所以coredns Pod 里面的/etc/resolve.conf 的内容就是宿主机上的内容。

在集群中 pod 之间互相用 svc name 访问的时候,会根据 resolv.conf 文件的 DNS 配置来解析域名,下面来分析具体的过程。

pod 的 resolv.conf 文件主要有三个部分,分别为 nameserver、search 和 option。而这三个部分可以由 K8s 指定,也可以通过 pod.spec.dnsConfig 字段自定义。
nameserver
resolv.conf 文件的第一行 nameserver 指定的是 DNS 服务的 IP,这里就是 coreDNS 的
clusterIP:

也就是说所有域名的解析,都要经过coreDNS的虚拟IP 10.100.0.2 进行解析, 不论是内部域还是外部域名。

search 域

resolv.conf 文件的第二行指定的是 DNS search 域。解析域名的时候,将要访问的域名依次带入 search 域,进行 DNS 查询。

比如我要在刚才那个 pod 中访问一个域名为 ng-deploy-80的服务,其进行的 DNS 域名查询的顺序是:

options

resolv.conf 文件的第三行指定的是其他项,最常见的是 dnots。dnots 指的是如果查询的域名包含的点 “.” 小于 5,则先走 search 域,再用绝对域名;如果查询的域名包含点数大于或等于 5,则先用绝对域名,再走 search 域。K8s 中默认的配置是 5。

也就是说,如果我访问的是 a.b.c.e.f.g ,那么域名查找的顺序如下:

通过 svc 访问

在 K8s 中,Pod 之间通过 svc 访问的时候,会经过 DNS 域名解析,再拿到 ip 通信。而 K8s 的域名全称为 "<service-name>.<namespace>.svc.cluster.local",而我们通常只需将 svc name 当成域名就能访问到 pod,这一点通过上面的域名解析过程并不难理解。

参考
(1)K8S落地实践 之 服务发现(CoreDNS)
https://blog.51cto.com/u_12965094/2641238
(2)自定义 DNS 服务
https://kubernetes.io/zh/docs/tasks/administer-cluster/dns-custom-nameservers/
(3)Kubernetes 服务发现之 coreDNS
https://juejin.cn/post/6844903965520297991
(4)Kubernetes 集群 DNS 服务发现原理
https://developer.aliyun.com/article/779121
(5)Kubernetes之服务发现和域名解析过程分析
https://www.jianshu.com/p/80ad7ff37744

以上是关于Kubernetes DNS支持的主要内容,如果未能解决你的问题,请参考以下文章

每天5分钟玩转Kubernetes | DNS访问Service

Kubernetes 部署集群内部DNS服务

Kubernetes addons 之 coredns部署

Kubernetes:*** 服务器和 DNS 问题

如何配置kubernetes dns

Kubernetes 中的 NGINX 无法解析 DNS