k8s教程(service篇)-Node本地DNS缓存

01 引言

声明:本文为《Kubernetes权威指南:从Docker到Kubernetes实践全接触(第5版)》的读书笔记

由于在Kubernetes集群中配置的DNS服务 是一个名为 “kube-dns” 的Service, 所以容器应用都通过其ClusterIP地址(例如169.169.0.100)去执行服务名的DNS域名解析。这对于大规模集群可能引起以下两个问题:

  • 集群DNS服务压力增大(这可以通过自动扩容缓解)
  • 由于DNS服务的IP地址是ServiceClusterIP地址,所以会通过kube- proxy设置的iptables规则进行转发,可能导致域名解析性能很差,原因是Netfilter 在做DNAT转换时可能会引起conntrack冲突,从而导致DNS查询产生5s的延时

为了解决这两个问题,Kubernetes引入了Node本地DNS缓存NodeLocal DNSCache)来提高整个集群的DNS域名解析的性能,本文来讲解下。

02 Node本地DNS缓存

使用Node本地DNS缓存的好处如下

  • 在没有本地DNS缓存时,集群DNS服务的Pod很可能在其他节点上,跨主机访问会增加网络延时,使用Node本地DNS缓存可 显著减少跨主机查询的网络延时
  • 跳过iptables DNAT和连接跟踪将有助于 减少conntrack竞争,并避免UDP DNS记录填满conntrack表
  • 本地缓存到集群DNS服务的连接协议可以升级为TCP。TCP conntrack条目将在连接关闭时被删除;默认使用UDP时,conntrack条目只能等到超时时间过后才被删除,操作系统的默认超时时间(nf_conntrack_udp_timeout),为30s;
  • 将DNS查询从UDP升级为TCP,将减少由于丢弃的UDP数据包和DNS超时而引起的尾部延迟(tail latency),UDP超时时间可能会长达30s(3次重试, 每次10s);
  • 提供Node级别DNS解析请求的度量 (Metrics)和可见性 (visibility) 可以重新启用负缓存(Negative caching)功能,减少对集群DNS服务的查询数量

2.1 工作流程

Node本地DNS缓存(NodeLocal DNSCache)的工作流程如图所示,客户端Pod首先会通过本地DNS缓存进行域名解析,当缓存中不存在域名时,会将请求转发到集群DS服务进行解析
在这里插入图片描述

2.2 部署Node本地DNS缓存工具

配置文件nodelocaldns.yaml的内容如下,主要包括 ServiceAccount、Daemonset、ConfigMap和Service 几个资源对象。

2.2.1 资源对象配置


Service Account的定义如下:

apiVersion: v1
kind: ServiceAccount
metadata: 
	name: node-local-dns
	namespace: kube-system 
	labels:
		kubernetes.io/cluster-service: "true"
		addonmanager.kubernetes.io/mode: Reconcile

Service的定义如下:

apiVersion: v1
kind: Service
metadata:
	name: kube-dns-upstream
	namespace: kube-system 
	labels:
		k8s-app: kube-dns
		kubernetes.io/cluster-service: "true"
		addonmanager.kubernetes.io/mode: Reconcile 
		kubernetes.io/name: "KubeDNSUpstream"
spec:
	ports:
	- name: dns
	  port: 53
	  protocol: UDP
	  targetPort: 53
	- name: dns-tcp
	  port: 53
	  protocol: TCP
	  targetPort: 53
	selector:
	  k8s-app: kube-dns

ConfigMap的定义如下:

apiversion: v1
kind: ConfigMap
metadata:
	name: node-local-dns
	namespace: kube-system 
	labels:
		addonmanager.kubernetes.io/mode: Reconcile
data:
Corefile: |
	cluster.local:53 {
		errors
		cache{
			success 9984 30 
			denial 9984 5
		}
		reload
		loop
		bind169.254.20.10
		forward.169.169.0.100{
			force tcp
		}
		prometheus 9253
		hea1th169.254.20.10:8081 
		}
	in-addr.arpa:53 {
		errors 
		cache 30 
		reload
		loop
		bind 169.254.20.10
		forward . 169.169.0.100{
			force tcp
		}
		prometheus 9253 
		}
	ip6.arpa:53 {
		errors 
		cache 30 
		reload
		loop
	    bind 169.254.20.10
	    forward . 169.169.0.100{
			force tcp
	    }
		prometheus 9253
		}
	.:53 {
		errors 
		cache 30 
		reload
		loop
		bind 169.254.20.10
		forward . 169.169.0.100{
			force tcp
		}
		prometheus 9253 
		}

