使用 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 的解析過程的話能夠去經過抓包來觀察。

相關文章
相關標籤/搜索