操作场景
本文接下来将详细介绍如何在 TKE 集群中使用 NodeLocal DNS Cache。
操作原理
通过 DaemonSet 在集群的每个节点上部署一个 hostNetwork 的 Pod,该 Pod 是 node-cache,可以缓存本节点上 Pod 的 DNS 请求。如果存在 cache misses ,该 Pod 将会通过 TCP 请求上游 kube-dns 服务进行获取。原理图如下所示:


说明
NodeLocal DNS Cache 没有高可用性(High Availability,HA),会存在单点 nodelocal dns cache 故障(Pod Evicted/ OOMKilled/ConfigMap error/DaemonSet Upgrade),但是该现象其实是任何的单点代理(例如 kube-proxy,cni pod)都会存在的常见故障问题。
前提条件
操作步骤
1. 一键部署 NodeLocal DNS Cache。YAML 示例如下:
---apiVersion: v1kind: ServiceAccountmetadata:name: node-local-dnsnamespace: kube-systemlabels:kubernetes.io/cluster-service: "true"addonmanager.kubernetes.io/mode: Reconcile---apiVersion: v1kind: ConfigMapmetadata:name: node-local-dnsnamespace: kube-systemdata:Corefile: |cluster.local:53 {errorscache {success 9984 30denial 9984 5}reloadloopbind 169.254.20.10forward . __PILLAR__CLUSTER__DNS__ {force_tcp}prometheus :9253health 169.254.20.10:8080}in-addr.arpa:53 {errorscache 30reloadloopbind 169.254.20.10forward . __PILLAR__CLUSTER__DNS__ {force_tcp}prometheus :9253}ip6.arpa:53 {errorscache 30reloadloopbind 169.254.20.10forward . __PILLAR__CLUSTER__DNS__ {force_tcp}prometheus :9253}.:53 {errorscache 30reloadloopbind 169.254.20.10forward . /etc/resolv.conf {force_tcp}prometheus :9253}---apiVersion: apps/v1kind: DaemonSetmetadata:name: node-local-dnsnamespace: kube-systemlabels:k8s-app: node-local-dnsspec:updateStrategy:rollingUpdate:maxUnavailable: 10%selector:matchLabels:k8s-app: node-local-dnstemplate:metadata:labels:k8s-app: node-local-dnsannotations:prometheus.io/port: "9253"prometheus.io/scrape: "true"spec:serviceAccountName: node-local-dnspriorityClassName: system-node-criticalhostNetwork: truednsPolicy: Default # Don't use cluster DNS.tolerations:- key: "CriticalAddonsOnly"operator: "Exists"- effect: "NoExecute"operator: "Exists"- effect: "NoSchedule"operator: "Exists"containers:- name: node-cacheimage: ccr.ccs.tencentyun.com/hale/k8s-dns-node-cache:1.15.13resources:requests:cpu: 25mmemory: 5Miargs: [ "-localip", "169.254.20.10", "-conf", "/etc/Corefile", "-setupiptables=true" ]securityContext:privileged: trueports:- containerPort: 53name: dnsprotocol: UDP- containerPort: 53name: dns-tcpprotocol: TCP- containerPort: 9253name: metricsprotocol: TCPlivenessProbe:httpGet:host: 169.254.20.10path: /healthport: 8080initialDelaySeconds: 60timeoutSeconds: 5volumeMounts:- mountPath: /run/xtables.lockname: xtables-lockreadOnly: false- name: config-volumemountPath: /etc/coredns- name: kube-dns-configmountPath: /etc/kube-dnsvolumes:- name: xtables-lockhostPath:path: /run/xtables.locktype: FileOrCreate- name: kube-dns-configconfigMap:name: kube-dnsoptional: true- name: config-volumeconfigMap:name: node-local-dnsitems:- key: Corefilepath: Corefile.base
2. 将 kubelet 的指定 dns 解析访问地址设置为 步骤1 中创建的 local dns cache。本文提供以下两种配置方法,请根据实际情况进行选择:
依次执行以下命令,修改 kubelet 启动参数并重启。
sed -i '/CLUSTER_DNS/c\\CLUSTER_DNS="--cluster-dns=169.254.20.10"' /etc/kubernetes/kubelet
systemctl restart kubelet
根据需求配置单个 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.localoptions:- name: ndotsvalue: "2"
配置验证
本次测试集群为 Kubernetes 1.14 版本集群。在通过上述步骤完成 NodeLocal DNSCache 组件部署之后,可以参照以下方法进行验证:
1. 选择一个 debug pod,调整 kubelet 参数或者配置 dnsConfig 后重启。
2. Dig 外网域名,尝试在 coredns pod 上抓包。
3. 显示169.254.20.10正常工作即可证明 NodeLocal DNSCache 组件部署成功。如下图所示:

