k8s coredns 优化

k8s coredns 优化

配置 NodeLocal DNS Cache

说明:

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

  • 下载 nodelocaldns.yaml

wget https://raw.githubusercontent.com/kubernetes/kubernetes/v1.22.16/cluster/addons/dns/nodelocaldns/nodelocaldns.yaml
  • 如果使用 IPv6,在使用 'IP:Port' 格式的时候需要把 CoreDNS 配置文件里的所有 IPv6 地址用方括号包起来。 如果你使用上述的示例清单, 需要把配置行 L70 修改为: "health [__PILLAR__LOCAL__DNS__]:8080"。

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

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

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

  • 修改 image repo

    sed -i 's/k8s.gcr.io/registry.solarfs.io/g' nodelocaldns.yaml
  • 如果 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__

  • 运行 kubectl create -f nodelocaldns.yaml

  • 如果 kube-proxy 运行在 IPVS 模式,需要修改 kubelet 的 --cluster-dns 参数 NodeLocal DNSCache 正在侦听的 <node-local-address> 地址。 否则,不需要修改 --cluster-dns 参数,因为 NodeLocal DNSCache 会同时侦听 kube-dns 服务的 IP 地址和 <node-local-address> 的地址。

    Rock Linux 修改 /etc/sysconfig/kubelet

    KUBELET_EXTRA_ARGS="--cluster-dns=169.254.20.10"

    重启 kubelet

    systemctl restart kubelet

启用后,node-local-dns Pod 将在每个集群节点上的 kube-system 名字空间中运行。 此 Pod 在缓存模式下运行 CoreDNS, 因此每个节点都可以使用不同插件公开的所有 CoreDNS 指标。

如果要禁用该功能,你可以使用 kubectl delete -f <manifest> 来删除 DaemonSet。 你还应该回滚你对 kubelet 配置所做的所有改动。

优化 ndots

DNS 查询可能因为执行查询的 Pod 所在的名字空间而返回不同的结果。 不指定名字空间的 DNS 查询会被限制在 Pod 所在的名字空间内。 要访问其他名字空间中的 Service,需要在 DNS 查询中指定名字空间。

例如,假定名字空间 test 中存在一个 Pod,prod 名字空间中存在一个服务 data

Pod 查询 data 时没有返回结果,因为使用的是 Pod 的名字空间 test

Pod 查询 data.prod 时则会返回预期的结果,因为查询中指定了名字空间。

DNS 查询可以使用 Pod 中的 /etc/resolv.conf 展开。kubelet 会为每个 Pod 生成此文件。例如,对 data 的查询可能被展开为 data.test.svc.cluster.localsearch 选项的取值会被用来展开查询。要进一步了解 DNS 查询,可参阅 resolv.conf 手册页面

nameserver 169.254.20.10
search <namespace>.svc.cluster.local svc.cluster.local cluster.local
options ndots:5

概括起来,名字空间 test 中的 Pod 可以成功地解析 data.prod 或者 data.prod.svc.cluster.local

pod 中修改 ndots

启动的服务pod 中增加 dnsConfig 配置, 减少search 查询数量

  ...
  dnsConfig:
    options:
      - name: ndots
        value: "2"

启用autopath 插件

autopath是一个可选的优化插件,可以提高集群外部名称查询的性能。启用autopath插件需要CoreDNS使用更多的内存来存储有关Pod的信息。Autopath的原理是在第一次域名查询失败尝试找到正确的域名,这样共需要2次(1次IPv4,1次IPv6)查询就可以获取到正确的结果, 减少客户端在查找外部名称时进行的DNS查询次数。

编辑 coredns configmap

kubectl edit configmap coredns -n kube-system

内容如下:

apiVersion: v1
data:
  Corefile: |
    .:53 {
        errors
        health {
           lameduck 5s
        }
        ready
        kubernetes cluster.local in-addr.arpa ip6.arpa {
           pods verified # 修改这里
           fallthrough in-addr.arpa ip6.arpa
           ttl 30
        }
        autopath @kubernetes # 增加这里
        prometheus :9153
        forward . 10.42.255.1 10.42.255.2 114.114.114.114 {
           max_concurrent 1000
        }
        cache 30
        loop
        reload
        loadbalance
    }

性能测试

安装 dnsperf

yum install dnsperf

准备好压测的dns 列表, dns.txt

www.baidu.com A

执行压测

dnsperf -l 30 -s 10.96.0.10 -d dns.txt
DNS Performance Testing Tool
Version 2.7.1

[Status] Command line: dnsperf -l 30 -s 10.96.0.10 -d dns.txt
[Status] Sending queries (to 10.96.0.10:53)
[Status] Started at: Sun Dec  4 13:09:04 2022
[Status] Stopping after 30.000000 seconds
[Status] Testing complete (time limit)

Statistics:

  Queries sent:         1703257
  Queries completed:    1703257 (100.00%)
  Queries lost:         0 (0.00%)

  Response codes:       NOERROR 1703257 (100.00%)
  Average packet size:  request 47, response 92
  Run time (s):         30.000809
  Queries per second:   56773.702336

  Average Latency (s):  0.001483 (min 0.000019, max 0.025491)
  Latency StdDev (s):   0.001063
dnsperf -l 30 -s 169.254.20.10 -d dns.txt
DNS Performance Testing Tool
Version 2.7.1

[Status] Command line: dnsperf -l 30 -s 169.254.20.10 -d dns.txt
[Status] Sending queries (to 169.254.20.10:53)
[Status] Started at: Sun Dec  4 13:10:16 2022
[Status] Stopping after 30.000000 seconds
[Status] Testing complete (time limit)

Statistics:

  Queries sent:         1623316
  Queries completed:    1623316 (100.00%)
  Queries lost:         0 (0.00%)

  Response codes:       NOERROR 1623316 (100.00%)
  Average packet size:  request 47, response 92
  Run time (s):         30.000978
  Queries per second:   54108.769387

  Average Latency (s):  0.001626 (min 0.000023, max 0.028625)
  Latency StdDev (s):   0.000950

参考

https://kubernetes.io/zh-cn/docs/tasks/administer-cluster/nodelocaldns/

https://kubernetes.io/zh-cn/docs/concepts/services-networking/dns-pod-service/

https://aws.amazon.com/cn/blogs/china/how-to-optimize-amazon-eks-cluster-dns-performance/

https://imroc.cc/tke/faq/install-localdns-with-ipvs/

https://github.com/kubernetes/kubernetes/blob/master/cluster/addons/dns/nodelocaldns/nodelocaldns.yaml

https://cloud.tencent.com/developer/article/1583706

https://imroc.cc/k8s/best-practice/optimize-dns/

Last updated