# 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](https://github.com/kubernetes/kubernetes/blob/b2ecd1b3a3192fbbe2b9e348e095326f51dc43dd/cluster/addons/dns/nodelocaldns/nodelocaldns.yaml#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](https://github.com/coredns/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.local`。 `search` 选项的取值会被用来展开查询。要进一步了解 DNS 查询，可参阅 [`resolv.conf` 手册页面](https://www.man7.org/linux/man-pages/man5/resolv.conf.5.html)。

```
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 查询数量

```yaml
  ...
  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
```

内容如下：

```yaml
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/>


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://liujinye.gitbook.io/openshift-docs/dns/k8s-coredns-you-hua.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
