在k8s集群中使用NodeLocal DNSCache(localdns)

NodeLocal DNSCache是Kubernetes官方推出的节点本地DNS缓存组件,在本文中后续直接使用localdns这个简写名字进行介绍和部署;从 v1.18 开始稳定,以DaemonSet形式在每个节点上运行一个轻量 CoreDNS,负责:

本地缓存集群DNS请求
减少跨节点访问kube-dns/CoreDNS的流量
降低 DNS 延迟、抖动,提高稳定性
减轻 kube-dns 服务压力

1.kube-dns服务默认流程

我们先来看看K8s中的kube-dns服务默认的流程

Pod → kube-dns ServiceIP → kube-proxy (iptables/ipvs) → 某节点 CoreDNS Pod → 解析

当有大量POD并发DNS请求时,kube-dns 就会成为瓶颈,跨节点转发会带来延迟与抖动,极端情况下 DNS 超时、解析失败。
引入NodeLocalDNS后解析就会变为以下流程

Pod → 本机 NodeLocalDNS (169.254.20.10:53) → 本地缓存 → 未命中才转发给 kube-dns

2.localdns在k8s集群中的优势

它在k8s集群中带来了以下优势
✅ 低延迟:同节点缓存,减少跨节点网络跳转
✅ 高稳定:避免 kube-dns 单点 / 瓶颈,网络抖动影响更小
✅ 降压力:显著减少 kube-dns 的 QPS
✅ 透明无侵入:应用无需修改,DNS 策略保持 ClusterFirst
使用NodeLocal DNSCache架构要点

监听:169.254.20.10:53(链路本地地址,不会与集群 IP 冲突)
模式:每个节点一个 Pod,hostNetwork: true,占用节点 53 端口
缓存:集群内域名(cluster.local)本地缓存,外部域名转发给上游
上游:指向集群原有 kube-dns(CoreDNS)ServiceIP

3.确认集群kube-proxy模式

我们在部署NodeLocal DNSCache首先需要确认k8s集群kube-proxy模式是使用的iptables还是ipvs

kubectl -n kube-system get cm kube-proxy -o yaml | grep mode
mode: ipvs

4.localdns组件配置

确认好模式以后我们就可以开始部署NodeLocal DNSCache

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

获取kube-dns的ClusterIP

kubedns=$(kubectl get svc kube-dns -n kube-system -o jsonpath={.spec.clusterIP})

获取集群域名(默认是cluster.local)

domain=cluster.local

设置本地监听IP

localdns=169.254.20.10

然后根据现场环境进行配置修改

4.1.iptables模式配置修改

cp nodelocaldns.yaml nodelocaldns-iptables.yaml
sed -i "s/__PILLAR__LOCAL__DNS__/$localdns/g;
s/__PILLAR__DNS__DOMAIN__/$domain/g;
s/__PILLAR__DNS__SERVER__/$kubedns/g" nodelocaldns-iptables.yaml

4.2.ipvs模式配置修改

cp nodelocaldns.yaml nodelocaldns-ipvs.yaml
sed -i "s/__PILLAR__LOCAL__DNS__/$localdns/g;
s/__PILLAR__DNS__DOMAIN__/$domain/g;
s/,__PILLAR__DNS__SERVER__//g" nodelocaldns-ipvs.yaml

IPVS 模式下不能绑定 kube-dns 的 ClusterIP,因此要删掉对应配置

5.localdns组件部署

两组不同的模式根据上述的文件进行部署
iptables模式部署

kubectl apply -f nodelocaldns-iptables.yaml

ipvs模式部署

kubectl apply -f nodelocaldns-ipvs.yaml

localdns组件状态检查

kubectl -n kube-system get ds node-local-dns
kubectl -n kube-system get pod -l k8s-app=node-local-dns

6.ipvs模式额外关键配置

如果kube-proxy是IPVS模式,必须修改kubelet的--cluster-dns参数,让Pod DNS指向本地node-local-dns

kubectl edit cm -n kube-system kubelet-config

修改clusterDNS的地址配置为169.254.20.10

apiVersion: v1
data:
  kubelet: |
    apiVersion: kubelet.config.k8s.io/v1beta1
    authentication:
      anonymous:
        enabled: false
      webhook:
        cacheTTL: 0s
        enabled: true
      x509:
        clientCAFile: /etc/kubernetes/pki/ca.crt
    authorization:
      mode: Webhook
      webhook:
        cacheAuthorizedTTL: 0s
        cacheUnauthorizedTTL: 0s
    cgroupDriver: systemd
    clusterDNS:
    - 169.254.20.10

然后所有节点重启kubelet。
iptables 模式无需修改 kubelet,因为node-local-dns会同时监听kube-dns的ClusterIP

7.验证localdns是否生效

看到169.254.20.10:53即正常

ss -uln | grep 53

起一个测试用的POD

kubectl run test-dns --image=busybox --rm -it

内部域名解析(集群 service)

nslookup kubernetes.default.svc.cluster.local

外部域名解析

nslookup www.baidu.com

查看缓存命中

kubectl -n kube-system exec -it <node-local-dns-pod-name> -- cat /etc/Corefile

查看metrics(缓存命中率)

curl localhost:9253/metrics | grep coredns_cache


内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://sulao.cn/post/1178

评论列表

0%