使用 NodeLocal DNS Cache

操做场景

经过在集群节点上以 Daemonset 的形式运行 NodeLocal DNS Cache,可以大幅提高集群内 DNS 解析性能,以及有效避免 conntrack 冲突引起的 DNS 五秒延迟node

操做原理

经过 DaemonSet 在集群的每一个节点上部署一个 hostNetwork 的 Pod,该 Pod 是 node-cache,能够缓存本节点上 Pod 的 DNS 请求。若是存在 cache misses ,该 Pod 将会经过 TCP 请求上游 kube-dns 服务进行获取。原理图以下所示:git

img

NodeLocal DNS Cache 没有高可用性(High Availability,HA),会存在单点 nodelocal dns cache 故障(Pod Evicted/ OOMKilled/ConfigMap error/DaemonSet Upgrade),可是该现象实际上是任何的单点代理(例如 kube-proxy,cni pod)都会存在的常见故障问题。github

<!--more-->shell

前提条件

建立了 Kubernetes 版本为 1.15 及以上的集群,且该集群中存在节点。api

操做步骤

wget -O nodelocaldns.yaml "https://github.com/kubernetes/kubernetes/raw/master/cluster/addons/dns/nodelocaldns/nodelocaldns.yaml"

该资源清单文件中包含几个变量,其中:缓存

  • __PILLAR__DNS__SERVER__ :表示 kube-dns 这个 Service 的 ClusterIP,能够经过命令 kubectl get svc -n kube-system | grep kube-dns | awk '{ print $3 }' 获取
  • __PILLAR__LOCAL__DNS__:表示 DNSCache 本地的 IP,默认为 169.254.20.10
  • __PILLAR__DNS__DOMAIN__:表示集群域,默认就是 cluster.local

修改相关配置app

sed -i 's/k8s.gcr.io/harbor.emarbox.com/g' nodelocaldns.yaml && \ 
sed -i 's/__PILLAR__DNS__SERVER__/10.96.0.10/g' nodelocaldns.yaml && \ 
sed -i 's/__PILLAR__LOCAL__DNS__/169.254.20.10/g' nodelocaldns.yaml && \ 
sed -i 's/__PILLAR__DNS__DOMAIN__/cluster.local/g' nodelocaldns.yaml

查看是否安装成功ide

$ kubectl get pods -n kube-system | grep node-local-dns
node-local-dns-658t4                       1/1     Running   0          19s
node-local-dns-6bsjv                       1/1     Running   0          19s
node-local-dns-wcxpw                       1/1     Running   0          19s

须要注意的是这里使用 DaemonSet 部署 node-local-dns 使用了 hostNetwork=true,会占用宿主机的 8080 端口,因此须要保证该端口未被占用。或者你本身修改 health 169.254.20.10:8080性能

修改配置,启用dns cache

本文提供如下两种配置方法,请根据实际状况进行选择:代理

若是 kube-proxy 组件使用的是 ipvs 模式的话咱们还须要修改 kubelet 的 --cluster-dns 参数,将其指向 169.254.20.10,Daemonset 会在每一个节点建立一个网卡来绑这个 IP,Pod 向本节点这个 IP 发 DNS 请求,缓存没有命中的时候才会再代理到上游集群 DNS 进行查询。 iptables 模式下 Pod 仍是向原来的集群 DNS 请求,节点上有这个 IP 监听,会被本机拦截,再请求集群上游 DNS,因此不须要更改 --cluster-dns 参数。

  1. 依次执行如下命令,修改 kubelet 启动参数并重启。
sed -i 's/10.96.0.10/169.254.20.10/g' /var/lib/kubelet/config.yaml
systemctl restart kubelet
  1. 根据需求配置单个 Pod 的 dnsconfig 后重启。YAML 核心部分参考以下:
  • 须要将 nameserver 配置为169.254.20.10。
  • 为确保集群内部域名可以被正常解析,须要配置 searches。
  • 适当下降 ndots 值有利于加速集群外部域名访问。
  • 当 Pod 没有使用带有多个 dots 的集群内部域名的状况下,建议将值设为2
dnsConfig:
nameservers: ["169.254.20.10"]
searches: 
 - default.svc.cluster.local
 - svc.cluster.local
 - cluster.local
options:
 - name: ndots
   value: "2"

验证

node-local-dns 安装配置完成后,咱们能够部署一个新的 Pod 来验证下:(test-node-local-dns.yaml)

apiVersion: v1
kind: Pod
metadata:
  name: test-node-local-dns
spec:
  containers:
  - name: local-dns
    image: busybox
    command: ["/bin/sh", "-c", "sleep 60m"]
  dnsConfig:
  nameservers: ["169.254.20.10"]
  searches: 
   - default.svc.cluster.local
   - svc.cluster.local
   - cluster.local
  options:
   - name: ndots
     value: "2"

直接部署:

$ kubectl apply -f test-node-local-dns.yaml
$ kubectl exec -it test-node-local-dns /bin/sh
/ # cat /etc/resolv.conf
nameserver 169.254.20.10
search default.svc.cluster.local svc.cluster.local cluster.local
options ndots:5

咱们能够看到 nameserver 已经变成 169.254.20.10 了,固然对于以前的历史 Pod 要想使用 node-local-dns 则须要重建,固然若是要想去跟踪 DNS 的解析过程的话能够去经过抓包来观察。

相关文章
相关标签/搜索