基于Docker提供内置的DNS服务器

2023-08-08

DNS简介,DNS服务是域名系统的缩写, 英文全称:Domain Name System,将域名和IP地址相互映射。在容器环境中,DNS至关重要,例如在Kubernetes集群中,通常一组Pod由一个Service负载,但是Service的IP地址有可能需要变动,那么就可以让Pod通过域名的方式去访问Service,Pod无需理会IP地址的变化。
Docker DNS,Docker link,Docker link是一个遗留的特性,在新版本的Docker中,一般不推荐使用。简单来说Docker link就是把两个容器连接起来,容器可以使用容器名进行通信,而不需要依赖ip地址(其实就是在容器的/etc/hosts文件添加了host记录,原本容器之间的IP就是通的,只是我们增加了host记录,可以不用IP去访问),创建容器centos-1>
创建容器centos-2,使用--link name:alias,name就是要访问的目标机器,alias就是自定义的别名。
查看容器centos-2的/etc/hosts文件>
意味着centos-2可以用centos-1-alias,9dde6339057a,centos-1来访问原先创建的容器。centos-1是不可以通过hostname访问centos-2的。
Embedded DNS,从Docker 1.10开始,Docker提供了一个内置的DNS服务器,当创建的容器属于自定义网络时,容器的/etc/resolv.conf会使用内置的DNS服务器(地址永远是127.0.0.11)来解析相同自定义网络内的其他容器。
基于Docker提供内置的DNS服务器 (https://ic.work/) 可编辑器件 第1张
为了向后兼容,default bridge网络的DNS配置没有改变,默认的docker网络使用的是宿主机的/etc/resolv.conf的配置。
创建一个自定义网络>
分别创建两个容器属于自定义网络my-network中>
查看容器centos-4的/etc/hosts和/etc/resolv.conf,可以看到nameserver添加的IP为127.0.0.11的Embedded DNS>
此时centos-3和centos-4可以互相解析>
Docker DNS配置,方式一:docker run (针对单个容器),方式二:daemon.json,nameserver只针对docker默认网络所有容器,dns-search和dns-opts针对所有网络容器。
Kubernetes DNS,基于Docker提供内置的DNS服务器 (https://ic.work/) 可编辑器件 第2张
在kubernetes中,有以下4中DNS策略,可以通过dnsPolicy指定>
Default: Pod从运行所在的节点继承名称解析配置,就是该 Pod 的 DNS 配置会跟宿主机完全一致。。Default 不是默认的 DNS 策略。如果未明确指定dnsPolicy,则使用 ClusterFirst。
ClusterFirst: 它会预先把 kube-dns(或 CoreDNS)的信息当作预设参数写入到该 Pod 内的 DNS 配置。不过ClusterFirst 还有一个冲突,如果你的 Pod 设置了 HostNetwork=true,则 ClusterFirst 就会被强制转换成 Default。
ClusterFirstWithHostNet: 对于与 hostNetwork(网络接口使用的是宿主机的) 一起运行的 Pod,应显式设置其DNS策略 ClusterFirstWithHostNet,他将同时解决default和ClusterFirst的DNS解析。如果不加上dnsPolicy: ClusterFirstWithHostNet,Pod默认使用所在宿主主机使用的DNS,这样也会导致容器内不能通过service name 访问k8s集群中其他Pod。
None: 表示会清除 Pod 预设的 DNS 配置,当 dnsPolicy 设置成这个值之后,Kubernetes 不会为 Pod 预先载入任何自身逻辑判断得到的 DNS 配置。因此若要将 dnsPolicy 的值设为 None,为了避免 Pod 里面没有配置任何 DNS参数,至少需要在dnsConfig中设置nameservers的参数。
在 Kubernetes 1.11 及其以后版本中,推荐使用 CoreDNS, kubeadm 默认会安装 CoreDNS。当Pod向CoreDNS发起DNS解析请求时,CoreDNS先会自己尝试解析,如果无法解析该域名,会将DNS请求交给CoreDNS的Pod所在的宿主机,让宿主机尝试解析。
本次实验kubernetes集群中coredns service的地址是10.247.3.10。
宿主机的/etc/resolv.conf文件如下>
CluterFirst,CluterFirst是kubernetes集群中默认的DNS策略,这里是一个普通的Pod yaml文件,没有指定dnsPolicy。
创建Pod后,进入该Pod查看/etc/resolv.conf配置,可以看到nameserver为CoreDNS的service的地址。
如果在Pod的yaml文件中指定了DNS参数,会和默认的ClusterFirst的配置叠加>
Default,dnsPolicy为Default模式时,Pod使用的是宿主机的DNS配置>
ClusterFirstWithHostNet,当Pod使用了hostNetwork模式时,Pod使用的是宿主机的网卡>
当Pod使用hostNetwork模式,并且未指定dnsPolicy为ClusterFirstWithHostNet时,Pod会使用的宿主机的DNS:,此时Pod无法通过域名访问Kubernetes集群内部>
如果Pod在hostNetwork模式下要通过域名的方式访问kubernetes集群内的服务,需要指定dnsPolicy为ClusterFirstWithHostNet>
此时查看Pod的DNS配置,可以看到nameserver使用的是CoreDNS:,None,当设置dnsPolicy为None时,不会使用Kubernetes集群和宿主机的 DNS 策略,但是必须自己配置dnsConfig。
StatefulSet 和 Service,StatefulSet Pod 具有唯一的标识,该标识包括顺序标识、稳定的网络标识和稳定的存储。该标识和 Pod 是绑定的,不管它被调度在哪个节点上。
StatefulSet 中的每个 Pod 根据 StatefulSet 的名称和 Pod 的序号派生出它的主机名。组合主机名的格式为$(StatefulSet 名称)-$(序号)。下例将会创建三个名称分别为web-0、web-1、web-2的 Pod。StatefulSet 可以使用 Headless Service(无头服务)控制它的 Pod 的网络域。管理域的这个服务的格式为:$(服务名称).$(命名空间).svc.cluster.local,其中cluster.local是集群域。一旦每个 Pod 创建成功,就会得到一个匹配的 DNS 子域,格式为:$(pod 名称).$(所属服务的 DNS 域名),其中所属服务由 StatefulSet 的serviceName域来设定。
基于Docker提供内置的DNS服务器 (https://ic.work/) 可编辑器件 第3张
通过域名去访问Headless Service负载的Pod是不走iptables的,通过域名去访问ClusterIP负载的Pod要走Iptables。
下面给出一些选择集群域、服务名、StatefulSet 名、及其怎样影响 StatefulSet 的 Pod 上的 DNS 名称的示例>
Headless Service,首先我们将StatefulSet和Headless Service结合使用,(通常情况下是这么做的)>
查看创建的StatefulSet的Pod,命名是有规律的按照0,1,2的顺序递增。
查看创建的Headless Service,可以看到ClusterIP为None>
找一个相同namespace的Pod来解析该Headless Service>
查看default命名空间下的Pod的/etc/resolv.conf配置>
在不同的 namespace 下的 Pod 通过 Service 访问的时候,需要在 Service name 后面加上 .。名字>
查看kube-system命名空间下的Pod的/etc/resolv.conf配置>
ClusterIP Service,现在我们将StatefulSet和ClusterIP Service结合使用>
查看创建的Service>
此时用Pod解析域名只能得到ClusterIP地址,无法得到Pod的IP地址>
Pod 的 hostname 与 subdomain,在 Kubernetes 中,如果不指定 Pod 的 hostname,其默认为 pod.metadata.name,通过 spec.hostname 字段可以自定义;另外还可以给 Pod 设置 subdomain,通过 spec.subdomain 字段。比如下面这个例子>
创建一个Nginx Pod,指定Pod的hostname和subdomain>
可以查看这个 Pod 的 hostname 和 hosts 文件>
在 busybox 容器中通过域名访问这个Pod>

文章推荐

相关推荐