在一些項(xiàng)目和技術(shù)交流中,發(fā)現(xiàn)很多朋友對(duì)OCP pod通信機(jī)制和OCP中的DNS犯懵。我專(zhuān)門(mén)寫(xiě)一篇進(jìn)行分析。
創(chuàng)新互聯(lián)公司專(zhuān)注于企業(yè)全網(wǎng)營(yíng)銷(xiāo)推廣、網(wǎng)站重做改版、左權(quán)網(wǎng)站定制設(shè)計(jì)、自適應(yīng)品牌網(wǎng)站建設(shè)、H5建站、商城網(wǎng)站建設(shè)、集團(tuán)公司官網(wǎng)建設(shè)、成都外貿(mào)網(wǎng)站建設(shè)公司、高端網(wǎng)站制作、響應(yīng)式網(wǎng)頁(yè)設(shè)計(jì)等建站業(yè)務(wù),價(jià)格優(yōu)惠性價(jià)比高,為左權(quán)等各大城市提供網(wǎng)站開(kāi)發(fā)制作服務(wù)。本文中大量?jī)?nèi)容和K8S是相通的,文中也直接大量使用了K8S的概念,因此本文題目起的是K8S。OCP=OpenShift Container Platform,OCP內(nèi)部的SDN用的是OVS。
我們以反問(wèn)的方式進(jìn)行“靈魂拷問(wèn)”
拷問(wèn)1. OCP中pod之間通訊是否一定需要service?
不需要。
沒(méi)有service,pod能通信,而且好好的,如下圖所示。
在一個(gè)namespace里(因?yàn)橛衝etworkpolicy,因此先做這個(gè)假設(shè)),只要指定的端口是pod開(kāi)放的端口,在一個(gè)pod中,curl另外一個(gè)pod,就絕對(duì)能通。pod之間能不能通和倆pod跨不跨service,有沒(méi)有service,沒(méi)半毛錢(qián)關(guān)系。
拷問(wèn)2. 從一個(gè)pod curl另外一個(gè)pod+端口號(hào)能通這件事,背后的鏈路機(jī)制是什么?
(1)倆pod在一個(gè)節(jié)點(diǎn)上,鏈路如下,流量沒(méi)有繞出本宿主機(jī)的ovs:
Pod 1的eth0 → vethxx → br0 → vethyy → Pod 2的eth0
(2).倆pod在不同node上,鏈路如下,pod之間的通訊經(jīng)過(guò)了vxlan:
Pod 1的eth0 → vethxx → br0 → vxlan0 → host1 eth0(192.168.1.101)→ network → host2 eth0(192.168.1.102)→ vxlan0 → br0 → vethmm → Pod 3的eth0
也就是說(shuō),截止到目前,我們把倆pod之間的通訊機(jī)制,簡(jiǎn)單介紹了。這里面沒(méi)service啥事,這點(diǎn)記住。還需要記住的是,這是OCP集群中,pod之間通訊的實(shí)際數(shù)據(jù)鏈路(和后面service尋址對(duì)應(yīng))。
拷問(wèn)3:我們都知道K8S service的基本概念,說(shuō)說(shuō)為啥K8S需要它?
我們首先要明確:Service是對(duì)一組提供相同功能的Pods的抽象,并為它們提供一個(gè)統(tǒng)一的內(nèi)部訪問(wèn)入口。它主要解決:
1.負(fù)載均衡(這個(gè)大家會(huì)最先想到)。
2.服務(wù)注冊(cè)與發(fā)現(xiàn):解決不同服務(wù)之間的通信問(wèn)題。在OpenShift中的創(chuàng)建應(yīng)用后,需要提供訪問(wèn)應(yīng)用的地址供其他服務(wù)調(diào)用,這個(gè)地址就是由Service提供。
每創(chuàng)建一個(gè)Service會(huì)分配一個(gè)ServiceIP地址,稱為ClusterIP,這個(gè)IP地址是一個(gè)虛擬的地址,無(wú)法執(zhí)行ping操作。同時(shí)自動(dòng)在內(nèi)部DNS注冊(cè)一條對(duì)應(yīng)的A記錄(A記錄很重要,后面展開(kāi)說(shuō)),這就完成了服務(wù)注冊(cè),注冊(cè)信息全部保存在Etcd中。
拷問(wèn)4:詳細(xì)說(shuō)說(shuō)服務(wù)注冊(cè)到底向etcd里注冊(cè)了啥?
注冊(cè)到etcd的,實(shí)際上是service yaml的先關(guān)內(nèi)容。
我們查看etcd中router service 的內(nèi)容。我們看到了什么?
service name、namespace、service ip、port number的,以及對(duì)應(yīng)的endpoints等很多信息。
也就是說(shuō),etcd里有namespace,service name,service ip等,
通過(guò)這三個(gè)信息就可組成DNS A記錄,也就是,service的FQDN和service ip之間的對(duì)應(yīng)關(guān)系。但需要說(shuō)明的是,etcd不是DNS!DNS A記錄是通過(guò)查詢生成的!OCP的DNS是由SkyDNS/CoreDNS實(shí)現(xiàn)的,這個(gè)后面說(shuō)。
我們?cè)僬f(shuō)說(shuō)服務(wù)發(fā)現(xiàn)。
服務(wù)發(fā)現(xiàn)這個(gè)詞經(jīng)常被妖魔化。我們把字換個(gè)順序,就好理解:發(fā)現(xiàn)服務(wù)。也就說(shuō),service A要和serviceB通訊,我得知道serviceB是誰(shuí)、在哪、service IP、pod ip都是啥?這就叫服務(wù)發(fā)現(xiàn)。
拷問(wèn)5:有了servcice以后,pod之間的通訊和沒(méi)有service有啥區(qū)別?
在數(shù)據(jù)通訊層,沒(méi)區(qū)別!因?yàn)閟ervice只是邏輯層面的東西。
但是,沒(méi)有service,K8S是無(wú)法控制pod之間的通訊的,也無(wú)法為pod之間進(jìn)行尋址。也就是說(shuō),沒(méi)有service,pod之間的通訊,就不會(huì)和K8S發(fā)生任何關(guān)系,和自己在筆記本linux中裝起兩容器ping著玩,沒(méi)太大區(qū)別(在網(wǎng)絡(luò)層)。
有了service以后,pod之間怎么尋址?
回答這個(gè)問(wèn)題,我們要站在開(kāi)發(fā)者角度。如果一個(gè)程序員,要寫(xiě)微服務(wù),微服務(wù)之間要相互調(diào)用,怎么寫(xiě)?寫(xiě) pod IP和service ip都不靠譜吧,你都不知道IP地址會(huì)是啥。
如果程序員決定用k8s做服務(wù)發(fā)現(xiàn)的前提下寫(xiě)服務(wù)之間的調(diào)用(如果使用spring cloud,那就用它的服務(wù)注冊(cè)中心做解析,也就不必用K8S的service了),那么就得寫(xiě)K8S的service名稱!
因?yàn)閟ervice名稱我們是可以固定的。
K8S中service有短名和長(zhǎng)名。
以下圖為例,jws-app就是service的短名,service的長(zhǎng)名是:
那么,這時(shí)候大魏也有個(gè)疑問(wèn)了。如果在兩個(gè)不同的namespace中,有兩個(gè)相同的service短名,微服務(wù)調(diào)用不是會(huì)出現(xiàn)混亂?程序員的代碼里是不是要寫(xiě)service全名?
不能說(shuō)想法不對(duì),但一般不這樣干。
首先,站在OCP集群cluster-admin的角度,我們看所有的項(xiàng)目,有幾十個(gè)或者而更多,會(huì)覺(jué)得在不同namespaces中起相同的service短名是可能(比如namespace A中有個(gè)acat的service,namespace B中也有個(gè)acat的service)。但站在程序員角度,他只是OCP的使用者,他有自己的namespace,他能訪問(wèn)的namespace很有限,可能就1個(gè)。絕大多數(shù)情況下,同一個(gè)業(yè)務(wù)項(xiàng)目的微服務(wù)一般會(huì)運(yùn)行在同一個(gè)namespace中,默認(rèn)如果使用短名稱(只寫(xiě)service name),則會(huì)自動(dòng)補(bǔ)全成當(dāng)前namespace的FQDN,只有在跨namespace調(diào)用的時(shí)候才必須寫(xiě)全名FQDN。
所以,程序員寫(xiě)的程序,用到了K8S service name,那么,真正跑應(yīng)用的pod之間的通訊,也必然會(huì)以service name去找。通過(guò)service名稱找到service ip,然后最終找到pod ip(一個(gè)service可能多個(gè)pod,從service ip到pod ip的負(fù)載均衡實(shí)現(xiàn)后面講)。找到pod的ip以后,接下來(lái)實(shí)際的數(shù)據(jù)交換,就和拷問(wèn)2講述機(jī)制就接上頭了。
拷問(wèn)6. 我們知道Service的作用了,那從service ip到pod ip這段的負(fù)載均衡怎么實(shí)現(xiàn)的?
K8S中通過(guò)service name做服務(wù)發(fā)現(xiàn),選短名會(huì)自動(dòng)自動(dòng)擴(kuò)展成FQDN,然后解析成service ip,然后再走kube-proxy負(fù)載均衡倒pod ip。
Service的負(fù)載均衡可以由很多的實(shí)現(xiàn)方式,目前Kubernetes官方提供了三種代理模式:userspace、iptables、ipvs。目前版本OpenShift默認(rèn)的代理模式是iptables
從圖中可以看出,當(dāng)客戶端訪問(wèn)Servcie的ClusterIP時(shí),由Iptables實(shí)現(xiàn)負(fù)載均衡,選擇一個(gè)后端處理請(qǐng)求,默認(rèn)的負(fù)載均衡策略是輪詢。在這種模式下,每創(chuàng)建一個(gè)Service,會(huì)自動(dòng)匹配后端實(shí)例Pod記錄在Endpoints對(duì)象中,并在所有Node節(jié)點(diǎn)上添加相應(yīng)的iptables規(guī)則,將訪問(wèn)該Service的ClusterIP與Port的連接重定向到Endpoints中的某一個(gè)后端Pod,由于篇幅有限,關(guān)于負(fù)載均衡實(shí)現(xiàn)的細(xì)節(jié)不再贅述。
這種模式有兩個(gè)缺點(diǎn)需要關(guān)注:第一,不支持復(fù)雜的負(fù)載均衡算法;第二,當(dāng)選擇的某個(gè)后端Pod沒(méi)有響應(yīng)時(shí),無(wú)法自動(dòng)重新連接到另一個(gè)Pod,用戶必須利用Pod的健康監(jiān)測(cè)來(lái)保證Endpoints列表中Pod都是存活的(也就是說(shuō),生產(chǎn)上你好把liveness和rediness配上。)。
對(duì)于OCP而言,每個(gè)節(jié)點(diǎn)上都有iptables。而iptables之前的通訊和同步,是通過(guò)每個(gè)節(jié)點(diǎn)的kube-proxy實(shí)現(xiàn)的(這個(gè)進(jìn)程在sdn pod中運(yùn)行。想詳細(xì)研究的可以看我前兩天寫(xiě)的文章: 深度解析:kube-proxy在OpenShift上的實(shí)現(xiàn))
拷問(wèn)7. 我記得iptables不是做防火墻的么?
OCP中的iptables,主要目的做的是service ip和pod ip鏈路的事情。一般不涉及常規(guī)意義上的防火墻規(guī)則的INPUT/OUTPUT ACCEPT/DENY。也就是說(shuō),不要嘗試自己ssh到OCP4節(jié)點(diǎn)上通過(guò)iptables做安全規(guī)則,不是這樣玩的。
拷問(wèn)8. 前面7個(gè)問(wèn)題清楚了,說(shuō)說(shuō)OCP的DNS機(jī)制吧。
首先,OCP3和OCP4的DNS機(jī)制是不同的。
OpenShift 3內(nèi)置的是SkyDNS,SkyDNS會(huì)監(jiān)測(cè)Kubernetes API,當(dāng)新創(chuàng)建一個(gè)Service,SkyDNS中就會(huì)提供
例如,如果 myproject 服務(wù)中存在 myapi 服務(wù),則整個(gè)OpenShift集群中的所有Pod都可以解析 myapi.myproject.svc.cluster.local 主機(jī)名以獲取Service ClusterIP地址。除此之外,OpenShift DNS還提供以下兩種短域名:
在簡(jiǎn)單了解了SkyDNS的機(jī)制之后,我們來(lái)看看OpenShift3是如何使用和配置DNS的。為了便于理解,我們用下圖來(lái)進(jìn)行說(shuō)明。
上圖表示了OpenShift 3中DNS解析流程:
以上就是OpenShift 3中DNS的解析流程,核心是通過(guò)每個(gè)節(jié)點(diǎn)上運(yùn)行的Dnsmasq進(jìn)程做了SkyDNS和上游DNS的代理。
在OpenShift 3的DNS里面需要注意以下幾點(diǎn):
OpenShift 4的DNS
OpenShift 4使用CoreDNS替換了OpenShift 3使用的SkyDNS,起到的作用是一樣的,同樣是提供OpenShift內(nèi)部的域名解析服務(wù)。
在OpenShift 4中CoreDNS使用Operator實(shí)現(xiàn)部署,最終會(huì)創(chuàng)建出DaemonSet部署CoreDNS,也就是在每個(gè)節(jié)點(diǎn)會(huì)啟動(dòng)一個(gè)CoreDNS容器。在Kubelet將--cluster-dns設(shè)定為CoreDNS的ServiceClusterIP,這樣Pod中就可以使用CoreDNS進(jìn)行域名解析。
在安裝OpenShift 4時(shí),通過(guò)名為dns的Clusteroperator創(chuàng)建整個(gè)DNS堆棧,最終會(huì)在項(xiàng)目openshift-dns-operator下實(shí)例化一個(gè)dns pod完成具體的部署配置操作。
Cluster Domain定義了集群中Pod和Service域名的基本DNS域,默認(rèn)為cluster.local,域名服務(wù)的地址是CoreDNS的ClusterIP,是配置的Service IP CIDR網(wǎng)段中的第10個(gè)地址,默認(rèn)網(wǎng)段為172.30.0.0/16,第十個(gè)地址為172.30.0.10。DNS解析流程如下圖所示:
上圖表示了OpenShift 4的DNS解析流程
說(shuō)簡(jiǎn)單點(diǎn),在OCP中,隨便創(chuàng)建一個(gè)pod,這個(gè)pod中的name server都會(huì)指向到172.30.0.10,這是coredns pod的service ip。
我們查看coredns的pod和service ip:
我們?cè)L問(wèn)prometheus-k8s-0 這個(gè)pod進(jìn)行查看。
查看這個(gè)規(guī)則:
sh-4.2$ cat /etc/resolv.conf
search openshift-monitoring.svc.cluster.local svc.cluster.local cluster.local
nameserver 172.30.0.10
options ndots:5
我們查看宿主機(jī)的dns。
OCP宿主機(jī)的nameserver可以是數(shù)據(jù)中心內(nèi)部的,也可以自行構(gòu)建。
舉例說(shuō),如果我要在pod中nslookup baidu.com:
1.如果coredns pod中有緩存,直接返回
2. coredns pod中沒(méi)有緩存,coredns一看這是外部域名,不歸它管,他就會(huì)轉(zhuǎn)到宿主機(jī)指向的192.168.91.8去解析,如果這192.168.91.8也解析不了,那就看還有沒(méi)有上級(jí)的DNS了??傊糜衐ns把baidu.com能解析出來(lái)。如果在OCP在純離線的環(huán)境,baidu.com八成就解析失敗了。(數(shù)據(jù)中心內(nèi)部應(yīng)該沒(méi)人給baidu.com自己配解析)
好了,靈魂拷問(wèn)結(jié)束,這種拷問(wèn)方式是不是感覺(jué)比直接敘述看著爽一些?
本文標(biāo)題:靈魂拷問(wèn)x8:關(guān)于K8SPod通信和DNS那些事兒!
網(wǎng)頁(yè)路徑:http://www.rwnh.cn/article12/sddigc.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)頁(yè)設(shè)計(jì)公司、軟件開(kāi)發(fā)、網(wǎng)站內(nèi)鏈、用戶體驗(yàn)、手機(jī)網(wǎng)站建設(shè)、搜索引擎優(yōu)化
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)