【容器】K8s容器内部dns解析慢解决方案

4 篇文章 0 订阅
4 篇文章 0 订阅

需求&背景

K8s内,要对做内部域名解析的劫持,解析 *.lol.com 至 172.34.18.12。
通过在coredns的配置文件配置 *.lol.com 的泛域名解析(如下所示),能够解析成功。但是在容器内部解析公网/内部地址慢。正常的http请求花费5-6秒。

template IN A lol.com {
  match .*\.lol\.com
  answer "{{ .Name }} 60 IN A 172.34.18.12"
  fallthrough
}

在这里插入图片描述

问题解决

DNS解析慢可能出现的问题在解析链路的各个环节。我们按照解析的路径逐步排查。在K8s内部从发起解析的设备,到K8s的DNS服务(coredns)。

1)在需要解析域名的容器抓包

首先在需要解析域名的容器内抓包,在容器所在宿主机执行以下步骤。
通过describe命令获取到Pod内的container-id

kubectl describe [po]

获取进程pid

docker inspect -f {{.State.Pid}} [container-id]

使用nsenter进入pid命名空间

nsenter -n -t [pid]

抓包53(dns解析使用)端口的流量,并记录timestamp

tcpdump -n -tt -i eth0 port 53
1654670942.436773 IP 11.5.0.87.59372 > 11.6.0.10.domain: 54304+ A? myfoo.lol.com.my-services.svc.cluster.local. (62)
1654670942.439162 IP 11.6.0.10.domain > 11.5.0.87.59372: 54304 NXDomain*- 0/1/0 (155)
1654670942.439269 IP 11.5.0.87.35180 > 11.6.0.10.domain: 1677+ A? myfoo.lol.com.svc.cluster.local. (50)
1654670942.439900 IP 11.6.0.10.domain > 11.5.0.87.35180: 1677 NXDomain*- 0/1/0 (143)
1654670942.440105 IP 11.5.0.87.40185 > 11.6.0.10.domain: 56859+ A? myfoo.lol.com.cluster.local. (46)
1654670942.441976 IP 11.6.0.10.domain > 11.5.0.87.40185: 56859 NXDomain*- 0/1/0 (139)
1654670942.442056 IP 11.5.0.87.43673 > 11.6.0.10.domain: 52888+ A? myfoo.lol.com.localdomain. (44)
1654670944.443202 IP 11.6.0.10.domain > 11.5.0.87.43673: 52888 ServFail- 0/0/0 (44)
1654670944.443329 IP 11.5.0.87.58234 > 11.6.0.10.domain: 52888+ A? myfoo.lol.com.localdomain. (44)
1654670946.444789 IP 11.6.0.10.domain > 11.5.0.87.58234: 52888 ServFail- 0/0/0 (44)
1654670946.444929 IP 11.5.0.87.59003 > 11.6.0.10.domain: 46828+ A? myfoo.lol.com. (32)
1654670946.445715 IP 11.6.0.10.domain > 11.5.0.87.59003: 46828*- 1/0/0 A 172.34.18.12 (62)
1654670946.448576 IP 11.5.0.87.52708 > 11.6.0.10.domain: 58584+ PTR? 12.18.34.172.in-addr.arpa. (43)
1654670948.449842 IP 11.6.0.10.domain > 11.5.0.87.52708: 58584 ServFail- 0/0/0 (43)
1654670948.450019 IP 11.5.0.87.52435 > 11.6.0.10.domain: 58584+ PTR? 12.18.34.172.in-addr.arpa. (43)
1654670950.451448 IP 11.6.0.10.domain > 11.5.0.87.52435: 58584 ServFail- 0/0/0 (43)

以上 11.5.0.87 是业务pod本身ip,11.6.0.10 是coredns svc 的ip。
以上的抓包结果显示 从11.5.0.87 发起dns解析请求至11.6.0.10。11.6.0.10 返回解析后的dns记录
最左边的timestamp显示1654670942 - 1654670946 相差有8秒
从日志看经历了 myfoo.lol.com.my-services.svc.cluster.local. 到 myfoo.lol.com. 最终解析出172.34.18.12的解析过程。
以上日志表明两点:
1.解析过程带了不同的域。
2.从容器内发起的解析请求指向11.6.0.10

coredns 日志

[ERROR] plugin/errors: 2 giaoxa.lol.com.localdomain. A: read udp 11.5.2.154:40494->114.114.114.114:53: i/o timeout
[ERROR] plugin/errors: 2 12.18.34.172.in-addr.arpa. PTR: read udp 11.5.2.154:38740->114.114.114.114:53: i/o timeout
[ERROR] plugin/errors: 2 12.18.34.172.in-addr.arpa. PTR: read udp 11.5.2.154:44143->114.114.114.114:53: i/o timeout

以上日志中,11.5.2.154是coredns Pod的ip。可以看到和 *.lol.com 相关的请求是 i/o timeout,而且114.114.114.114没有给返回,说明尝试通过114.114.114.114对域名进行解析是失败的

抓包coredns所在宿主机

tcpdump -n -tt -i eth0 port 53

