kubernetes-guide/best-practices/dns/optimize-coredns-performanc...

84 lines
4.7 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

# CoreDNS 性能优化
CoreDNS 作为 Kubernetes 集群的域名解析组件,如果性能不够可能会影响业务,本文介绍几种 CoreDNS 的性能优化手段。
## 合理控制 CoreDNS 副本数
考虑以下几种方式:
1. 根据集群规模预估 coredns 需要的副本数,直接调整 coredns deployment 的副本数:
```bash
kubectl -n kube-system scale --replicas=10 deployment/coredns
```
2. 为 coredns 定义 HPA 自动扩缩容。
3. 安装 [cluster-proportional-autoscaler](https://github.com/kubernetes-sigs/cluster-proportional-autoscaler) 以实现更精确的扩缩容(推荐)。
## 禁用 ipv6
如果 K8S 节点没有禁用 IPV6 的话,容器内进程请求 coredns 时的默认行为是同时发起 IPV4 和 IPV6 解析,而通常我们只需要用到 IPV4当容器请求某个域名时coredns 解析不到 IPV6 记录,就会 forward 到 upstream 去解析,如果到 upstream 需要经过较长时间(比如跨公网,跨机房专线),就会拖慢整个解析流程的速度,业务层面就会感知 DNS 解析慢。
CoreDNS 有一个 [template](https://coredns.io/plugins/template/) 的插件,可以用它来禁用 IPV6 的解析,只需要给 CoreDNS 加上如下的配置:
```txt
template ANY AAAA {
rcode NXDOMAIN
}
```
> 这个配置的含义是:给所有 IPV6 的解析请求都响应空记录,即无此域名的 IPV6 记录。
## 优化 ndots
默认情况下Kubernetes 集群中的域名解析往往需要经过多次请求才能解析到。查看 pod 内 的 `/etc/resolv.conf` 可以知道 `ndots` 选项默认为 5:
![](https://image-host-1251893006.cos.ap-chengdu.myqcloud.com/2023%2F09%2F25%2F20230925111437.png)
意思是: 如果域名中 `.` 的数量小于 5就依次遍历 `search` 中的后缀并拼接上进行 DNS 查询。
举个例子,在 debug 命名空间查询 `kubernetes.default.svc.cluster.local` 这个 service:
1. 域名中有 4 个 `.`,小于 5尝试拼接上第一个 search 进行查询,即 `kubernetes.default.svc.cluster.local.debug.svc.cluster.local`,查不到该域名。
2. 继续尝试 `kubernetes.default.svc.cluster.local.svc.cluster.local`,查不到该域名。
3. 继续尝试 `kubernetes.default.svc.cluster.local.cluster.local`,仍然查不到该域名。
4. 尝试不加后缀,即 `kubernetes.default.svc.cluster.local`,查询成功,返回响应的 ClusterIP。
可以看到一个简单的 service 域名解析需要经过 4 轮解析才能成功,集群中充斥着大量无用的 DNS 请求。
怎么办呢?我们可以设置较小的 ndots在 Pod 的 dnsConfig 中可以设置:
![](https://image-host-1251893006.cos.ap-chengdu.myqcloud.com/2023%2F09%2F25%2F20230925111448.png)
然后业务发请求时尽量将 service 域名拼完整,这样就不会经过 search 拼接造成大量多余的 DNS 请求。
不过这样会比较麻烦,有没有更好的办法呢?有的!请看下面的 autopath 方式。
## 启用 autopath
启用 CoreDNS 的 autopath 插件可以避免每次域名解析经过多次请求才能解析到,原理是 CoreDNS 智能识别拼接过 search 的 DNS 解析,直接响应 CNAME 并附上相应的 ClusterIP一步到位可以极大减少集群内 DNS 请求数量。
启用方法是修改 CoreDNS 配置:
```bash
kubectl -n kube-system edit configmap coredns
```
修改红框中圈出来的配置:
![](https://image-host-1251893006.cos.ap-chengdu.myqcloud.com/2023%2F09%2F25%2F20230925111502.png)
* 加上 `autopath @kubernetes`
* 默认的 `pods insecure` 改成 `pods verified`
需要注意的是,启用 autopath 后,由于 coredns 需要 watch 所有的 pod会增加 coredns 的内存消耗,根据情况适当调节 coredns 的 memory request 和 limit。
## 部署 NodeLocal DNSCache
参考 k8s 官方文档 [Using NodeLocal DNSCache in Kubernetes clusters](https://kubernetes.io/docs/tasks/administer-cluster/nodelocaldns/)
如果是使用 TKE 并且 kube-proxy 转发模式为 iptables可以直接在扩展组件中安装此扩展组件扩展组件说明请参考 [TKE 官方文档](https://cloud.tencent.com/document/product/457/49423);如果使用的 ipvs 模式,可以参考 [TKE IPVS 模式安装 localdns](../../tencent/networking/install-localdns-with-ipvs.md)。
## 使用 DNSAutoscaler
社区有开源的 [cluster-proportional-autoscaler](https://github.com/kubernetes-sigs/cluster-proportional-autoscaler) ,可以根据集群规模自动扩缩容,支持比较灵活的扩缩容算法。
如果使用的是 TKE已经将其产品化成 `DNSAutoscaler 扩展组件`,在扩展组件中直接安装即可,组件说明请参考 [TKE 官方文档](https://cloud.tencent.com/document/product/457/49305)。