k8s域名解析超时?使用NodeLocal DNSCache来解决

科技   2024-09-11 07:31   广东  

在使用K8s集群的过程中,我们发现部分Pod在进行Service名称解析时,容易出现请求超时的情况。

对于K8s有所了解的读者会知道,当Pod中的程序请求域名时,相关的解析是由CoreDNS来处理的。因此,在集群处于较大规模的情况下,相关的请求也将非常多,这导致CoreDNS会面临较大的处理压力,从而出现部分请求超时的情况。
对于此问题,Kubernetes社区引入了NodeLocal DNSCache方案, 用于提升集群的域名解析性能。
一. 方案介绍
NodeLocal DNSCache使用DaemonSet 的方式,会在每个节点部署DNS缓存服务,用于缓解CoreDNS的压力。对于Pod而言,这种方式也避免了需要跨主机网络访问DNS服务而导致的网络延迟,可以有效提升集群域名解析的能力。
启用 NodeLocal DNSCache 之后,DNS 查询会遵循如下

业务Pod作为客户端,向Local DNSCache发起域名解析请求,此时,如果该Local DNSCache 已缓存相关信息,会从缓存中检索信息并提供给到客户端。如果没有命中缓存,则会转发到集群 的CoreDNS节点请求解析,并在收到信息后进行缓存。
可以看到,在这种情况下,域名只需要到CoreDNS请求一次,后面的相关解析都由本机节点的Local DNSCache来处理,在效率无疑会有极大地提升。

说明:NodeLocal DNSCache 的本地侦听 IP 地址可以是任何地址,只要该地址不和你的集群里现有的 IP 地址发生冲突。 推荐使用本地范围内的地址,例如,IPv4 链路本地区段 '169.254.0.0/16' 内的地址, 或者 IPv6 唯一本地地址区段 'fd00::/8' 内的地址。

二. 部署NodeLocal DNSCache

1. 按照下方示例创建一个资源清单,并把它保存为 nodelocaldns.yaml

https://github.com/kubernetes/kubernetes/blob/master/cluster/addons/dns/nodelocaldns/nodelocaldns.yaml
2.  修改设置

把清单里的变量更改为正确的值:

kubedns=`kubectl get svc kube-dns -n kube-system -o jsonpath={.spec.clusterIP}`
domain=<cluster-domain>
localdns=<node-local-address>

#在本示例中,使用下面的值
domain=cluster.local
localdns=169.254.20.10

注:<cluster-domain> 的默认值是 "cluster.local"。<node-local-address> 是 NodeLocal DNSCache 选择的本地侦听 IP 地址,例如:169.254.20.10。

  • 如果 kube-proxy 运行在 IPTABLES 模式,执行下面命令更改设置:
sed -i "s/__PILLAR__LOCAL__DNS__/$localdns/g; s/__PILLAR__DNS__DOMAIN__/$domain/g; s/__PILLAR__DNS__SERVER__/$kubedns/g" nodelocaldns.yaml

注:node-local-dns Pod 会设置 __PILLAR__CLUSTER__DNS__ 和 __PILLAR__UPSTREAM__SERVERS__。在此模式下, node-local-dns Pod 会同时侦听 kube-dns 服务的 IP 地址和 <node-local-address> 的地址,以便 Pod 可以使用其中任何一个 IP 地址来查询 DNS 记录。

  • 如果 kube-proxy 运行在 IPVS 模式,则使用下面命令:

sed -i "s/__PILLAR__LOCAL__DNS__/$localdns/g; s/__PILLAR__DNS__DOMAIN__/$domain/g; s/,__PILLAR__DNS__SERVER__//g; s/__PILLAR__CLUSTER__DNS__/$kubedns/g" nodelocaldns.yaml
注:在此模式下,node-local-dns Pod 只会侦听 <node-local-address> 的地址。node-local-dns 接口不能绑定 kube-dns 的集群 IP 地址,因为 IPVS 负载均衡使用的接口已经占用了该地址。node-local-dns Pod 会设置 __PILLAR__UPSTREAM__SERVERS__。

3. 部署程序

kubectl create -f nodelocaldns.yaml

启用后, node-local-dns Pod 将在每个集群节点上的 kube-system 命名空间中运行。

$ kubectl  get pod -n kube-system  -l k8s-app=node-local-dns
NAME                   READY   STATUS    RESTARTS   AGE
node-local-dns-clrsb   1/1     Running   0          6m35s
node-local-dns-msx22   1/1     Running   0          6m35s
node-local-dns-wpphv   1/1     Running   0          6m35s
如果 kube-proxy 运行在 IPVS 模式,需要修改 每个节点的kubelet 的 --cluster-dns 参数,改为NodeLocal DNSCache 正在侦听的 <node-local-address> 地址。
使用如下命令:
$ sed -i 's/$kubedns/$localdns/g' /var/lib/kubelet/config.yaml
$ systemctl daemon-reload && systemctl restart kubelet
此时,查看新创建的Pod,会发现相关的DNS解析自动指向 LocalDns 地址

如下所示:

$ cat /etc/resolv.conf
nameserver 169.254.20.10
search default.svc.cluster.local svc.cluster.local cluster.local
options ndots:5

至此,整个部署过程完成,现在可以开始体验NodeLocal DNSCacher带来的效果了。


推荐内容:

热门技术专栏限时特惠中,点击查看↓ 

------------------ END ------------------

关注公众号,获取更多精彩内容

感谢阅读,如果觉得内容还行可以随手点个“赞”或者“在看”,也欢迎分享文章到朋友圈和技术群。

需要开通转载白名单的话,请联系我。

DevOps实战派
DevOps、SRE和运维领域资深技术老鸟;公众号主要分享相关领域的专业知识。
 最新文章