解密OpenShift内部通信网络
上一篇:PaaS中OpenShift持久化存儲(chǔ)的管理實(shí)踐
由于 OpenShift 網(wǎng)絡(luò)通信概念較多,相對(duì)理解起來(lái)困難,為了方便讀者能夠清晰深入內(nèi)部,在開(kāi)始網(wǎng)絡(luò)模型講解之前,我們先嘗試從 OpenShift 的用戶(hù)角度,提出 5 個(gè)問(wèn)題,并對(duì) 5 個(gè)問(wèn)題作出解答,先對(duì) OpenShift 網(wǎng)絡(luò)通信有個(gè)大致的概念。然后讀者帶著對(duì)這 5 個(gè)問(wèn)題的理解,閱讀本章節(jié)更為詳細(xì)的內(nèi)容。
1. OpenShift 中 Pod 之間通訊是否一定需要 Service?
? ?
答案:Pod 之間的通信不需要 Service。
在同一個(gè) Namespace 中, Pod A 開(kāi)放了某個(gè)端口,在一個(gè) Pod B 中 curl pod_A_IP:port,就能與之通信,如下圖 2-45 所示。
圖 2-45 查看兩個(gè) pod 的 IP 地址
所以說(shuō):Pod 之間能不能通信,和兩個(gè) Pod 經(jīng)不經(jīng)過(guò) Service、有沒(méi)有 Service 無(wú)關(guān)。
2. 從一個(gè) Pod 訪問(wèn)另外一個(gè) Pod 可以通信,其數(shù)據(jù)鏈路是什么?
? ?
答案:兩個(gè) Pod 如果在一個(gè) OpenShift 節(jié)點(diǎn)上,其通信流量沒(méi)有繞出本宿主機(jī)的 OVS:如果兩個(gè) Pod 在不同節(jié)點(diǎn)上, Pod 之間的通信經(jīng)過(guò)了 Vxlan。具體內(nèi)容后文將展開(kāi)說(shuō)明。
3. 既然 Pod 之間通信不需要 Service,為何 Kubernetes 引入 Service?
? ?
我們首先要明確:Service 是對(duì)一組提供相同功能的 Pods 的抽象,并為它們提供一個(gè)統(tǒng)一的內(nèi)部訪問(wèn)入口。它主要解決:
負(fù)載均衡:Service 提供其所屬多個(gè) Pod 的負(fù)載均衡
服務(wù)注冊(cè)與發(fā)現(xiàn):解決不同服務(wù)之間的通信問(wèn)題。在 OpenShift 中的創(chuàng)建應(yīng)用后,需要提供訪問(wèn)應(yīng)用的地址供其他服務(wù)調(diào)用,這個(gè)地址就是由 Service 提供。
在 OpenShift 中,我們每創(chuàng)建一個(gè) Service,會(huì)分配一個(gè) IP 地址,稱(chēng)為 ClusterIP,這個(gè) IP 地址是一個(gè)虛擬的地址(OpenShift 外部不可達(dá)),這樣內(nèi)部 DNS 就可以通過(guò) Service 名稱(chēng)(FQDN)解析成 ClusterIP 地址。這就完成了服務(wù)注冊(cè),DNS 解析需要的信息全部保存在 Etcd 中。
那么,Service 注冊(cè)到 Etcd 的內(nèi)容是什么呢?
實(shí)際上是 Service 資源對(duì)象的 Yaml 包含的相關(guān)內(nèi)容。
也就是說(shuō),Etcd 中記錄的 Services 注冊(cè)信息里有 Namespace,Service Name,ClusterIP 等,通過(guò)這三個(gè)信息就可組成 DNS A 記錄,也就是,Service 的 FQDN 和 Service ip 之間的對(duì)應(yīng)關(guān)系。需要說(shuō)明的是,Etcd 不是 DNS,DNS A 記錄是通過(guò)查詢(xún)生成的。OpenShift 的 DNS 是由 SkyDNS/CoreDNS 實(shí)現(xiàn)的(后面內(nèi)容詳細(xì)介紹)。
服務(wù)發(fā)現(xiàn)這個(gè)詞經(jīng)常被妖魔化。它的作用是為了 OpenShift 某個(gè)服務(wù)發(fā)現(xiàn)另外一個(gè)服務(wù)。也就說(shuō),Service A 要和 ServiceB 通訊,我需要知道 ServiceB 是誰(shuí)、在哪、Cluster IP、對(duì)應(yīng)的 Pod IP 都是什么?這就叫服務(wù)發(fā)現(xiàn)。
4. 有了 Service 以后,Pod 之間的通訊和沒(méi)有 Service 有何區(qū)別?
? ?
在數(shù)據(jù)通訊層,沒(méi)區(qū)別,因?yàn)?Service 只是邏輯層面的東西。
但是,沒(méi)有 Service,多個(gè) Pod 無(wú)法實(shí)現(xiàn)統(tǒng)一入口,也無(wú)法實(shí)現(xiàn)負(fù)載均衡。也就是說(shuō),沒(méi)有 Service,多個(gè) Pod 之間的負(fù)載均衡就要依賴(lài)第三方實(shí)現(xiàn)。
那么,有了 Service 以后,Pod 之間怎么尋址?
回答這個(gè)問(wèn)題,我們要站在開(kāi)發(fā)者角度。如果一個(gè)程序員,要寫(xiě)微服務(wù),微服務(wù)之間要相互調(diào)用,怎么寫(xiě)?寫(xiě) Pod IP 和 ClusterIP 是不現(xiàn)實(shí)的,因?yàn)檫@兩個(gè) IP 可能發(fā)生變化。
如果程序員決定用 Kubernetes 做服務(wù)發(fā)現(xiàn)的前提下(如果使用微服務(wù)框架中的服務(wù)注冊(cè)中心做服務(wù)注冊(cè)發(fā)現(xiàn),可以不使用 Kubernetes 的 Service),實(shí)現(xiàn)不同服務(wù)之間的調(diào)用,那么就需要使用 Kubernetes 的 Service 名稱(chēng)。因?yàn)?Service 名稱(chēng)我們是可以固定的。
OpenShift/Kubernetes 中 Service 有短名和長(zhǎng)名。以下圖 2-46 為例,jws-app 就是 Service 的短名,Service 長(zhǎng)名的格式是:..svc.cluser.local,也就是 jws-app.web.svc.cluser.local。Service 短名可以自動(dòng)補(bǔ)充成長(zhǎng)名,這是 OpenShift 中的 DNS 做的,這個(gè)后面介紹。
圖 2-46 查看 Service 的名稱(chēng)
那么,如果在兩個(gè)不同的 Namespace 中,有兩個(gè)相同的 Service 短名,微服務(wù)調(diào)用不是會(huì)出現(xiàn)混亂?程序員的代碼里是不是要寫(xiě) Service 全名?
首先,站在 OpenShift 集群管理員的角度,我們看所有的項(xiàng)目,有幾十個(gè)或者而更多,會(huì)覺(jué)得在不同 Namespaces 中存在相同的 Service 短名是可能(比如 Namespace A 中有個(gè) acat 的 Service,Namespace B 中也有個(gè) acat 的 Service)。但站在程序員角度,他只是 OpenShift 的使用者、擁有有自己的 Namespace 的管理權(quán),其他 Namespace 不能訪問(wèn)。而且絕大多數(shù)情況下,同一個(gè)業(yè)務(wù)項(xiàng)目的微服務(wù)一般會(huì)運(yùn)行在同一個(gè) Namespace 中,默認(rèn)如果使用短名稱(chēng)(只寫(xiě) Service Name),則會(huì)自動(dòng)補(bǔ)全成當(dāng)前 Namespace 的 FQDN,只有在跨 Namespace 調(diào)用的時(shí)候才必須寫(xiě)全名 FQDN。
所以,程序員寫(xiě)的程序用到了 Service Name。那么,真正運(yùn)行應(yīng)用的 Pod 之間的通訊,也必然會(huì)以 Service Name 去找。通過(guò) Service 名稱(chēng)解析為 Service ClusterIP,然后經(jīng)過(guò) Kube-proxy(默認(rèn) Iptables 模式)的負(fù)載均衡最終選擇一個(gè)實(shí)際的 Pod IP。找到 Pod IP 以后,接下來(lái)就會(huì)進(jìn)行實(shí)際的數(shù)據(jù)交換,這就和 Service 沒(méi)有關(guān)系了。
5. ClusterIP 到 Pod IP 這部分的負(fù)載均衡怎么實(shí)現(xiàn)的?
? ?
目前版本 OpenShift 中是通過(guò) kube-proxy(iptables 模式)實(shí)現(xiàn)的。具體內(nèi)容后面內(nèi)容詳細(xì)介紹。
6
? ?
通過(guò)以上 5 個(gè)問(wèn)題的問(wèn)答,相信很多讀者關(guān)于 OpenShift 通信網(wǎng)絡(luò)的疑問(wèn)有了大致的了解。接下來(lái),我們針對(duì) OpenShift 的網(wǎng)絡(luò)通信展開(kāi)講述。
7
? ?
OpenShift 的網(wǎng)絡(luò)模型
OpenShift 的網(wǎng)絡(luò)模型繼承于 Kubernetes,從內(nèi)到外共包含如下四個(gè)方面:
Pod 內(nèi)部容器通信的的網(wǎng)絡(luò)。
Pod 與 Pod 通信的網(wǎng)絡(luò)。
Pod 和 Service 之間通信的網(wǎng)絡(luò)。
集群外部與 Service 或 Pod 通信的網(wǎng)絡(luò)。
這四部分構(gòu)成了整個(gè) OpenShift 的網(wǎng)絡(luò)模型,下面我們分別進(jìn)行說(shuō)明。
7.1
? ?
Pod 內(nèi)部容器通信的網(wǎng)絡(luò)
我們都知道 Pod 是一組容器的組合,意味著每個(gè) Pod 中可以有多個(gè)容器存在,那么這多個(gè)容器之間如何通信呢?這就是這部分要解決的問(wèn)題。
Kubernetes 通過(guò)為 Pod 分配統(tǒng)一的網(wǎng)絡(luò)空間,實(shí)現(xiàn)了多個(gè)容器之間網(wǎng)絡(luò)共享,也就是同一個(gè) Pod 中的容器之間通過(guò) Localhost 相互通信。
7.2
? ?
Pod 與 Pod 通信的網(wǎng)絡(luò)
關(guān)于這部分 Kubernetes 在設(shè)計(jì)之時(shí)的目標(biāo)就是 Pod 之間可以不經(jīng)過(guò) NAT 直接通信,即使 Pod 跨主機(jī)。而這部分 Kubernetes 早期并未提供統(tǒng)一標(biāo)準(zhǔn)的方案,需要用戶(hù)提前將節(jié)點(diǎn)網(wǎng)絡(luò)配置完成,各個(gè)廠商提供了不同的解決方案,諸如 Flannel、OVS 等等。隨著 Kubernetes 的發(fā)展,在網(wǎng)絡(luò)方向上希望通過(guò)統(tǒng)一的方式來(lái)集成不同的網(wǎng)絡(luò)方案,也就有了現(xiàn)在的網(wǎng)絡(luò)開(kāi)放接口 CNI(Container Network Interface)。
CNI 項(xiàng)目是由多個(gè)公司和項(xiàng)目創(chuàng)建組成的,包括 CoreOS、紅帽、Apache Mesos、Cloud Foundry、Kubernetes、Kurma 和 rkt。CoreOS 首先提出定義網(wǎng)絡(luò)插件和容器之間的通用接口,CNI 被設(shè)計(jì)為規(guī)范,它僅關(guān)注容器的網(wǎng)絡(luò)連接并在刪除容器時(shí)刪除分配的網(wǎng)絡(luò)資源。
CNI 有三個(gè)主要組成部分:
CNI 規(guī)范:定義容器運(yùn)行時(shí)和網(wǎng)絡(luò)插件之間的 API。
插件:對(duì)各種 SDN 對(duì)接的組件。
庫(kù):提供 CNI 規(guī)范的 Go 實(shí)現(xiàn),容器運(yùn)行時(shí)可以使用它來(lái)便捷地使用 CNI。
各廠商遵守規(guī)范開(kāi)發(fā)網(wǎng)絡(luò)組件,在技術(shù)實(shí)現(xiàn)上共分為兩大陣營(yíng):
基于二層實(shí)現(xiàn):通過(guò)將 Pod 放在一個(gè)大二層網(wǎng)絡(luò)中,跨節(jié)點(diǎn)通信通常使用 Vxlan 或 UDP 封包實(shí)現(xiàn),常用的此類(lèi)插件有 Flannel(UDP 或 Vxlan 封包模式)、OVS、Contiv、OVN 等。
基于三層實(shí)現(xiàn):將 Pod 放在一個(gè)互聯(lián)互通的網(wǎng)絡(luò)中,通常使用路由實(shí)現(xiàn),常用的此類(lèi)插件有 Calico、Flannel-GW、Contiv、OVN 等。
可以看到網(wǎng)絡(luò)插件的種類(lèi)較為繁多,OpenShift 默認(rèn)使用的是基于 OVS 的二層網(wǎng)絡(luò)實(shí)現(xiàn) Pod 與 Pod 之間的通信,后面我們將詳細(xì)介紹。
7.3
? ?
Pod 和 Service 之間通信的網(wǎng)絡(luò)
Pod 與 Service 之間的通信主要指在 Pod 中訪問(wèn) Service 的地址。在 OpenShift 中, Service 是對(duì)一組提供相同功能的 Pods 的抽象,并為它們提供一個(gè)統(tǒng)一的內(nèi)部訪問(wèn)入口。主要解決以下兩個(gè)問(wèn)題:
服務(wù)注冊(cè)與發(fā)現(xiàn):服務(wù)注冊(cè)發(fā)現(xiàn)在微服務(wù)架構(gòu)中,解決不同服務(wù)之間的通信問(wèn)題。在 OpenShift 中的創(chuàng)建應(yīng)用后,需要提供訪問(wèn)應(yīng)用的地址供其他服務(wù)調(diào)用,這個(gè)地址就是由 Service 提供。
每創(chuàng)建一個(gè) Service 會(huì)分配一個(gè) Service IP 地址,稱(chēng)為 ClusterIP,這個(gè) IP 地址是一個(gè)虛擬的地址,無(wú)法執(zhí)行 ping 操作。同時(shí)自動(dòng)在內(nèi)部 DNS 注冊(cè)一條對(duì)應(yīng)的 A 記錄,這就完成了服務(wù)注冊(cè),注冊(cè)信息全部保存在 Etcd 中。服務(wù)發(fā)現(xiàn)支持環(huán)境變量和 DNS 兩種方式,其中 DNS 的方式最為常用,關(guān)于 DNS 的部分我們將在后面章節(jié)詳細(xì)說(shuō)明。
負(fù)載均衡:每個(gè) Service 后端可能對(duì)應(yīng)多個(gè) Pod 示例,在訪問(wèn) Service 的時(shí)候需要選擇一個(gè)合適的后端處理請(qǐng)求。
Service 的負(fù)載均衡可以由很多的實(shí)現(xiàn)方式,目前 Kubernetes 官方提供了三種代理模式:userspace、iptables、ipvs。目前版本 OpenShift 默認(rèn)的代理模式是 iptables,本文主要介紹這種模式。有興趣的讀者參考 Kubernetes 官網(wǎng)中對(duì) Service 的介紹自行了解其他模式。
Iptables 模式官方示意圖如下圖 2-47 所示:
圖 2-47 Iptables 模式
從圖中可以看出,當(dāng)客戶(hù)端訪問(wèn) Servcie 的 ClusterIP 時(shí),由 Iptables 實(shí)現(xiàn)負(fù)載均衡,選擇一個(gè)后端處理請(qǐng)求,默認(rèn)的負(fù)載均衡策略是輪詢(xún)。在這種模式下,每創(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,用戶(hù)必須利用 Pod 的健康監(jiān)測(cè)來(lái)保證 Endpoints 列表中 Pod 都是存活的。
集群外部與 Service 或 Pod 通信的網(wǎng)絡(luò)上節(jié)中我們說(shuō)過(guò),創(chuàng)建 Service 分配的 ClusterIP 是一個(gè)虛擬 IP 地址,外部是無(wú)法訪問(wèn)的,那么該如何實(shí)現(xiàn)集群外部訪問(wèn)部署在集群中的應(yīng)用呢?
目前 OpenShift 共有以下五種對(duì)外暴露服務(wù)的方式:
Hostport
Nodeport
Hostnetwork
Ingress/router
LoadBalancer
不同方式的使用場(chǎng)景各不相同,關(guān)于每種方式的具體細(xì)節(jié)我們將在后面小節(jié)中進(jìn)行說(shuō)明。
8
? ?
多租戶(hù)的隔離
對(duì)于 OpenShift 來(lái)說(shuō),認(rèn)為一個(gè) Namespace 就是一個(gè)租戶(hù),實(shí)現(xiàn)多組戶(hù)隔離主要表現(xiàn)在網(wǎng)絡(luò)上,即每個(gè)租戶(hù)都擁有與其他租戶(hù)完全隔離的自有網(wǎng)絡(luò)環(huán)境。而 OpenShift 的網(wǎng)絡(luò)可以由多種第三方插件實(shí)現(xiàn),是否支持多租戶(hù)隔離要看選擇的 Pod 網(wǎng)絡(luò)插件。目前廣泛使用的是通過(guò)網(wǎng)絡(luò)策略控制網(wǎng)絡(luò)隔離,網(wǎng)絡(luò)策略采用了比較嚴(yán)格的單向流控制,最小粒度可控制到 Pod 與 Pod,而不僅僅是 Namespace 級(jí)別的隔離。
在了解了 OpenShift 網(wǎng)絡(luò)模型之后,可以看到 OpenShift 網(wǎng)絡(luò)涉及的范圍大而復(fù)雜,除了 Pod 內(nèi)部容器通信比較簡(jiǎn)單、無(wú)需管理之外,其余的四部分都是可以配置管理的,如替換不同的插件或者通過(guò)不同的方式實(shí)現(xiàn)。
本文選自《OpenShift 在企業(yè)中的實(shí)踐》(第 2 版),經(jīng)出版社授權(quán)發(fā)布。
推薦語(yǔ):經(jīng)典暢銷(xiāo)書(shū)再次升級(jí)!紅帽首席解決方案架構(gòu)師聯(lián)合撰寫(xiě),20位全球知名企業(yè)IT負(fù)責(zé)人推薦,基于OpenShift v4,詳述PaaS、DevOps、云原生、微服務(wù)治理。完整描繪企業(yè)數(shù)字化轉(zhuǎn)型路線,為企業(yè)通過(guò)OpenShift實(shí)現(xiàn)IT轉(zhuǎn)型給出具體建議和參考架構(gòu)。
推薦閱讀
分布領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)(DDD):領(lǐng)域接口化設(shè)計(jì)式緩存的選擇
2021-09-27
2W 字詳解設(shè)計(jì)模式!
2021-09-22
PaaS中OpenShift持久化存儲(chǔ)的管理實(shí)踐
2021-10-18
消息冪等(去重)通用解決方案,RocketMQ
2021-10-11
柴華:DDD在哈啰交易中臺(tái)的實(shí)踐
2021-09-02
肖然:DDD分層架構(gòu)的代碼結(jié)構(gòu)實(shí)戰(zhàn)
2021-08-26
資深架構(gòu)師談 DDD 興起,解決難題與實(shí)現(xiàn)步驟
2021-08-23
DDD 搭上了微服務(wù)這個(gè)順風(fēng)車(chē),又快又穩(wěn)
2021-07-15
從架構(gòu)演進(jìn)談 DDD 興起的原因以及與微服務(wù)的關(guān)系
2021-06-30
微服務(wù)等于Spring Cloud?了解微服務(wù)架構(gòu)和框架
2021-10-21
限流 & 熔斷的考量
2021-10-19
用企業(yè)架構(gòu)下好數(shù)字化轉(zhuǎn)型這盤(pán)大棋
2021-10-25
技術(shù)架構(gòu)的戰(zhàn)略和戰(zhàn)術(shù)原則
2021-10-25
2021 編程語(yǔ)言排行榜
2021-10-22
微服務(wù)等于Spring Cloud?了解微服務(wù)架構(gòu)和框架
2021-10-21
一個(gè)電商供應(yīng)鏈系統(tǒng)的DDD實(shí)戰(zhàn)
2021-10-20
新人創(chuàng)作打卡挑戰(zhàn)賽發(fā)博客就能抽獎(jiǎng)!定制產(chǎn)品紅包拿不停!總結(jié)
以上是生活随笔為你收集整理的解密OpenShift内部通信网络的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: hdu 4524 郑厂长系列故事——
- 下一篇: hdu 2570 迷障(贪心)