Kubernetes内部域名解析的那些事儿
<h1>前言</h1><p> 在kubernets环境中,服务发现大都是基于内部域名的方式。那么就涉及到内部域名的解析。从1.11版本开始,kubeadm已经使用第三方的CoreDNS替换官方的kubedns作为集群内部域名的解析组件。</p>
<h1>kubernets中的4种DNS策略</h1>
<h2>None</h2>
<p>表示空的DNS设置,这种方式一般用于想要自定义 DNS 配置的场景,往往需要和 dnsConfig 配合一起使用达到自定义 DNS 的目的。</p>
<h2>Default</h2>
<p>此种方式是让kubelet来决定使用何种DNS策略。而kubelet默认的方式,就是使用宿主机的/etc/resolv.conf文件。</p>
<p>同时,kubelet也可以配置指定的DNS策略文件,使用kubelet参数即可,如:–resolv-conf=/etc/resolv.conf</p>
<h2>ClusterFirst</h2>
<p>此种方式是使用kubernets集群内部中的kubedns或coredns服务进行域名解析。若解析不成功,才会使用宿主机的DNS配置来进行解析。</p>
<h2>ClusterFistWithHostNet</h2>
<p>在某些场景下,我们的 POD 是用 HOST 模式启动的(HOST模式,是共享宿主机网络的),一旦用 HOST 模式,表示这个 POD 中的所有容器,都要使用宿主机的 /etc/resolv.conf 配置进行DNS查询,但如果你想使用了 HOST 模式,还继续使用 Kubernetes 的DNS服务,那就将 dnsPolicy 设置为 ClusterFirstWithHostNet。</p>
<h2>策略配置示例</h2>
<p>DNS策略,需要在Pod,或者Deployment、RC等资源中,设置 dnsPolicy 即可,以 Pod 为例:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">apiVersion: v1
kind: Pod
metadata:
labels:
name: cadvisor</span>-<span style="color: rgba(0, 0, 0, 1)">nodexxxx
hostip: </span><span style="color: rgba(128, 0, 128, 1)">192.168</span><span style="color: rgba(0, 0, 0, 1)">.x.x
name: cadvisor</span>-<span style="color: rgba(0, 0, 0, 1)">nodexxxx
namespace: monitoring
spec:
containers:
</span>-<span style="color: rgba(0, 0, 0, 1)"> args:
</span>- --<span style="color: rgba(0, 0, 0, 1)">profiling
</span>- --housekeeping_interval=<span style="color: rgba(0, 0, 0, 1)">10s
</span>- --storage_duration=<span style="color: rgba(0, 0, 0, 1)">1m0s
image: google</span>/<span style="color: rgba(0, 0, 0, 1)">cadvisor:latest
name: cadvisor</span>-<span style="color: rgba(0, 0, 0, 1)">nodexxxx
ports:
</span>- containerPort: <span style="color: rgba(128, 0, 128, 1)">8080</span><span style="color: rgba(0, 0, 0, 1)">
name: http
protocol: TCP
resources: {}
securityContext:
privileged: </span><span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">
terminationMessagePath: </span>/dev/termination-<span style="color: rgba(0, 0, 0, 1)">log
terminationMessagePolicy: File
dnsPolicy: ClusterFirst
nodeName: nodexxxx</span></pre>
</div>
<h1>kubernets中域名解析流程</h1>
<p># Pod中的resolv.conf的解析配置</p>
<p># kubectl exec -it nginx-deploy-5754944d6c-dtzpj cat /etc/resolv.conf</p>
<div class="cnblogs_code">
<pre>nameserver <span style="color: rgba(128, 0, 128, 1)">10.96</span>.<span style="color: rgba(128, 0, 128, 1)">0.2</span><span style="color: rgba(0, 0, 0, 1)">
search default.svc.cluster.local svc.cluster.local cluster.local
options ndots:</span><span style="color: rgba(128, 0, 128, 1)">5</span></pre>
</div>
<p># kubectl get svc -n kube-system |grep dns</p>
<div class="cnblogs_code">
<pre>kube-dns ClusterIP<span style="color: rgba(128, 0, 128, 1)">10.96</span>.<span style="color: rgba(128, 0, 128, 1)">0.2</span> <none> <span style="color: rgba(128, 0, 128, 1)">53</span>/UDP,<span style="color: rgba(128, 0, 128, 1)">53</span>/TCP,<span style="color: rgba(128, 0, 128, 1)">9153</span>/TCP 158d</pre>
</div>
<p>a)文件中配置的 nameserver 一般是k8s集群内部的dns服务的ClusterIP,无法ping,但是可以访问。</p>
<p>b)意味着集群Pod内部的所有域名的解析,都要经过kubedns的虚拟ip 10.96.0.2 进行解析。</p>
<p>c)resolv.conf中search域分别是default.svc.cluster.local svc.cluster.local cluster.local,在kubernets中,域名的全称必须是 service-name.namespace.svc.cluster.local 。</p>
<p>d)假如集群中有一个svc(Service)名为a,在某个Pod中执行命令 curl a 时,在此Pod中会根据/etc/resolv.conf进行解析流程。选择nameserver 10.96.0.2进行解析,将字符串'a'带入到/etc/resolv.conf文件中不同的search域,依次进行查找,如下:</p>
<p>a.default.svc.cluster.local -> a.svc.cluster.local -> a.cluster.local</p>
<p>先查找 a.default.svc.cluster.local ,若找不到,则再查找 a.svc.cluster.local ,依次往下进行,直到找到为止。</p>
<h1>curl效率分析</h1>
<p>在集群中若存在一个名为a的svc,在Pod中curl a和curl a.default都能实现请求,那么两种方式哪个的效率高呢?</p>
<p>那肯定是curl a啦,因为发起此请求时,通过/etc/resolv.conf中第一列的search域就能直接找到 a.default.svc.cluster.local ,直接避免了下一级的查找。</p>
<h1>容器中访问外部域名讲述</h1>
<p>下文将通过示例说明Pod访问外部域名时发起的相应的请求信息。</p>
<p>以请求baidu.com为例,因为DNS容器一般不具备bash,所以无法通过docker exec的方式进入容器抓包,所以此处采用 进入到DNS容器的网络中(不是发起DNS请求的容器)的姿势去抓包,抓包姿势准备好后,同时在某容器中访问baidu.com,即可看到在进行的DNS查找的过程中都产生了什么样的数据包。</p>
<p> </p>
<p><span style="color: rgba(255, 0, 0, 1)">### 实操 </span></p>
<p><span style="color: rgba(0, 112, 192, 1)"># 进入dns容器网络,准备好抓包姿势 </span></p>
<p># 查看Pod所在具体的node节点</p>
<p># kubectl get pods -n kube-system -o wide|grep dns</p>
<div class="cnblogs_code">
<pre>coredns-5c48579f88-8wprg<span style="color: rgba(128, 0, 128, 1)">1</span>/<span style="color: rgba(128, 0, 128, 1)">1</span> Running<span style="color: rgba(128, 0, 128, 1)">16</span> 30d <span style="color: rgba(128, 0, 128, 1)">10.244</span>.<span style="color: rgba(128, 0, 128, 1)">4.120</span><span style="color: rgba(0, 0, 0, 1)"> node1
coredns</span>-5c48579f88-rsnpr <span style="color: rgba(128, 0, 128, 1)">1</span>/<span style="color: rgba(128, 0, 128, 1)">1</span> Running <span style="color: rgba(128, 0, 128, 1)">0</span> 30d <span style="color: rgba(128, 0, 128, 1)">10.244</span>.<span style="color: rgba(128, 0, 128, 1)">5.142</span> node2</pre>
</div>
<p><span style="color: rgba(0, 112, 192, 1)"># 这里以node1上的容器为操作对象,所以到node1节点上进行操作 </span></p>
<p># 找到容器并打印对应的NS ID</p>
<p># docker ps |grep dns</p>
<div class="cnblogs_code">
<pre>a964bbb43534 c0f6e815079e <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">/coredns -conf /etc…</span><span style="color: rgba(128, 0, 0, 1)">"</span> <span style="color: rgba(128, 0, 128, 1)">2</span> days ago Up <span style="color: rgba(128, 0, 128, 1)">2</span> days k8s_coredns_coredns-5c48579f88-8wprg_kube-system_b1e7f3c3-98eb-<span style="color: rgba(128, 0, 128, 1)">4843</span>-b156-<span style="color: rgba(0, 0, 0, 1)">1d203f98bd74_16
fbd12d2f9c7c k8s.gcr.io</span>/pause:<span style="color: rgba(128, 0, 128, 1)">3.1</span> <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">/pause</span><span style="color: rgba(128, 0, 0, 1)">"</span> <span style="color: rgba(128, 0, 128, 1)">5</span> days ago Up <span style="color: rgba(128, 0, 128, 1)">5</span> days k8s_POD_coredns-5c48579f88-8wprg_kube-system_b1e7f3c3-98eb-<span style="color: rgba(128, 0, 128, 1)">4843</span>-b156-1d203f98bd74_3</pre>
</div>
<p># docker inspect --format "{{.State.Pid}}" a964bbb43534</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(128, 0, 128, 1)">21617</span></pre>
</div>
<p># 进入此容器的网络Namespace</p>
<p># nsenter -n -t 21617</p>
<p># 抓包姿势就绪</p>
<p># tcpdump -i eth0 udp dst port 53|grep 'baidu.com'</p>
<p> </p>
<p><span style="color: rgba(0, 112, 192, 1)"># 在另外的某容器中,进行域名查找操作 </span></p>
<p><span style="color: rgba(255, 0, 0, 1)">说明:</span>一般pod中没有nslookup命令,故需要手动安装,根据不同环境自选以下操作。</p>
<p><strong>### Centos </strong></p>
<p>]# cat /etc/redhat-release</p>
<p>CentOS Linux release 7.5.1804 (Core)</p>
<p>]# yum -y install bind-utils</p>
<p><strong>### Debian </strong></p>
<p># cat /etc/issue</p>
<p>Debian GNU/Linux 9</p>
<p># apt-get install dnsutils -y</p>
<p>root@jenkins-7d66bf7977-cm4x4:~# nslookup baidu.com 10.244.4.120</p>
<p> </p>
<p><span style="color: rgba(255, 0, 0, 1)">注意</span>:10.244.4.120是node1上的dns pod在kubernets集群中的内部通信ip地址。因为环境中有两个dns pod,将其指定要单个具体的容器,能够使抓包数据完整。</p>
<p> </p>
<p><span style="color: rgba(0, 112, 192, 1)"># 随后,在前面就绪的抓包姿势窗口就能看到数据包的出现 </span></p>
<p># tcpdump -i eth0 udp dst port 53|grep 'baidu.com'</p>
<div class="cnblogs_code">
<pre>tcpdump: verbose output suppressed, use -v or -vv <span style="color: rgba(0, 0, 255, 1)">for</span><span style="color: rgba(0, 0, 0, 1)"> full protocol decode
listening on eth0, link</span>-type EN10MB (Ethernet), capture size <span style="color: rgba(128, 0, 128, 1)">262144</span><span style="color: rgba(0, 0, 0, 1)"> bytes
</span><span style="color: rgba(128, 0, 128, 1)">16</span>:<span style="color: rgba(128, 0, 128, 1)">57</span>:<span style="color: rgba(128, 0, 128, 1)">50.791154</span> IP <span style="color: rgba(128, 0, 128, 1)">10.244</span>.<span style="color: rgba(128, 0, 128, 1)">4.127</span>.<span style="color: rgba(128, 0, 128, 1)">51794</span> > node1.domain: <span style="color: rgba(128, 0, 128, 1)">55406</span>+ A? baidu.com.infra.svc.cluster.local. (<span style="color: rgba(128, 0, 128, 1)">51</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(128, 0, 128, 1)">16</span>:<span style="color: rgba(128, 0, 128, 1)">57</span>:<span style="color: rgba(128, 0, 128, 1)">50.792540</span> IP <span style="color: rgba(128, 0, 128, 1)">10.244</span>.<span style="color: rgba(128, 0, 128, 1)">4.127</span>.<span style="color: rgba(128, 0, 128, 1)">56306</span> > node1.domain: <span style="color: rgba(128, 0, 128, 1)">27958</span>+ A? baidu.com.svc.cluster.local. (<span style="color: rgba(128, 0, 128, 1)">45</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(128, 0, 128, 1)">16</span>:<span style="color: rgba(128, 0, 128, 1)">57</span>:<span style="color: rgba(128, 0, 128, 1)">50.793439</span> IP <span style="color: rgba(128, 0, 128, 1)">10.244</span>.<span style="color: rgba(128, 0, 128, 1)">4.127</span>.<span style="color: rgba(128, 0, 128, 1)">59799</span> > node1.domain: <span style="color: rgba(128, 0, 128, 1)">27048</span>+ A? baidu.com.cluster.local. (<span style="color: rgba(128, 0, 128, 1)">41</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(128, 0, 128, 1)">16</span>:<span style="color: rgba(128, 0, 128, 1)">57</span>:<span style="color: rgba(128, 0, 128, 1)">50.799463</span> IP <span style="color: rgba(128, 0, 128, 1)">10.244</span>.<span style="color: rgba(128, 0, 128, 1)">4.127</span>.<span style="color: rgba(128, 0, 128, 1)">39116</span> > node1.domain: <span style="color: rgba(128, 0, 128, 1)">2303</span>+ A? baidu.com. (<span style="color: rgba(128, 0, 128, 1)">27</span>)</pre>
</div>
<p><span style="color: rgba(255, 0, 0, 1)">说明: </span></p>
<p>a)数据包中显示的 infra 是执行nslookup的pod的NameSpace;</p>
<p>b)根据数据显示,在真正解析到 baidu.com 之前,经历了baidu.com.infra.svc.cluster.local. > baidu.com.svc.cluster.local. > baidu.com.cluster.local. 三次DNS请求。</p>
<h1>请求浪费的原因</h1>
<p>上文在正确请求到baidu.com之前,有过三次无效请求,即意味着请求浪费,那为什么会出现那种情况呢,请继续往下看。</p>
<p> </p>
<p># Pod中的resolv.conf的解析配置</p>
<div class="cnblogs_code">
<pre>root@jenkins-7d66bf7977-cm4x4:/# <span style="color: rgba(0, 0, 255, 1)">cat</span> /etc/<span style="color: rgba(0, 0, 0, 1)">resolv.conf
nameserver </span><span style="color: rgba(128, 0, 128, 1)">10.96</span>.<span style="color: rgba(128, 0, 128, 1)">0.2</span><span style="color: rgba(0, 0, 0, 1)">
search infra.svc.cluster.local svc.cluster.local cluster.local host.com
options ndots:</span><span style="color: rgba(128, 0, 128, 1)">5</span></pre>
</div>
<p> </p>
<p><span style="color: rgba(255, 0, 0, 1)"># options ndots:5 解释 </span></p>
<p>如果查询的域名包含的点".",不到5个,那么进行DNS查找,将使用非完全限定名称(或者叫绝对域名),如果你查询的域名包含点数大于等于5,那么DNS查询,默认会使用绝对域名进行查询。</p>
<p>如果我们请求的域名是,a.b.c.d.e,这个域名中有4个点,那么容器中进行DNS请求时,会使用非绝对域名进行查找,使用非绝对域名,会按照 /etc/resolv.conf 中的 search 域,走一遍追加匹配:</p>
<p>a.b.c.d.e.cicd.svc.cluster.local. -></p>
<p>a.b.c.d.e.svc.cluster.local. -></p>
<p>a.b.c.d.e.cluster.local.</p>
<p>直到找到为止。如果走完了search域还找不到,则使用 a.b.c.d.e. ,作为绝对域名进行DNS查找。</p>
<p> </p>
<p><span style="color: rgba(255, 0, 0, 1)">说明: </span></p>
<p>a)请求域名中点数少于5个时,先走search域,最后将其视为绝对域名进行查询;</p>
<p>b)请求域名中点数大于等于5个时,直接视为绝对域名进行查找,只有当查询不到的时候,才继续走 search 域。</p>
<h1>优化请求浪费</h1>
<h2>使用全限定域名</h2>
<p>当访问某域名时,以 '.' 为后缀,即使用 完全限定域名(绝对域名),这样发起的域名请求时将不会走search域进行匹配,而是直接使用整个原始域名字符串为个体进行解析。</p>
<p> </p>
<p>如:</p>
<p>nslookup baidu.com<span style="color: rgba(255, 0, 0, 1)"><strong>.</strong></span></p>
<h2>配置特定ndots</h2>
<p>在kubernets中,ndots值默认是5。是因为,Kubernetes 认为,内部域名,最长为5,要保证内部域名的请求,优先走集群内部的DNS,而不是将内部域名的DNS解析请求,有打到外网的机会,Kubernetes 设置 ndots 为5是一个比较合理的行为。</p>
<p>如果有特定业务需求,也可配置ndots,如下:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">apiVersion: v1
kind: Pod
metadata:
namespace: default
name: dns</span>-<span style="color: rgba(0, 0, 0, 1)">example
spec:
containers:
</span>-<span style="color: rgba(0, 0, 0, 1)"> name: test
image: nginx
dnsConfig:
options:
</span>-<span style="color: rgba(0, 0, 0, 1)"> name: ndots
value: </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">1</span><span style="color: rgba(128, 0, 0, 1)">"</span></pre>
</div>
</div>
<div id="MySignature" role="contentinfo">
<p>========================================</p>
<div>
作者:罗穆瑞
</div>
<div>
出处:http://www.cnblogs.com/kazihuo/
</div>
<p>转载请保留此段声明,且在文章页面明显位置给出原文链接,谢谢!</p>
<p>==============================================================================</p>
<p>^_^ 如果觉得这篇文章对你有小小的帮助的话,记得在右下角点个<span class="red">“推荐”</span>哦,您的<span class="red">“推荐”</span>将是我最大的写作动力 ^_^</p>
<p>==============================================================================</p><br><br>
来源:https://www.cnblogs.com/kazihuo/p/13071242.html
頁:
[1]