Kubernetes網絡三部曲之三 ~ NodePort vs LoadBalancer vs Ingress

前言

在上一篇《Kubernetes網絡三部曲~Service網絡》中,波波講解了K8s的4層網絡棧中的第2層Service網路。有了Service網絡,K8s集羣內的應用可以通過服務名/ClusterIP進行統一尋址和訪問,而不需要關心應用集羣中到底有多少個Pods,Pod的IP是什麼,會不會變化,以及如何以負載均衡方式去訪問等問題。但是,K8s的Service網絡只是一個集羣內部網絡,集羣外部是無法直接訪問的。而我們發佈的應用,有些是需要暴露出去,要讓外網甚至公網能夠訪問的,這樣才能對外輸出業務價值。K8s如何將內部服務暴露出去?這是波波在本文要展開分析的問題。

在這裏插入圖片描述

在講到K8s如何接入外部流量的時候,大家常常會聽到NodePort,LoadBalancer和Ingress等概念,這些概念都是和K8s外部流量接入相關的,它們既是不同概念,同時又有關聯性。下面我們分別解釋這些概念和它們之間的關係。

NodePort

先提前強調一下,NodePort是K8s將內部服務對外暴露的基礎,後面的LoadBalancer底層有賴於NodePort

之前我們講了K8s網絡的4層抽象,Service網絡在第2層,節點網絡在第0層。實際上,只有節點網絡是可以直接對外暴露的,具體暴露方式要看數據中心或公有云的底層網絡部署,但不管採用何種部署,節點網絡對外暴露是完全沒有問題的。那麼現在的問題是,第2層的Service網絡如何通過第0層的節點網絡暴露出去?我們可以回看一下K8s服務發現的原理圖,如下圖所示,然後不妨思考一下,K8s集羣中有哪一個角色,即掌握Service網絡的所有信息,可以和Service網絡以及Pod網絡互通互聯,同時又可以和節點網絡打通?

在這裏插入圖片描述

答案是Kube-Proxy。上一篇我們提到Kube-Proxy是K8s內部服務發現的一個關鍵組件,事實上,它還是K8s將內部服務暴露出去的關鍵組件。Kube-Proxy在K8s集羣中所有Worker節點上都部署有一個,它掌握Service網絡的所有信息,知道怎麼和Service網絡以及Pod網絡互通互聯。如果要將Kube-Proxy和節點網絡打通(從而將某個服務通過Kube-Proxy暴露出去),只需要讓Kube-Proxy在節點上暴露一個監聽端口即可。這種通過Kube-Proxy在節點上暴露一個監聽端口,將K8s內部服務通過Kube-Proxy暴露出去的方式,術語就叫NodePort(顧名思義,端口暴露在節點上)。下圖是通過NodePort暴露服務的簡化概念模型。

在這裏插入圖片描述

如果我們要將K8s內部的一個服務通過NodePort方式暴露出去,可以將服務發佈(kind: Service)的type設定爲NodePort,同時指定一個30000~32767範圍內的端口。服務發佈以後,K8s在每個Worker節點上都會開啓這個監聽端口。這個端口的背後是Kube-Proxy,當K8s外部有Client要訪問K8s集羣內的某個服務,它通過這個服務的NodePort端口發起調用,這個調用通過Kube-Proxy轉發到內部的Servcie抽象層,然後再轉發到目標Pod上。Kube-Proxy轉發以及之後的環節,可以和上一篇《Kubernetes網絡三部曲~Service網絡》的內容對接起來。注意,爲了直觀形象,上圖的Service在K8s集羣中被畫成一個獨立組件,實際是沒有獨立Service這樣一個組件的,只是一個抽象概念,如果要理解這個抽象的底層實現細節,可以回頭看上一圖的K8s服務發現原理,或者回到上一篇《Kubernetes網絡三部曲~Service網絡》。

LoadBalancer

上面我們提到,將K8s內部的服務通過NodePort方式暴露出去,K8s會在每個Worker節點上都開啓對應的NodePort端口。邏輯上看,K8s集羣中的所有節點都會暴露這個服務,或者說這個服務是以集羣方式暴露的(實際支持這個服務的Pod可能就分佈在其中有限幾個節點上,但是因爲所有節點上都有Kube-Proxy,所以所有節點都知道該如何轉發)。既然是集羣,就會涉及負載均衡問題,誰負責對這個服務的負載均衡訪問?答案是需要引入負載均衡器(Load Balancer)。下圖是通過LoadBalancer,將服務對外暴露的概念模型。

在這裏插入圖片描述

假設我們有一套阿里雲K8s環境,要將K8s內部的一個服務通過LoadBalancer方式暴露出去,可以將服務發佈(Kind: Service)的type設定爲LoadBalancer。服務發佈後,阿里雲K8s不僅會自動創建服務的NodePort端口轉發,同時會自動幫我們申請一個SLB,有獨立公網IP,並且阿里雲K8s會幫我們自動把SLB映射到後臺K8s集羣的對應NodePort上。這樣,通過SLB的公網IP,我們就可以訪問到K8s內部服務,阿里雲SLB負載均衡器會在背後做負載均衡。

值得一提的是,如果是在本地開發測試環境裏頭搭建的K8s,一般不支持Load Balancer也沒必要,因爲通過NodePort做測試訪問就夠了。但是在生產環境或者公有云上的K8s,例如GCP或者阿里雲K8s,基本都支持自動創建Load Balancer。

Ingress

有了前面的NodePort + LoadBalancer,將K8s內部服務暴露到外網甚至公網的需求就已經實現了,那麼爲啥還要引入Ingress這樣一個概念呢?它起什麼作用?

