國(guó)家安全人民防線建設(shè)網(wǎng)站如何在網(wǎng)上推廣產(chǎn)品
k8s 系列之 CoreDNS
CoreDNS工作原理
kuberntes 中的 pod 基于 service 域名解析后,再負(fù)載均衡分發(fā)到 service 后端的各個(gè) pod 服務(wù)中,如果沒有 DNS 解析,則無法查到各個(gè)服務(wù)對(duì)應(yīng)的 service 服務(wù)
在 Kubernetes 中,服務(wù)發(fā)現(xiàn)有幾種方式:
基于環(huán)境變量的方式
基于內(nèi)部域名的方式
從 K8S 1.11 開始,K8S 已經(jīng)使用 CoreDNS,替換 KubeDNS 來充當(dāng)其 DNS 解析, DNS 如何解析,依賴容器內(nèi) resolv 文件的配置
# cat /etc/resolv.conf
nameserver 10.200.254.254
search default.svc.cluster.local. svc.cluster.local. cluster.local.
options ndots:5
ndots:5:如果查詢的域名包含的點(diǎn) “.” 不到 5 個(gè),那么進(jìn)行 DNS 查找,將使用非完全限定名稱(或者叫絕對(duì)域名),如果你查詢的域名包含點(diǎn)數(shù)大于等于 5,那么 DNS 查詢,默認(rèn)會(huì)使用絕對(duì)域名進(jìn)行查詢。Kubernetes 域名的全稱,必須是 service-name.namespace.svc.cluster.local 這種模式,服務(wù)名
# nslookup kubernetes.default.svc.cluster.local
Server: 10.200.254.254
Address: 10.200.254.254:53Name: kubernetes.default.svc.cluster.local
Address: 10.200.0.1
DNS策略,在Pod,Deployment RC等資源設(shè)置 dnsPolicy
None
用于想要自定義 DNS 配置的場(chǎng)景,而且需要和 dnsConfig 配合一起使用
Default
讓 kubelet 來決定使用何種 DNS 策略。而 kubelet 默認(rèn)使用宿主機(jī)的 /etc/resolv.conf(使用宿主機(jī)的DNS策略)
但 kubelet 可以配置使用什么文件來進(jìn)行 DNS 策略,使用 kubelet 的參數(shù):–resolv-conf=/etc/resolv.conf 來決定 DNS 解析文件地址
ClusterFirst
表示 POD 內(nèi)的 DNS 使用集群中配置的 DNS 服務(wù),使用 Kubernetes 中 kubedns 或 coredns 服務(wù)進(jìn)行域名解析。如果解析不成功,才會(huì)使用宿主機(jī)的 DNS 進(jìn)行解析
ClusterFirstWithHostNet
POD 是用 HOST 模式啟動(dòng)的(HOST模式),用 HOST 模式表示 POD 中的所有容器,都使用宿主機(jī)的 /etc/resolv.conf 進(jìn)行 DNS 查詢,但如果使用了 HOST 模式,還繼續(xù)使用 Kubernetes 的 DNS 服務(wù),那就將 dnsPolicy 設(shè)置為 ClusterFirstWithHostNet
配置文件使用 configmap
health:CoreDNS 健康檢查為 http://$IP:8080/health,返回為 OK
kubernetes:CoreDNS 將根據(jù) Kubernetes 服務(wù)和 pod 的 IP 回復(fù) DNS 查詢
prometheus:CoreDNS 度量 http://$IP:9153/metrics
proxy:不在 Kubernetes 集群域內(nèi)的查詢都將轉(zhuǎn)發(fā)到預(yù)定義的解析器(/etc/resolv.conf),可以配置多個(gè)upstream 域名服務(wù)器,也可以用于延遲查找 /etc/resolv.conf 中定義的域名服務(wù)器
cache:啟用緩存,30 秒 TTL
loop:檢測(cè)簡(jiǎn)單的轉(zhuǎn)發(fā)循環(huán),如果找到循環(huán)則停止 CoreDNS 進(jìn)程
reload:允許自動(dòng)重新加載已更改的 Corefile
loadbalance:DNS 負(fù)載均衡器,默認(rèn)round_robin
apiVersion: v1
kind: ConfigMap
metadata:name: corednsnamespace: namespace-test
data:Corefile: |.:53 {errorshealthreadykubernetes cluster.local 10.200.0.0/16 {pods insecureupstream 114.114.114.114fallthrough in-addr.arpa ip6.arpanamespaces namespace-test}prometheus :9153forward . /etc/resolv.confcache 30loopreloadloadbalance}
Coredns 規(guī)定協(xié)議
當(dāng)前 CoreDNS 接受4種協(xié)議: DNS, DNS over TLS (DoT), DNS over HTTP/2 (DoH)
and DNS over gRPC??梢酝ㄟ^在服務(wù)器配置文件,在zone 前加個(gè)前綴來指定服務(wù)器接收哪種協(xié)議。
dns:// for plain DNS (the default if no scheme is specified).
tls:// for DNS over TLS, see RFC 7858.
https:// for DNS over HTTPS, see RFC 8484.
grpc:// for DNS over gRPC.
UDP非標(biāo)準(zhǔn)端口只在某些地區(qū)某些運(yùn)營(yíng)商有用,DoT,即DNS over TLS,支持DoT的公共DNS服務(wù)有Quad9的9.9.9.9,Google的8.8.8.8以及Cloudflare的1.1.1.1,可以這么使用:
.:5301 {forward . tls://9.9.9.9 {tls_servername dns.quad9.net}cache
}
.:5302 {forward . tls://1.1.1.1 tls://1.0.0.1 {tls_servername 1dot1dot1dot1.cloudflare-dns.com}cache
}
.:5303 {forward . tls://8.8.8.8 tls://8.8.4.4 {tls_servername dns.google}cache
}
由于proxy插件新版本已經(jīng)移除,作為external plugin,需要自己編譯CoreDNS。
git clone https://github.com/coredns/coredns.git
cd coredns
make
CoreDNS使用了go modules機(jī)制,所以在make過程中會(huì)自動(dòng)下載依賴的package??梢酝ㄟ^HTTP_PROXY環(huán)境變量指定,或者使用國(guó)內(nèi)的一些鏡像(如果你信得過的話)通過GOPROXY環(huán)境變量指定。則在make前,要修改plugin.cfg文件,加入以下:
proxy:github.com/coredns/proxy
再make,就會(huì)把插件編譯進(jìn)去。如果發(fā)現(xiàn)沒有編譯進(jìn)去,可以先執(zhí)行一下go generate coredns.go再make
coredns 安裝部署
下載:https://github.com/coredns/deployment/tree/master/kubernetes
deploy.sh 用于生成用于 kube-dns 的集群上運(yùn)行 CoreDNS 的 yaml 文件
coredns.yaml.sed 文件作為模板,它創(chuàng)建一個(gè) ConfigMap 和一個(gè) CoreDNS deployment 的yaml 文件
./deploy.sh 172.18.0.0/24 cluster.local 生成 yaml 文件,在使用 kubectl apply 部署在 k8s 中
官方性能
計(jì)算表達(dá)式: MB required (default settings) = (Pods + Services) / 1000 + 54
cache 需要 30 MB,大約緩存 10000 條記錄操作 buffer 需要 5 MB,用于處理查詢,大約可以承受 30 K QPS 量
CoreDNS 的性能優(yōu)化
概述
CoreDNS 作為 Kubernetes 集群的域名解析組件,如果性能不夠可能會(huì)影響業(yè)務(wù),本文介紹幾種 CoreDNS 的性能優(yōu)化手段。
合理控制 CoreDNS 副本數(shù)
考慮以下幾種方式:
根據(jù)集群規(guī)模預(yù)估 coredns 需要的副本數(shù),直接調(diào)整 coredns deployment 的副本數(shù):
kubectl -n kube-system scale --replicas=10 deployment/coredns
為 coredns 定義 HPA 自動(dòng)擴(kuò)縮容。
安裝 cluster-proportional-autoscaler 以實(shí)現(xiàn)更精確的擴(kuò)縮容(推薦)。
禁用 ipv6
如果 K8S 節(jié)點(diǎn)沒有禁用 IPV6 的話,容器內(nèi)進(jìn)程請(qǐng)求 coredns 時(shí)的默認(rèn)行為是同時(shí)發(fā)起 IPV4 和 IPV6 解析,而通常我們只需要用到 IPV4,當(dāng)容器請(qǐng)求某個(gè)域名時(shí),coredns 解析不到 IPV6 記錄,就會(huì) forward 到 upstream 去解析,如果到 upstream 需要經(jīng)過較長(zhǎng)時(shí)間(比如跨公網(wǎng),跨機(jī)房專線),就會(huì)拖慢整個(gè)解析流程的速度,業(yè)務(wù)層面就會(huì)感知 DNS 解析慢。
CoreDNS 有一個(gè) template 的插件,可以用它來禁用 IPV6 的解析,只需要給 CoreDNS 加上如下的配置:
template ANY AAAA {
rcode NXDOMAIN
}
這個(gè)配置的含義是:給所有 IPV6 的解析請(qǐng)求都響應(yīng)空記錄,即無此域名的 IPV6 記錄。
優(yōu)化 ndots
默認(rèn)情況下,Kubernetes 集群中的域名解析往往需要經(jīng)過多次請(qǐng)求才能解析到。查看 pod 內(nèi) 的 /etc/resolv.conf 可以知道 ndots 選項(xiàng)默認(rèn)為 5:
意思是: 如果域名中 . 的數(shù)量小于 5,就依次遍歷 search 中的后綴并拼接上進(jìn)行 DNS 查詢。
舉個(gè)例子,在 debug 命名空間查詢 kubernetes.default.svc.cluster.local 這個(gè) service:
域名中有 4 個(gè) .,小于 5,嘗試拼接上第一個(gè) search 進(jìn)行查詢,即 kubernetes.default.svc.cluster.local.debug.svc.cluster.local,查不到該域名。
繼續(xù)嘗試 kubernetes.default.svc.cluster.local.svc.cluster.local,查不到該域名。
繼續(xù)嘗試 kubernetes.default.svc.cluster.local.cluster.local,仍然查不到該域名。
嘗試不加后綴,即 kubernetes.default.svc.cluster.local,查詢成功,返回響應(yīng)的 ClusterIP。
可以看到一個(gè)簡(jiǎn)單的 service 域名解析需要經(jīng)過 4 輪解析才能成功,集群中充斥著大量無用的 DNS 請(qǐng)求。
怎么辦呢?我們可以設(shè)置較小的 ndots,在 Pod 的 dnsConfig 中可以設(shè)置:
然后業(yè)務(wù)發(fā)請(qǐng)求時(shí)盡量將 service 域名拼完整,這樣就不會(huì)經(jīng)過 search 拼接造成大量多余的 DNS 請(qǐng)求。
不過這樣會(huì)比較麻煩,有沒有更好的辦法呢?有的!請(qǐng)看下面的 autopath 方式。
啟用 autopath
啟用 CoreDNS 的 autopath 插件可以避免每次域名解析經(jīng)過多次請(qǐng)求才能解析到,原理是 CoreDNS 智能識(shí)別拼接過 search 的 DNS 解析,直接響應(yīng) CNAME 并附上相應(yīng)的 ClusterIP,一步到位,可以極大減少集群內(nèi) DNS 請(qǐng)求數(shù)量。
啟用方法是修改 CoreDNS 配置:
kubectl -n kube-system edit configmap coredns
修改紅框中圈出來的配置:
加上 autopath @kubernetes。
默認(rèn)的 pods insecure 改成 pods verified。
需要注意的是,啟用 autopath 后,由于 coredns 需要 watch 所有的 pod,會(huì)增加 coredns 的內(nèi)存消耗,根據(jù)情況適當(dāng)調(diào)節(jié) coredns 的 memory request 和 limit。
CoreDNS 的排障
報(bào)錯(cuò):***********************dns: overflowing header size
此時(shí)需修改參數(shù):
#kubectl describe configmap coredns -n kube-system
Name: coredns
Namespace: kube-system
Labels: <none>
Annotations: kubectl.kubernetes.io/last-applied-configuration:{"apiVersion":"v1","data":{"Corefile":".:53 {\n errors\n health {\n lameduck 5s\n }\n ready\n kubernetes cluster.local...Data
====
Corefile:
----
.:53 {errorshealth {lameduck 5s}readykubernetes cluster.local in-addr.arpa ip6.arpa {fallthrough in-addr.arpa ip6.arpa}template ANY AAAA {rcode NXDOMAIN}prometheus :9153forward . /etc/resolv.confbufsize 2048 ##調(diào)大此參數(shù) 或增加此參數(shù)cache 30loopreloadloadbalance
}