1654681471.359635 IP 172.34.57.8.40494 > 114.114.114.114.domain: 1584+ A? giaoxa.lol.com.localdomain. (45)
1654681471.609660 IP 172.34.57.8.36977 > 114.114.114.114.domain: 5934+ AAAA? alauda.cn.localdomain. (39)
1654681471.609671 IP 172.34.57.8.52810 > 114.114.114.114.domain: 1473+ A? alauda.cn.localdomain. (39)
1654681471.624745 IP 172.34.57.8.39735 > 114.114.114.114.domain: 7872+ AAAA? alauda.cn. (27)
1654681471.624758 IP 172.34.57.8.40497 > 114.114.114.114.domain: 59218+ A? alauda.cn. (27)
1654681472.216579 IP 172.34.57.8.42082 > 114.114.114.114.domain: 53658+ A? alauda.cn. (27)
1654681472.216589 IP 172.34.57.8.33765 > 114.114.114.114.domain: 11138+ AAAA? alauda.cn. (27)
1654681472.321413 IP 172.34.57.8.59460 > 114.114.114.114.domain: 56340+ NS? . (17)
1654681472.569026 IP 172.34.57.8.55787 > 114.114.114.114.domain: 33954+ NS? . (17)
1654681473.233810 IP 172.34.57.8.39542 > 114.114.114.114.domain: 24956+ AAAA? alauda.cn.localdomain. (39)
1654681473.233819 IP 172.34.57.8.54779 > 114.114.114.114.domain: 64571+ A? alauda.cn.localdomain. (39)
1654681473.361569 IP 172.34.57.8.56071 > 114.114.114.114.domain: 1584+ A? giaoxa.lol.com.localdomain. (45)
1654681473.611310 IP 172.34.57.8.38455 > 114.114.114.114.domain: 27253+ A? alauda.cn.localdomain. (39)
1654681473.611342 IP 172.34.57.8.53131 > 114.114.114.114.domain: 31824+ AAAA? alauda.cn.localdomain. (39)
1654681473.784304 IP 172.34.57.8.48873 > 114.114.114.114.domain: 13483+ NS? . (17)
1654681474.032091 IP 172.34.57.8.39103 > 114.114.114.114.domain: 34671+ NS? . (17)
1654681474.217868 IP 172.34.57.8.37204 > 114.114.114.114.domain: 6801+ AAAA? alauda.cn. (27)
1654681474.217878 IP 172.34.57.8.40697 > 114.114.114.114.domain: 65501+ A? alauda.cn. (27)
1654681475.235208 IP 172.34.57.8.57250 > 114.114.114.114.domain: 48387+ A? alauda.cn.localdomain. (39)
1654681475.235219 IP 172.34.57.8.34787 > 114.114.114.114.domain: 50884+ AAAA? alauda.cn.localdomain. (39)
1654681475.247316 IP 172.34.57.8.52486 > 114.114.114.114.domain: 54567+ NS? . (17)
1654681475.366260 IP 172.34.57.8.38740 > 114.114.114.114.domain: 16503+ PTR? 12.18.34.172.in-addr.arpa. (43)
1654681475.494900 IP 172.34.57.8.49735 > 114.114.114.114.domain: 41610+ NS? . (17)
1654681475.613035 IP 172.34.57.8.54194 > 114.114.114.114.domain: 27016+ AAAA? alauda.cn. (27)
1654681475.613049 IP 172.34.57.8.47105 > 114.114.114.114.domain: 36162+ A? alauda.cn. (27)
1654681476.710241 IP 172.34.57.8.57710 > 114.114.114.114.domain: 24258+ NS? . (17)
1654681476.957868 IP 172.34.57.8.51551 > 114.114.114.114.domain: 14591+ NS? . (17)
1654681477.237061 IP 172.34.57.8.42955 > 114.114.114.114.domain: 13195+ A? alauda.cn. (27)
1654681477.237085 IP 172.34.57.8.42017 > 114.114.114.114.domain: 62057+ AAAA? alauda.cn. (27)
1654681477.368084 IP 172.34.57.8.44143 > 114.114.114.114.domain: 16503+ PTR? 12.18.34.172.in-addr.arpa. (43)

以上日志是从宿主机172.34.57.8 发送到域名解析服务器 114.114.114.114,可以看到都是
172.34.57.8 -> 114.114.114.114, 没有返回。

解决

改ndots

nameserver 11.6.0.10
search my-services.svc.cluster.local svc.cluster.local cluster.local localdomain
options ndots:5

以上是容器内部的 /etc/resolv.conf
ndots:通俗一点说,如果你的域名请求参数中,点的个数比配置的ndots小,则会按照配置的search内容,依次添加相应的后缀直到获取到域名解析后的地址。如果通过添加了search之后还是找不到域名,则会按照一开始请求的域名进行解析。
我们发现在容器抓包的记录中做了以下域名解析:

  1. myfoo.lol.com.my-services.svc.cluster.local
  2. myfoo.lol.com.svc.cluster.local.
  3. myfoo.lol.com.cluster.local.
  4. myfoo.lol.com.localdomain.
  5. myfoo.lol.com.