我們知道在公有云(阿里雲/AWS/GCP)上,公網LB+IP是需要花錢買的。我們回看上圖的通過LoadBalancer(簡稱LB)暴露服務的方式,發現要暴露一個服務就需要購買一個獨立的LB+IP,如果要暴露十個服務就需要購買十個LB+IP,顯然,從成本考慮這是不划算也不可擴展的。那麼,有沒有辦法只需購買一個(或者少量)的LB+IP,但是卻可以按需暴露更多服務出去呢?答案其實不復雜,就是想辦法在K8內部部署一個獨立的反向代理服務,讓它做代理轉發。谷歌給這個內部獨立部署的反向代理服務起了一個奇怪的名字,就叫Ingress,它的簡化概念模型如下圖所示:

在這裏插入圖片描述

Ingress就是一個特殊的Service,通過節點的**HostPort(80/443)**暴露出去,前置一般也有LB做負載均衡。Ingress轉發到內部的其它服務,是通過集羣內的Service抽象層/ClusterIP進行轉發,最終轉發到目標服務Pod上。Ingress的轉發可以基於Path轉發,也可以基於域名轉發等方式,基本上你只需給它設置好轉發路由表即可,功能和Nginx無本質差別。

注意,上圖的Ingress概念模型是一種更抽象的畫法,隱去了K8s集羣中的節點,實際HostPort是暴露在節點上的。

所以,Ingress並不是什麼神奇的東西,首先,它本質上就是K8s集羣中的一個比較特殊的Service(發佈Kind: Ingress)。其次,這個Service提供的功能主要就是7層反向代理(也可以提供安全認證,監控,限流和SSL證書等高級功能),功能類似Nginx。第三,這個Service對外暴露出去是通過HostPort(80/443),可以和上面LoadBalancer對接起來。有了這個Ingress Service,我們可以做到只需購買一個LB+IP,就可以通過Ingress將內部多個(甚至全部)服務暴露出去,Ingress會幫忙做代理轉發。

那麼哪些軟件可以做這個Ingress?傳統的Nginx/Haproxy可以,現代的微服務網關Zuul/SpringCloudGateway/Kong/Envoy/Traefik等等都可以。當然,谷歌別出心裁給這個東東起名叫Ingress,它還是做了一些包裝,以簡化對Ingress的操作。如果你理解了原理,那麼完全可以用Zuul或者SpringCloudGateway,或者自己定製開發一個反向代理,來替代這個Ingress。部署的時候以普通Service部署,將type設定爲LoadBalancer即可,如下圖所示:

在這裏插入圖片描述

注意,Ingress是一個7層反向代理,如果你要暴露的是4層服務,還是需要走獨立LB+IP方式。

Kubectl Proxy & Port Forward

上面提到的服務暴露方案,包括NodePort/LoadBalancer/Ingress,主要針對正式生產環境。如果在本地開發測試環境,需要對本地部署的K8s環境中的服務或者Pod進行快速調試或測試,還有幾種簡易辦法,這邊一併簡單介紹下,如下圖所示:

在這裏插入圖片描述

  • 辦法一,通過kubectl proxy命令,在本機上開啓一個代理服務,通過這個代理服務,可以訪問K8s集羣內的任意服務。背後,這個Kubectl代理服務通過Master上的API Server間接訪問K8s集羣內服務,因爲Master知道集羣內所有服務信息。這種方式只限於7層HTTP轉發。
  • 辦法二,通過kubectl port-forward命令,它可以在本機上開啓一個轉發端口,間接轉發到K8s內部的某個Pod的端口上。這樣我們通過本機端口就可以訪問K8s集羣內的某個Pod。這種方式是TCP轉發,不限於HTTP。
  • 辦法三,通過kubectl exec命令直接連到Pod上去執行linux命令,功能類似docker exec。

總結

  1. NodePort是K8s內部服務對外暴露的基礎,LoadBalancer底層有賴於NodePort。NodePort背後是Kube-Proxy,Kube-Proxy是溝通Service網絡、Pod網絡和節點網絡的橋樑。
  2. 將K8s服務通過NodePort對外暴露是以集羣方式暴露的,每個節點上都會暴露相應的NodePort,通過LoadBalancer可以實現負載均衡訪問。公有云(如阿里雲/AWS/GCP)提供的K8s,都支持自動部署LB,且提供公網可訪問IP,LB背後對接NodePort。
  3. Ingress扮演的角色是對K8s內部服務進行集中反向代理,通過Ingress,我們可以同時對外暴露K8s內部的多個服務,但是隻需要購買1個(或者少量)LB。Ingress本質也是一種K8s的特殊Service,它也通過HostPort(80/443)對外暴露。
  4. 通過Kubectl Proxy或者Port Forward,可以在本地環境快速調試訪問K8s中的服務或Pod。
  5. K8s的Service發佈主要有3種type,type=ClusterIP,表示僅內部可訪問服務,type=NodePort,表示通過NodePort對外暴露服務,type=LoadBalancer,表示通過LoadBalancer對外暴露服務(底層對接NodePort,一般公有云才支持)。

至此,Kubernetes網絡三部曲全部講解完成,希望這三篇文章對你理解和用好K8s有幫助。下表是對三部曲的濃縮總結,是希望大家帶走記住的:

在這裏插入圖片描述

順便提一下,波波近期和極客時間合作,開設了一門叫《Spring Boot和K8s雲原生微服務實踐》的課程,以案例項目驅動形式,講解如何基於Spring Boot技術棧開發一個微服務SaaS應用,並最終將案例應用部署到本地和阿里雲K8s環境,歡迎大家關注學習。

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章