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