Kubernetes中內(nèi)部服務(wù)調(diào)用DNS解析
之前文章<老大喊我7天從SpringCloud轉(zhuǎn)到K8S>中我提到過我們使用open-feign來訪問內(nèi)部服務(wù),有很多童鞋留言問我訪問內(nèi)部服務(wù)的url應(yīng)該怎么寫,但是還是整個(gè)系統(tǒng)的整體url嗎?
比如我整個(gè)系統(tǒng)的url是 http://www.think123.com, 現(xiàn)在有user服務(wù)和manage服務(wù),那我現(xiàn)在想要訪問user服務(wù)的ip就變成 http://www.think123.com/user嗎? 當(dāng)然不是因?yàn)檫@樣的話你的訪問就相當(dāng)于還是訪問外網(wǎng),又要重新走gateway, 這樣子不僅增加網(wǎng)絡(luò)開銷,而且我們做鑒權(quán)也不方便,因?yàn)榉?wù)間的訪問鑒權(quán)往往是通過一個(gè)注解或者token來實(shí)現(xiàn)的。
服務(wù)的ip地址
我們都知道在k8s中我們一般會(huì)部署多個(gè)pod, 而我們又是通過K8S的Service來做LoadBalance的,Service會(huì)根據(jù)一定的策略來選擇具體訪問的pod, 如下圖所示

因此實(shí)際上我們只需要知道service的地址就行了,使用下面的命令查看service的地址
kubectl get svc -n <namespace>

