云原生系列「二」Kubernetes网络详解
前言
K8s是一個強大的平臺,但它的網(wǎng)絡(luò)比較復雜,涉及很多概念,例如Pod網(wǎng)絡(luò),Service網(wǎng)絡(luò),Cluster IPs,NodePort,LoadBalancer和Ingress等等,這么多概念足以讓新手望而生畏。但是,只有深入理解K8s網(wǎng)絡(luò),才能為理解和用好K8s打下堅實基礎(chǔ)。為了幫助大家理解,模仿TCP/IP協(xié)議棧,我把K8s的網(wǎng)絡(luò)分解為四個抽象層,從0到3,除了第0層,每一層都是構(gòu)建于前一層之上,如下圖所示:
第0層Node節(jié)點網(wǎng)絡(luò)比較好理解,也就是保證K8s節(jié)點(物理或虛擬機)之間能夠正常IP尋址和互通的網(wǎng)絡(luò),這個一般由底層(公有云或數(shù)據(jù)中心)網(wǎng)絡(luò)基礎(chǔ)設(shè)施支持。第0層我們假定已經(jīng)存在,所以不展開。第1到3層網(wǎng)絡(luò),我將分三篇文章,分別進行剖析,本文是第一篇Pod網(wǎng)絡(luò)。
注意,本文旨在幫助大家建立K8s網(wǎng)絡(luò)的概念模型,而不是對底層技術(shù)的精確描述。實際我們學技術(shù)以應(yīng)用為主,重要的是快速建立起直觀易懂的概念模型,能夠指導我們正常應(yīng)用即可,當然理解一定的技術(shù)細節(jié)也是有幫助的。另外,本文假定讀者對基本的網(wǎng)絡(luò)技術(shù),ip地址空間和容器技術(shù)等有一定的了解。
Pod網(wǎng)絡(luò)概念模型
Pod相當于是K8s云平臺中的虛擬機,它是K8s的基本調(diào)度單位。所謂Pod網(wǎng)絡(luò),就是能夠保證K8s集群中的所有Pods(包括同一節(jié)點上的,也包括不同節(jié)點上的Pods),邏輯上看起來都在同一個平面網(wǎng)絡(luò)內(nèi),能夠相互做IP尋址和通信的網(wǎng)絡(luò),下圖是Pod網(wǎng)絡(luò)的簡化概念模型:
Pod網(wǎng)絡(luò)構(gòu)建于Node節(jié)點網(wǎng)絡(luò)之上,它又是上層Service網(wǎng)絡(luò)的基礎(chǔ)。為了進一步理解Pod網(wǎng)絡(luò),我將對同一節(jié)點上的Pod之間的網(wǎng)絡(luò),以及不同節(jié)點上的Pod之間網(wǎng)絡(luò),分別進行剖析。
同一節(jié)點上的Pod網(wǎng)絡(luò)
前面提到,Pod相當于是K8s云平臺中的虛擬機,實際一個Pod中可以住一個或者多個(大多數(shù)場景住一個)應(yīng)用容器,這些容器共享Pod的網(wǎng)絡(luò)棧和其它資源如Volume。那么什么是共享網(wǎng)絡(luò)棧?同一節(jié)點上的Pod之間如何尋址和互通?我以下圖樣例來解釋:
上圖節(jié)點上展示了Pod網(wǎng)絡(luò)所依賴的3個網(wǎng)絡(luò)設(shè)備,eth0是節(jié)點主機上的網(wǎng)卡,這個是支持該節(jié)點流量出入的設(shè)備,也是支持集群節(jié)點間IP尋址和互通的設(shè)備。docker0是一個虛擬網(wǎng)橋,可以簡單理解為一個虛擬交換機,它是支持該節(jié)點上的Pod之間進行IP尋址和互通的設(shè)備。veth0則是Pod1的虛擬網(wǎng)卡,是支持該Pod內(nèi)容器互通和對外訪問的虛擬設(shè)備。docker0網(wǎng)橋和veth0網(wǎng)卡,都是linux支持和創(chuàng)建的虛擬網(wǎng)絡(luò)設(shè)備。
上圖Pod1內(nèi)部住了3個容器,它們都共享一個虛擬網(wǎng)卡veth0。內(nèi)部的這些容器可以通過localhost相互訪問,但是它們不能在同一端口上同時開啟服務(wù),否則會有端口沖突,這就是共享網(wǎng)絡(luò)棧的意思。Pod1中還有一個比較特殊的叫pause的容器,這個容器運行的唯一目的是為Pod建立共享的veth0網(wǎng)絡(luò)接口。如果你SSH到K8s集群中一個有Pod運行的節(jié)點上去,然后運行docker ps,可以看到通過pause命令運行的容器。
Pod的IP是由docker0網(wǎng)橋分配的,例如上圖docker0網(wǎng)橋的IP是172.17.0.1,它給第一個Pod1分配IP為172.17.0.2。如果該節(jié)點上再啟一個Pod2,那么相應(yīng)的分配IP為172.17.0.3,如果再啟動Pod可依次類推。因為這些Pods都連在同一個網(wǎng)橋上,在同一個網(wǎng)段內(nèi),它們可以進行IP尋址和互通,如下圖所示:
從上圖我們可以看到,節(jié)點內(nèi)Pod網(wǎng)絡(luò)在172.17.0.0/24這個地址空間內(nèi),而節(jié)點主機在10.100.0.0/24這個地址空間內(nèi),也就是說Pod網(wǎng)絡(luò)和節(jié)點網(wǎng)絡(luò)不在同一個網(wǎng)絡(luò)內(nèi),那么不同節(jié)點間的Pod該如何IP尋址和互通呢?下一節(jié)我們來分析這個問題。
不同節(jié)點間的Pod網(wǎng)絡(luò)
現(xiàn)在假設(shè)我們有兩個節(jié)點主機,host1(10.100.0.2)和host2(10.100.0.3),它們在10.100.0.0/24這個地址空間內(nèi)。host1上有一個PodX(172.17.0.2),host2上有一個PodY(172.17.1.3),Pod網(wǎng)絡(luò)在172.17.0.0/16這個地址空間內(nèi)。注意,Pod網(wǎng)絡(luò)的地址,是由K8s統(tǒng)一管理和分配的,保證集群內(nèi)Pod的IP地址唯一。我們發(fā)現(xiàn)節(jié)點網(wǎng)絡(luò)和Pod網(wǎng)絡(luò)不在同一個網(wǎng)絡(luò)地址空間內(nèi),那么host1上的PodX該如何與host2上的PodY進行互通?
實際上不同節(jié)點間的Pod網(wǎng)絡(luò)互通,有很多技術(shù)實現(xiàn)方案,底層的技術(shù)細節(jié)也很復雜。為了簡化描述,我把這些方案大體分為兩類,一類是路由方案,另外一類是覆蓋(Overlay)網(wǎng)絡(luò)方案。
如果底層的網(wǎng)絡(luò)是你可以控制的,比如說企業(yè)內(nèi)部自建的數(shù)據(jù)中心,并且你和運維團隊的關(guān)系比較好,可以采用路由方案,如下圖所示:
這個方案簡單理解,就是通過路由設(shè)備為K8s集群的Pod網(wǎng)絡(luò)單獨劃分網(wǎng)段,并配置路由器支持Pod網(wǎng)絡(luò)的轉(zhuǎn)發(fā)。例如上圖中,對于目標為172.17.1.0/24這個范圍內(nèi)的包,轉(zhuǎn)發(fā)到10.100.0.3這個主機上,同樣,對于目標為172.17.0.0/24這個范圍內(nèi)的包,轉(zhuǎn)發(fā)到10.100.0.2這個主機上。當主機的eth0接口接收到來自Pod網(wǎng)絡(luò)的包,就會向內(nèi)部網(wǎng)橋轉(zhuǎn)發(fā),這樣不同節(jié)點間的Pod就可以相互IP尋址和通信。這種方案依賴于底層的網(wǎng)絡(luò)設(shè)備,但是不引入額外性能開銷
如果底層的網(wǎng)絡(luò)是你無法控制的,比如說公有云網(wǎng)絡(luò),或者企業(yè)的運維團隊不支持路由方案,可以采用覆蓋(Overlay)網(wǎng)絡(luò)方案,如下圖所示:
所謂覆蓋網(wǎng)絡(luò),就是在現(xiàn)有網(wǎng)絡(luò)之上再建立一個虛擬網(wǎng)絡(luò),實現(xiàn)技術(shù)有很多,例如flannel/weavenet等等,這些方案大都采用隧道封包技術(shù)。簡單理解,Pod網(wǎng)絡(luò)的數(shù)據(jù)包,在出節(jié)點之前,會先被封裝成節(jié)點網(wǎng)絡(luò)的數(shù)據(jù)包,當數(shù)據(jù)包到達目標節(jié)點,包內(nèi)的Pod網(wǎng)絡(luò)數(shù)據(jù)包會被解封出來,再轉(zhuǎn)發(fā)給節(jié)點內(nèi)部的Pod網(wǎng)絡(luò)。這種方案對底層網(wǎng)絡(luò)沒有特別依賴,但是封包解包會引入額外性能開銷。
CNI簡介
考慮到Pod網(wǎng)絡(luò)實現(xiàn)技術(shù)眾多,為了簡化集成,K8s支持CNI(Container Network Interface)標準,不同的Pod網(wǎng)絡(luò)技術(shù)可以通過CNI插件形式和K8s進行集成。節(jié)點上的Kubelet通過CNI標準接口操作Pod網(wǎng)路,例如添加或刪除網(wǎng)絡(luò)接口等,它不需要關(guān)心Pod網(wǎng)絡(luò)的具體實現(xiàn)細節(jié)
總結(jié)
有了Pod網(wǎng)絡(luò),K8s集群內(nèi)的所有Pods在邏輯上都可以看作在一個平面網(wǎng)絡(luò)內(nèi),可以正常IP尋址和互通。但是Pod僅僅是K8s云平臺中的虛擬機抽象,最終,我們需要在K8s集群中運行的是應(yīng)用或者說服務(wù)(Service),而一個Service背后一般由多個Pods組成集群,這時候就引入了服務(wù)發(fā)現(xiàn)(Service Discovery)和負載均衡(Load Balancing)等問題。
Service網(wǎng)絡(luò)概念模型
我們假定第1層Pod網(wǎng)絡(luò)已經(jīng)存在,下圖是K8s的第2層Service網(wǎng)絡(luò)的簡化概念模型:
實際上,K8s通過在Client和Account-App的Pod集群之間引入一層Account-Serivce抽象,來解決上述問題:
K8s中為何要引入Service抽象?背后的原理是什么?后面我將以技術(shù)演進視角來解釋這些問題。
服務(wù)發(fā)現(xiàn)技術(shù)演進
DNS域名服務(wù)是一種較老且成熟的標準技術(shù),實際上DNS可以認為是最早的一種服務(wù)發(fā)現(xiàn)技術(shù)。
在K8s中引入DNS實現(xiàn)服務(wù)發(fā)現(xiàn)其實并不復雜,實際K8s本身就支持Kube-DNS組件。假設(shè)K8s引入DNS做服務(wù)發(fā)現(xiàn)(如上圖所示),運行時,K8s可以把Account-App的Pod集群信息(IP+Port等)自動注冊到DNS,Client應(yīng)用則通過域名查詢DNS發(fā)現(xiàn)目標Pod,然后發(fā)起調(diào)用。這個方案不僅簡單,而且對Client也無侵入(目前幾乎所有的操作系統(tǒng)都自帶DNS客戶端)。但是基于DNS的服務(wù)發(fā)現(xiàn)也有如下問題:
考慮到上述不同DNS客戶端實現(xiàn)的差異,不在K8s控制范圍內(nèi),所以K8s沒有直接采用DNS技術(shù)做服務(wù)發(fā)現(xiàn)。注意,實際K8s是引入Kube-DNS支持通過域名訪問服務(wù)的,不過這是建立在CusterIP/Service網(wǎng)絡(luò)之上,這個我后面會展開。
另外一種較新的服務(wù)發(fā)現(xiàn)技術(shù),是引入Service Registry+Client配合實現(xiàn),在當下微服務(wù)時代,這是一個比較流行的做法。目前主流的產(chǎn)品,如Netflix開源的Eureka + Ribbon,HashiCorp開源的Consul,還有阿里新開源Nacos等,都是這個方案的典型代表。
在K8s中引入Service Registry實現(xiàn)服務(wù)發(fā)現(xiàn)也不復雜,K8s自身帶分布式存儲etcd就可以實現(xiàn)Service Registry。假設(shè)K8s引入Service Registry做服務(wù)發(fā)現(xiàn)(如上圖所示),運行時K8s可以把Account-App和Pod集群信息(IP + Port等)自動注冊到Service Registry,Client應(yīng)用則通過Service Registry查詢發(fā)現(xiàn)目標Pod,然后發(fā)起調(diào)用。這個方案也不復雜,而且客戶端可以實現(xiàn)靈活的負載均衡策略,但是需要引入客戶端配合,對客戶應(yīng)用有侵入性,所以K8s也沒有直接采用這種方案。
K8s雖然沒有直接采用上述方案,但是它的Service網(wǎng)絡(luò)實現(xiàn)是在上面兩種技術(shù)的基礎(chǔ)上擴展演進出來的。它融合了上述方案的優(yōu)點,同時解決了上述方案的不足,下節(jié)我會詳細剖析K8s的Service網(wǎng)絡(luò)的實現(xiàn)原理,前面提到,K8s的服務(wù)發(fā)現(xiàn)機制是在上節(jié)講的Service Registry + DNS基礎(chǔ)上發(fā)展演進出來的,下圖展示K8s服務(wù)發(fā)現(xiàn)的簡化原理:
在K8s平臺的每個Worker節(jié)點上,都部署有兩個組件,一個叫Kubelet,另外一個叫Kube-Proxy,這兩個組件+Master是K8s實現(xiàn)服務(wù)注冊和發(fā)現(xiàn)的關(guān)鍵。下面我們看下簡化的服務(wù)注冊發(fā)現(xiàn)流程。
- 首先,在服務(wù)Pod實例發(fā)布時(可以對應(yīng)K8s發(fā)布中的Kind: Deployment),Kubelet會負責啟動Pod實例,啟動完成后,Kubelet會把服務(wù)的PodIP列表匯報注冊到Master節(jié)點。
- 其次,通過服務(wù)Service的發(fā)布(對應(yīng)K8s發(fā)布中的Kind: Service),K8s會為服務(wù)分配ClusterIP,相關(guān)信息也記錄在Master上。
- 第三,在服務(wù)發(fā)現(xiàn)階段,Kube-Proxy會監(jiān)聽Master并發(fā)現(xiàn)服務(wù)ClusterIP和PodIP列表映射關(guān)系,并且修改本地的linux iptables轉(zhuǎn)發(fā)規(guī)則,指示iptables在接收到目標為某個ClusterIP請求時,進行負載均衡并轉(zhuǎn)發(fā)到對應(yīng)的PodIP上。
- 運行時,當有消費者Pod需要訪問某個目標服務(wù)實例的時候,它通過ClusterIP發(fā)起調(diào)用,這個ClusterIP會被本地iptables機制截獲,然后通過負載均衡,轉(zhuǎn)發(fā)到目標服務(wù)Pod實例上。
實際消費者Pod也并不直接調(diào)服務(wù)的ClusterIP,而是先調(diào)用服務(wù)名,因為ClusterIP也會變(例如針對TEST/UAT/PROD等不同環(huán)境的發(fā)布,ClusterIP會不同),只有服務(wù)名一般不變。為了屏蔽ClusterIP的變化,K8s在每個Worker節(jié)點上還引入了一個KubeDNS組件,它也監(jiān)聽Master并發(fā)現(xiàn)服務(wù)名和ClusterIP之間映射關(guān)系,這樣, 消費者Pod通過KubeDNS可以間接發(fā)現(xiàn)服務(wù)的ClusterIP。
注意,K8s的服務(wù)發(fā)現(xiàn)機制和目前微服務(wù)主流的服務(wù)發(fā)現(xiàn)機制(如Eureka + Ribbon)總體原理類似,但是也有顯著區(qū)別(這些區(qū)別主要體現(xiàn)在客戶端):
個人認為,對比目前微服務(wù)主流的服務(wù)發(fā)現(xiàn)機制,K8s的服務(wù)發(fā)現(xiàn)機制抽象得更好,它通過ClusterIP統(tǒng)一屏蔽服務(wù)發(fā)現(xiàn)和負載均衡,一個服務(wù)一個ClusterIP,這個模型和傳統(tǒng)的IP網(wǎng)絡(luò)模型更貼近和易于理解。ClusterIP也是一個IP,但這個IP后面跟的不是一個服務(wù)實例,而是一個服務(wù)集群,所以叫集群ClusterIP。同時,它對客戶應(yīng)用無侵入,且不穿透沒有額外性能損耗。
總結(jié)
有了Service抽象,K8s中部署的應(yīng)用都可以通過一個抽象的ClusterIP進行尋址訪問,并且消費方不需要關(guān)心這個ClusterIP后面究竟有多少個Pod實例,它們的PodIP是什么,會不會變化,如何以負載均衡方式去訪問等問題。但是,K8s的Service網(wǎng)絡(luò)只是一個集群內(nèi)可見的內(nèi)部網(wǎng)絡(luò),集群外部是看不到Service網(wǎng)絡(luò)的,也無法直接訪問。而我們發(fā)布應(yīng)用,有些是需要暴露出去,要讓外網(wǎng)甚至公網(wǎng)能夠訪問的,這樣才能對外提供服務(wù)。K8s如何將內(nèi)部服務(wù)暴露出去?
在講到K8s如何接入外部流量的時候,大家常常會聽到NodePort,LoadBalancer和Ingress等概念,這些概念都是和K8s外部流量接入相關(guān)的,它們既是不同概念,同時又有關(guān)聯(lián)性。下面我們分別解釋這些概念和它們之間的關(guān)系。
NodePort
先提前強調(diào)一下,NodePort是K8s將內(nèi)部服務(wù)對外暴露的基礎(chǔ),后面的LoadBalancer底層有賴于NodePort。
之前我們講了K8s網(wǎng)絡(luò)的4層抽象,Service網(wǎng)絡(luò)在第2層,節(jié)點網(wǎng)絡(luò)在第0層。實際上,只有節(jié)點網(wǎng)絡(luò)是可以直接對外暴露的,具體暴露方式要看數(shù)據(jù)中心或公有云的底層網(wǎng)絡(luò)部署,但不管采用何種部署,節(jié)點網(wǎng)絡(luò)對外暴露是完全沒有問題的。那么現(xiàn)在的問題是,第2層的Service網(wǎng)絡(luò)如何通過第0層的節(jié)點網(wǎng)絡(luò)暴露出去?我們可以回看一下K8s服務(wù)發(fā)現(xiàn)的原理圖,如下圖所示,然后不妨思考一下,K8s集群中有哪一個角色,即掌握Service網(wǎng)絡(luò)的所有信息,可以和Service網(wǎng)絡(luò)以及Pod網(wǎng)絡(luò)互通互聯(lián),同時又可以和節(jié)點網(wǎng)絡(luò)打通?
答案是Kube-Proxy。上一篇我們提到Kube-Proxy是K8s內(nèi)部服務(wù)發(fā)現(xiàn)的一個關(guān)鍵組件,事實上,它還是K8s將內(nèi)部服務(wù)暴露出去的關(guān)鍵組件。Kube-Proxy在K8s集群中所有Worker節(jié)點上都部署有一個,它掌握Service網(wǎng)絡(luò)的所有信息,知道怎么和Service網(wǎng)絡(luò)以及Pod網(wǎng)絡(luò)互通互聯(lián)。如果要將Kube-Proxy和節(jié)點網(wǎng)絡(luò)打通(從而將某個服務(wù)通過Kube-Proxy暴露出去),只需要讓Kube-Proxy在節(jié)點上暴露一個監(jiān)聽端口即可。這種通過Kube-Proxy在節(jié)點上暴露一個監(jiān)聽端口,將K8s內(nèi)部服務(wù)通過Kube-Proxy暴露出去的方式,術(shù)語就叫NodePort(顧名思義,端口暴露在節(jié)點上)。下圖是通過NodePort暴露服務(wù)的簡化概念模型。
如果我們要將K8s內(nèi)部的一個服務(wù)通過NodePort方式暴露出去,可以將服務(wù)發(fā)布(kind: Service)的type設(shè)定為NodePort,同時指定一個30000~32767范圍內(nèi)的端口。服務(wù)發(fā)布以后,K8s在每個Worker節(jié)點上都會開啟這個監(jiān)聽端口。這個端口的背后是Kube-Proxy,當K8s外部有Client要訪問K8s集群內(nèi)的某個服務(wù),它通過這個服務(wù)的NodePort端口發(fā)起調(diào)用,這個調(diào)用通過Kube-Proxy轉(zhuǎn)發(fā)到內(nèi)部的Servcie抽象層,然后再轉(zhuǎn)發(fā)到目標Pod上。Kube-Proxy轉(zhuǎn)發(fā)以及之后的環(huán)節(jié),可以和上一篇《Kubernetes網(wǎng)絡(luò)三部曲~Service網(wǎng)絡(luò)》的內(nèi)容對接起來。注意,為了直觀形象,上圖的Service在K8s集群中被畫成一個獨立組件,實際是沒有獨立Service這樣一個組件的,只是一個抽象概念,如果要理解這個抽象的底層實現(xiàn)細節(jié),可以回頭看上一圖的K8s服務(wù)發(fā)現(xiàn)原理,或者回到上一篇《Kubernetes網(wǎng)絡(luò)三部曲~Service網(wǎng)絡(luò)》。
LoadBalancer
上面我們提到,將K8s內(nèi)部的服務(wù)通過NodePort方式暴露出去,K8s會在每個Worker節(jié)點上都開啟對應(yīng)的NodePort端口。邏輯上看,K8s集群中的所有節(jié)點都會暴露這個服務(wù),或者說這個服務(wù)是以集群方式暴露的(實際支持這個服務(wù)的Pod可能就分布在其中有限幾個節(jié)點上,但是因為所有節(jié)點上都有Kube-Proxy,所以所有節(jié)點都知道該如何轉(zhuǎn)發(fā))。既然是集群,就會涉及負載均衡問題,誰負責對這個服務(wù)的負載均衡訪問?答案是需要引入負載均衡器(Load Balancer)。下圖是通過LoadBalancer,將服務(wù)對外暴露的概念模型。
假設(shè)我們有一套阿里云K8s環(huán)境,要將K8s內(nèi)部的一個服務(wù)通過LoadBalancer方式暴露出去,可以將服務(wù)發(fā)布(Kind: Service)的type設(shè)定為LoadBalancer。服務(wù)發(fā)布后,阿里云K8s不僅會自動創(chuàng)建服務(wù)的NodePort端口轉(zhuǎn)發(fā),同時會自動幫我們申請一個SLB,有獨立公網(wǎng)IP,并且阿里云K8s會幫我們自動把SLB映射到后臺K8s集群的對應(yīng)NodePort上。這樣,通過SLB的公網(wǎng)IP,我們就可以訪問到K8s內(nèi)部服務(wù),阿里云SLB負載均衡器會在背后做負載均衡。
值得一提的是,如果是在本地開發(fā)測試環(huán)境里頭搭建的K8s,一般不支持Load Balancer也沒必要,因為通過NodePort做測試訪問就夠了。但是在生產(chǎn)環(huán)境或者公有云上的K8s,例如GCP或者阿里云K8s,基本都支持自動創(chuàng)建Load Balancer。
Ingress
有了前面的NodePort + LoadBalancer,將K8s內(nèi)部服務(wù)暴露到外網(wǎng)甚至公網(wǎng)的需求就已經(jīng)實現(xiàn)了,那么為啥還要引入Ingress這樣一個概念呢?它起什么作用?
我們知道在公有云(阿里云/AWS/GCP)上,公網(wǎng)LB+IP是需要花錢買的。我們回看上圖的通過LoadBalancer(簡稱LB)暴露服務(wù)的方式,發(fā)現(xiàn)要暴露一個服務(wù)就需要購買一個獨立的LB+IP,如果要暴露十個服務(wù)就需要購買十個LB+IP,顯然,從成本考慮這是不劃算也不可擴展的。那么,有沒有辦法只需購買一個(或者少量)的LB+IP,但是卻可以按需暴露更多服務(wù)出去呢?答案其實不復雜,就是想辦法在K8內(nèi)部部署一個獨立的反向代理服務(wù),讓它做代理轉(zhuǎn)發(fā)。谷歌給這個內(nèi)部獨立部署的反向代理服務(wù)起了一個奇怪的名字,就叫Ingress,它的簡化概念模型如下圖所示:
Ingress就是一個特殊的Service,通過節(jié)點的**HostPort(80/443)**暴露出去,前置一般也有LB做負載均衡。Ingress轉(zhuǎn)發(fā)到內(nèi)部的其它服務(wù),是通過集群內(nèi)的Service抽象層/ClusterIP進行轉(zhuǎn)發(fā),最終轉(zhuǎn)發(fā)到目標服務(wù)Pod上。Ingress的轉(zhuǎn)發(fā)可以基于Path轉(zhuǎn)發(fā),也可以基于域名轉(zhuǎn)發(fā)等方式,基本上你只需給它設(shè)置好轉(zhuǎn)發(fā)路由表即可,功能和Nginx無本質(zhì)差別。
注意,上圖的Ingress概念模型是一種更抽象的畫法,隱去了K8s集群中的節(jié)點,實際HostPort是暴露在節(jié)點上的。
所以,Ingress并不是什么神奇的東西,首先,它本質(zhì)上就是K8s集群中的一個比較特殊的Service(發(fā)布Kind: Ingress)。其次,這個Service提供的功能主要就是7層反向代理(也可以提供安全認證,監(jiān)控,限流和SSL證書等高級功能),功能類似Nginx。第三,這個Service對外暴露出去是通過HostPort(80/443),可以和上面LoadBalancer對接起來。有了這個Ingress Service,我們可以做到只需購買一個LB+IP,就可以通過Ingress將內(nèi)部多個(甚至全部)服務(wù)暴露出去,Ingress會幫忙做代理轉(zhuǎn)發(fā)。
那么哪些軟件可以做這個Ingress?傳統(tǒng)的Nginx/Haproxy可以,現(xiàn)代的微服務(wù)網(wǎng)關(guān)Zuul/SpringCloudGateway/Kong/Envoy/Traefik等等都可以。當然,谷歌別出心裁給這個東東起名叫Ingress,它還是做了一些包裝,以簡化對Ingress的操作。如果你理解了原理,那么完全可以用Zuul或者SpringCloudGateway,或者自己定制開發(fā)一個反向代理,來替代這個Ingress。部署的時候以普通Service部署,將type設(shè)定為LoadBalancer即可,如下圖所示:
注意,Ingress是一個7層反向代理,如果你要暴露的是4層服務(wù),還是需要走獨立LB+IP方式。
Kubectl Proxy & Port Forward
上面提到的服務(wù)暴露方案,包括NodePort/LoadBalancer/Ingress,主要針對正式生產(chǎn)環(huán)境。如果在本地開發(fā)測試環(huán)境,需要對本地部署的K8s環(huán)境中的服務(wù)或者Pod進行快速調(diào)試或測試,還有幾種簡易辦法,這邊一并簡單介紹下,如下圖所示:
- 辦法一,通過kubectl proxy命令,在本機上開啟一個代理服務(wù),通過這個代理服務(wù),可以訪問K8s集群內(nèi)的任意服務(wù)。背后,這個Kubectl代理服務(wù)通過Master上的API Server間接訪問K8s集群內(nèi)服務(wù),因為Master知道集群內(nèi)所有服務(wù)信息。這種方式只限于7層HTTP轉(zhuǎn)發(fā)。
- 辦法二,通過kubectl port-forward命令,它可以在本機上開啟一個轉(zhuǎn)發(fā)端口,間接轉(zhuǎn)發(fā)到K8s內(nèi)部的某個Pod的端口上。這樣我們通過本機端口就可以訪問K8s集群內(nèi)的某個Pod。這種方式是TCP轉(zhuǎn)發(fā),不限于HTTP。
- 辦法三,通過kubectl exec命令直接連到Pod上去執(zhí)行l(wèi)inux命令,功能類似docker exec。
總結(jié)
至此,Kubernetes網(wǎng)絡(luò)三部曲全部講解完成,希望這三篇文章對你理解和用好K8s有幫助。下表是對三部曲的濃縮總結(jié),是希望大家?guī)ё哂涀〉?#xff1a;
總結(jié)
以上是生活随笔為你收集整理的云原生系列「二」Kubernetes网络详解的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: spring中注解无法修饰静态变量
- 下一篇: MySQL定时归档