ConfigMap Corefile的主要配置参数如下:

  • bind 169.254.20.10 :node-local-dns需要绑定的本地IP地址,建议将其设置为169.254.0.0/16范围,确保不与集群内的其他IP冲突;
  • forward.169.169.0.100:在node-local-dns缓存中不存在域名记录时, 将转发到的上游DNS服务器IP设置为Kubernetes集群DNS服务(kube-dns)的IP,例如169.169.0.100;
  • health169.254.20.10:8081:健康检查端口号设置与Daemonset的livenessProbe一致,需要注意,node-local-dns网络模式设置了 hostNetwork=true,这个端口号也会被直接绑定到宿主机上,需要确保不与宿主机的其他应用冲突。

DaemonSet的定义如下:

apiVersion: apps/v1
kind: DaemonSet
metadata:
	name: node-local-dns 
	namespace: kube-system 
	labels:
		k8s-app: node-local-dns
		kubernetes.io/cluster-service: "true"
		addonmanager.kubernetes.io/mode: Reconcile 
spec:
	updatestrategy:
		rollingUpdate:
			maxUnavai1able: 10% 
	selector:
		matchLabels:
			k8s-app: node-local-dns 
	template:
		metadata:
			labels:
				k8s-app: node-local-dns 
			annotations:
				prometheus.io/port: "9253" 
				prometheus.io/scrape: "true" 
		spec:
			priorityclassName: system-node-critical 
			serviceAccountName: node-local-dns 
			hostNetwork: true
			dnsPolicy: Default Don't use cluster DNS. 
			tolerations:
			- key: "CriticalAddonsOnly" 
			  operator: "Exists"
			- effect: "NoExecute"
			  operator: "Exists"
			- effect: "NoSchedule"
			  operator: "Exists"
		containers:
		- name: node-cache
		  image: k8s.gcr.io/k8s-dns-node-cache: 1.15.13 
			resources:
				requests:
				cpu: 25m
				memory: 5Mi
				args: ["-localip","169.254.20.10","-conf","/etc/Corefile","-upstreamsvc","kube-dns-upstream"]
			securityContext:
				privileged: true
			ports:
			- containerPort: 53
			  name: dns
		      protocol: UDP
		    - containerPort: 53
		      name: dns-tcp
		      protocol: TCP
		    - containerPort: 9253
		      name: metrics
		      protocol: TCP
		    livenessProbe:
				httpGet:
					host: 169.254.20.10
					path: /health
					port: 8081
				initialDelaySeconds: 60 
				timeoutSeconds: 5
			volumeMounts:
			- mountPath: /run/xtables.lock 
			  name: xtables-lock
		      readonly: false
		    - name: config-volume 
			  mountPath: /etc/coredns 
			- name: kube-dns-config 
			  mountPath: /etc/kube-dns
		volumes:
		- name: xtables-lock
			hostPath:
				path: /run/xtables.lock 
				type: FileorCreate 
		- name: kube-dns-config 
		  configMap:
			name: coredns
			optional: true
		- name: config-volume
			configMap:
				name: node-local-dns
				items:
					- key: Corefile
					  path: Corefile.base

Daemonset node-local-dns的主要配置参数如下:

  • args: [“-localip” , “169.254.20.10” , “-conf” , “/etc/Corefile” , “upstreamsvc” , “kube-dns-upstream”]:将-localip参数设置为node-local-dns绑定的本地IP地址,对其他参数无须修改;
  • livenessProber中的健康检查端口号与ConfigMap中的一致;

另外,如果kube-proxy代理模式(-proxy-mode)使用的是ipvs模式,则还需要修改kubelet的启动参数-cluster-dns为node-local-dns绑定的本地IP地169.254.20.10。

2.2.2 部署

通过kubectl create命令创建node-local-dns服务:

kubectl create -f nodelocaldns.yaml 
serviceaccount/node-local-dns created 
service/kube-dns-upstream created 
configmap/node-local-dns created 
daemonset.apps/node-local-dns created

确认在每个Node上都运行了一个node-local-dns Pod:
在这里插入图片描述
在客户端Pod内对服务名的解析没有变化,仍然可以直接通过服务名访问其他服务,例如:
在这里插入图片描述

03 文末

本文主要讲解Node本地DNS缓存相关的概念,希望能帮助到大家,谢谢大家的阅读,本文完!

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值