直到myfoo.lol.com 才解析出来,说明以上1-4都是无用解析。我们更改ndots配置,略过这些解析步骤即可。如下设置ndots

nameserver 11.6.0.10
search my-services.svc.cluster.local svc.cluster.local cluster.local localdomain
options ndots:1
listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
1654686042.988636 IP 11.5.0.87.53253 > 11.6.0.10.domain: 27170+ A? giaoxa.lol.com. (33)
1654686042.990862 IP 11.6.0.10.domain > 11.5.0.87.53253: 27170*- 1/0/0 A 172.34.18.12 (64)
1654686042.992319 IP 11.5.0.87.49080 > 11.6.0.10.domain: 15523+ PTR? 12.18.34.172.in-addr.arpa. (43)
1654686042.992980 IP 11.6.0.10.domain > 11.5.0.87.49080: 15523 ServFail- 0/0/0 (43)
1654686042.993054 IP 11.5.0.87.49690 > 11.6.0.10.domain: 15523+ PTR? 12.18.34.172.in-addr.arpa. (43)
1654686042.994753 IP 11.6.0.10.domain > 11.5.0.87.49690: 15523 ServFail- 0/0/0 (43)

以上抓包记录显示是直接从giaoxa.lol.com开始解析的,只会经历一次114.114.114.114超时,就能解析出172.34.18.12

使用全限定域名

最直接,最有效的优化方式,就是使用 “fully qualified name”,简单来说,使用“完全限定域名”(也叫绝对域名),你访问的域名,必须要以 “.” 为后缀,这样就会避免走 search 域进行匹配
也就是说使用 xxx.lol.com.
但是这种办法不符合大家习惯

只在k8s内部进行解析

我们的集群是在私有化环境中,无公网访问,根据上面的抓包和日志可以看出,发送给公网dns解析服务器114.114.114.114的请求都timeout。既然我们不需要公网解析,给ban掉就行。
根据https://coredns.io/plugins/forward/,coredns forward插件控制 coredns 对于接收到的dns解析请求的转发。我们只需要删除掉forward插件就可以让coredns直接按照templates中的配置进行泛域名解析。
在这里插入图片描述
这样改动后,不需要再等待向公网域名解析服务器发请求,直接在coredns返回解析结果。

参考

  1. core dns 配置手册 https://coredns.io/manual/toc/#configuration
  2. core dns 插件 forward https://coredns.io/plugins/forward/
  3. core dns 配置说明 https://help.aliyun.com/document_detail/380963.html
  4. core dns 插件 template https://coredns.io/plugins/template/
  5. dns ptr 是什么 https://www.cloudflare.com/learning/dns/dns-records/dns-ptr-record/
  6. dns 解析常见返回 https://bluecatnetworks.com/blog/the-top-four-dns-response-codes-and-what-they-mean/
  7. resolv.conf 中的 search 和 ndots 配置. 使用 nsenter 在容器网络命名空间抓包 https://cloud.tencent.com/developer/article/1669860
  8. k8s dns 配置,策略,解析等 https://hansedong.github.io/2018/11/20/9/
  9. k8s coredns 日志报 i/o timeout https://github.com/kubernetes/kubernetes/issues/86762
  10. 使用HostAliases向 Pod /etc/hosts 文件添加条目
  • 19
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
Kubernetes (k8s) 是一个流行的容器编排和管理工具,它能够自动部署、扩展和管理容器化应用程序。在Kubernetes中,容器一般是通过服务发现的方式来进行通信,在这个过程中,域名解析是至关重要的一环。 容器中的应用程序通常会使用DNS进行域名解析来定位其他容器或外部服务。Nginx作为一个常用的容器化Web服务器,也需要通过DNS解析来将域名转换为IP地址,以便与其他容器或外部服务进行通信。 然而,有时候在Kubernetes集群中,容器的域名解析可能会出现不稳定性的问题。这可能导致Nginx无法解析需要的域名,使得容器间的网络通信出现故障或不可靠。 引起这种不稳定性的原因可能是多种多样的。首先,DNS解析问题可能与Kubernetes集群的配置有关。如果DNS服务配置不正确或不稳定,容器中的Nginx就无法准确地解析域名。 其次,网络问题也可能导致DNS解析不稳定。如果网络延迟高或者网络带宽不足,DNS解析可能会超时或失败,从而影响到Nginx的正常运行。 最后,应用程序本身的问题也可能导致DNS解析的不稳定性。如果应用程序没有正确地处理域名解析失败的情况,可能会导致Nginx无法正常工作。 要解决这个问题,我们可以采取以下措施: 1. 检查Kubernetes集群的DNS配置,确保DNS服务正常运行并配置正确。 2. 检查网络状况,确保网络延迟低、带宽充足,减少DNS解析超时的可能性。 3. 在应用程序中添加域名解析失败的错误处理机制,例如进行重试或回退到备用解析方案。 综上所述,k8s容器中的Nginx DNS解析不稳定的问题可能与Kubernetes集群的配置、网络问题或应用程序本身相关。通过检查和调整配置,优化网络状况以及合理处理解析失败,我们可以提高Nginx DNS解析的稳定性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值