我們可以看到service的ip,因?yàn)槲覀兎?wù)是部署到同一個(gè)集群的,那是不是只需要知道服務(wù)的ip就行了,然后在open-feign中聲明要訪問的服務(wù)的ip加上端口就可以了呢?
原則是上可以的,但是實(shí)際上有問題,首先不同集群中ip地址不一樣,如果你要部署不同集群,那么每次都要修改,其次就算只有一個(gè)集群,這個(gè)ip也是可能變動(dòng)的,所以寫ip不太靠譜。
服務(wù)的域名
好在kubernetes給某個(gè)服務(wù)都添加了一個(gè)域名(這是通過kube-proxy和iptables實(shí)現(xiàn)的), 域名的規(guī)則是 ..svc.cluster.local。
比如對(duì)于我們的user服務(wù),我們這個(gè)地址就是 user.dev.svc.cluster.local(<serviceName>.<namespace>.svc.cluster.local)
當(dāng)然后面的這么一堆你都可以省略,實(shí)際上我們?cè)趏pen-feign的url中只需要聲明 http://user:9201/(服務(wù)名:端口) 就可以了,kubernetes在進(jìn)行dns尋址的時(shí)候會(huì)先在本地dns找user這個(gè)域名對(duì)應(yīng)的ip地址
K8S的DNS解析機(jī)制
1.集群域名和后綴:Kubernetes集群中的每個(gè)服務(wù)都會(huì)被分配一個(gè)域名,該域名由服務(wù)名稱(Service Name)和命名空間(Namespace)組成。例如,一個(gè)服務(wù)名為my-service,位于命名空間my-namespace的服務(wù)的完整域名將是my-service.my-namespace.svc.cluster.local。svc.cluster.local是Kubernetes集群默認(rèn)的后綴。 2.Kubernetes DNS服務(wù)器:Kubernetes集群內(nèi)部有一個(gè)專用的DNS服務(wù)器負(fù)責(zé)處理服務(wù)的DNS解析請(qǐng)求。這個(gè)DNS服務(wù)器通常被命名為kube-dns或coredns。 3.解析流程:在進(jìn)行DNS解析時(shí),應(yīng)用程序或服務(wù)可以使用服務(wù)名作為主機(jī)名(hostname),然后發(fā)送DNS查詢請(qǐng)求到Kubernetes DNS服務(wù)器。 4.DNS查詢:Kubernetes DNS服務(wù)器接收到DNS查詢請(qǐng)求后,會(huì)根據(jù)請(qǐng)求中的域名信息進(jìn)行解析。它首先進(jìn)行域名拆分,將服務(wù)名、命名空間和集群后綴分離開。 5.域名解析:Kubernetes DNS服務(wù)器會(huì)依次解析域名的各個(gè)部分。它首先解析命名空間,然后根據(jù)服務(wù)名在該命名空間下查找對(duì)應(yīng)的Service資源。 6.Service資源解析:Kubernetes DNS服務(wù)器在Service資源中查找與請(qǐng)求的服務(wù)名和命名空間匹配的條目。如果找到匹配項(xiàng),將返回與之關(guān)聯(lián)的Pod IP地址列表。 7.IP地址返回:Kubernetes DNS服務(wù)器將解析到的Pod IP地址返回給發(fā)起請(qǐng)求的應(yīng)用程序或服務(wù)。 8.重試機(jī)制:如果在初始查詢時(shí)沒有找到匹配的Service資源,Kubernetes DNS服務(wù)器可能會(huì)進(jìn)行一些重試機(jī)制,以確保服務(wù)名得到正確解析。這樣做是因?yàn)樵趧?chuàng)建和刪除Service資源的過程中,可能會(huì)存在一定的延遲。通過這種方式,Kubernetes DNS解析機(jī)制使得服務(wù)能夠通過服務(wù)名進(jìn)行通信,無需關(guān)心具體的Pod IP地址。這種抽象層簡(jiǎn)化了服務(wù)之間的通信配置,并支持動(dòng)態(tài)擴(kuò)展和管理服務(wù)。
查看域名
可以通過下面的命令查看域名
kubectl get svc my-service -n my-namespace -o jsonpath='{.metadata.name}.{.metadata.namespace}.svc.cluster.local'
查看coredns
通過下面的命令可以查看coredns pod
kubectl -n kube-system get pods -l k8s-app=kube-dns
當(dāng)然我們可以通過下面的命令查看coredns的配置
kubectl -n kube-system get cm -l k8s-app=kube-dnskubectl describe cm coredns -n kube-system
其核心配置如下
.:53 {errorsreadyhealthkubernetes cluster.local in-addr.arpa ip6.arpa {pods insecurefallthrough in-addr.arpa ip6.arpa}prometheus :9153forward . /etc/resolv.confcache 30loopreloadloadbalanceimport custom/*.override}
1..:53 表示監(jiān)聽的 DNS 端口號(hào)為 53,. 表示根域名(Root Zone)。 2.kubernetes cluster.local in-addr.arpa ip6.arpa 定義了多個(gè)域和反向解析配置項(xiàng)。?kubernetes 是 Kubernetes 插件的名稱,用于解析 Kubernetes 集群的服務(wù)和 Pod。?cluster.local 是 Kubernetes 集群內(nèi)部域名的默認(rèn)后綴。?in-addr.arpa 和 ip6.arpa 是用于反向 DNS 解析的 IPv4 和 IPv6 地址后綴。?pods insecure 允許對(duì) Pod 進(jìn)行非安全(insecure)的 DNS 解析。?fallthrough in-addr.arpa ip6.arpa 表示如果查詢未匹配到任何資源記錄,則繼續(xù)向下查詢反向 DNS 解析。 3.forward . /etc/resolv.conf 將未能解析的 DNS 請(qǐng)求轉(zhuǎn)發(fā)給 /etc/resolv.conf 文件中配置的其他 DNS 服務(wù)器。
大家也可以去看pod中中/etc/host和/etc/resolv.conf然后也能發(fā)現(xiàn)一些跡象。
結(jié)束語
至此,講清楚了集群中內(nèi)部服務(wù)之間是如何訪問的,且k8s是如何進(jìn)行尋址導(dǎo)致對(duì)應(yīng)的pod的,希望對(duì)大家有所幫助。
