Kubernetes Ingress簡單入門

RancherLabs發表於2020-05-26

作者:Nick Ramirez

原文連結:https://thenewstack.io/kubernetes-ingress-for-beginners/

本文轉載自Rancher Labs

不知道你是否注意到一個奇怪的現象,儘管Kubernetes Ingress API仍然處於beta狀態,但是已經有許多公司使用它來暴露Kubernetes服務。從事相關專案的工程師表示,Kubernetes Ingress API越來越有可能摘下其beta標籤。實際上,Kubernetes Ingress API處於beta狀態已經持續了幾年的時間,準確來說,是在2015年秋季開始進入該階段的。但是,漫長的beta階段可以讓Kubernetes貢獻者有時間來完善規範並使其與已經搭建好的實施軟體(HAProxy、NGINX、Traefik等)保持一致,從而使API標準化以反映最常見並且有需求的功能。

隨著該功能GA的臨近,那麼現在應該是一個合適的時機可以幫助新手快速瞭解Ingress的工作方式。簡而言之,Ingress是一個規則,可以繪製出在叢集內部的服務如何彌合鴻溝,暴露到客戶可以使用它的外部世界。同時,稱為Ingress controller的代理在叢集網路的邊緣進行偵聽(監視要新增的規則),並將每個服務對映到特定的URL路徑或域名以供公眾使用。在Kubernetes維護者開發API的同時,其他開源專案也實現了Ingress Controller併為其代理新增了自己的獨特功能。

在本文中,我將介紹這些概念,並幫助你瞭解Ingress模式背後的驅動力。

路由問題

在Kubernetes中建立Pod時,需要為其分配selector標籤,如Deployment manifest的以下片段所示:

該Deployment建立了執行Docker映象my-app的三個副本,併為其分配app=foo標籤。除了直接訪問Pod,通常將它們分組在Service下,這使它們可以在單個叢集IP地址上使用(但是隻能在同一叢集中使用)。Service充當抽象層,隱藏了pod的週期短暫特性,可以隨時增加或減少或替換它們。它還可以執行基本的迴圈負載均衡。

例如,以下Service定義收集所有帶有selector標籤app = foo的Pod,並在其中平均路由流量。

但是,只能從叢集內部以及執行在附近的其他Pod訪問此服務。Kubernetes Operator正在努力解決如何為叢集外部的客戶端提供訪問許可權。該問題在早期就已經出現,並且將兩種機制直接整合到Service規範中進行處理。編寫service manifest時,包括一個名為type的欄位,該欄位的值為NodePortLoadBalancer。這是一個將型別設定為NodePort的示例:

NodePort型別的服務使用起來很簡單。本質上,這些服務希望Kubernetes API為他們分配一個隨機的TCP埠,並將其暴露到叢集之外。這樣做的方便之處在於,客戶端可以使用該埠將叢集中的任何節點作為目標,並且他們的訊息將被中轉到正確的位置。這就類似於你可以撥打美國境內的任何電話,而接聽電話的人都會確保為你轉接到合適的人。

缺點在於,該埠的值必須介於30000到32767之間,雖然這個範圍安全地避開了常用埠地範圍,但是與常見的HTTP埠80和HTTPS 443相比,該埠顯然不是很標準。此外,隨機性本身也是一個障礙,因為它意味著你事先不知道值是什麼,這使得配置NAT、防火牆規則更具挑戰性——尤其是需要為每項服務設定不同的隨機埠。

另一個選項是將型別設定為LoadBalancer。但是,這有一些前提條件——僅當你在GKE或EKS之類的雲託管環境中執行並且可以使用該雲供應商的負載均衡器技術時,它才有效,因為它是自動選擇並配置的。其缺點是比較昂貴,因為使用這種型別的服務會為每個服務啟動一個託管的負載均衡器以及一個新的公共IP地址,這會產生額外的費用。

Ingress路由

分配一個隨機埠或外部負載均衡器是很容易操作的,但也帶來了獨特的挑戰。定義許多NodePort服務會造成隨機埠混亂,而定義許多負載均衡器服務會導致需要支付比實際所需更多的雲資源費用。這些情況不可能完全避免,但也許可以減少它的使用範圍,甚至你只需要分配1個隨機埠或1個負載均衡器就能夠暴露許多內部服務。因此,這一平臺需要一個新的抽象層,該層可以在入口點(entrypoint)後面整合許多服務。

那時,Kubernetes API引入了一種稱為Ingress的新型manifest,它為路由問題提供了新的思路。它的工作方式是這樣的:你編寫一個Ingress manifest,宣告你希望客戶端如何路由到服務。manifest實際上並不自行執行任何操作,你必須將Ingress Controller部署到你的叢集中,以監視這些宣告並對其執行操作。

與其他任何應用程式一樣,Ingress controller是Pod,因此它們是叢集的一部分並且可以看到其他Pod。它們是使用在市場上已經發展了多年的反向代理搭建的,因此,你可以選擇HAProxy Ingress Controller、NGINX Ingress Controller等。底層代理為其提供了第7層路由和負載均衡功能。不同的代理將自己的功能集放到表中。例如,HAProxy Ingress Controller不需要像NGINX Ingress Controller那樣頻繁地重新載入,因為它為伺服器分配了slot,並使用Runtime API在執行時填充slot。這使得該Ingress Controller擁有更好的效能。

Ingress Controller本身位於叢集內部,與其他Kubernetes Pod一樣,也容易受到同一“監獄”的“監禁”。你需要通過NodePort或LoadBalancer型別的服務將它們暴露到外部。但是,現在你只有一個入口點,所有流量都將通過此處:一個服務連線到一個Ingress Controller,Ingress Controller依次連線到許多內部Pod。Controller具有檢查HTTP請求的功能,可以根據其發現的特徵(例如URL路徑或域名)將客戶端定向到正確的Pod。

參考這個Ingress的示例,該示例定義了URL路徑/foo應該如何連線到名為foo-service的後端服務,而URL路徑/bar被定向到名稱為bar-service的服務。

如上文所示,你依舊需要為你的Pod設定服務,但是你不需要在Pod上設定型別欄位,因為路由和負載均衡將由Ingress層處理。服務的作用被簡化為以通用名稱對Pod進行分組。最終,兩個路徑,/foo和/bar,將由一個公共IP地址和域名提供服務,例如example.com/fooexample.com/bar 。本質上,這是API閘道器模式,在API閘道器中,單個地址將請求路由到多個後端應用程式。

新增Ingress Controller

Ingress manifest的宣告式方法是你可以指定所需的內容,而無需知道如何實現。Ingress Controller的工作之一是執行,它需要監控新的ingress規則並配置其底層代理以制定相應的路由。

你可以使用Kubernetes包管理工具Helm安裝HAProxy Ingress Controller。首先,通過下載Helm二進位制檔案並將其複製到PATH環境變數中包含的資料夾(例如/usr/local/bin/)中來安裝Helm。接下來,新增HAProxy Technologies Helm庫,並使用helm install命令部署Ingress Controller。

通過執行命令kubectl get service列出所有正在執行的服務來驗證是否已建立Ingress Controller。

HAProxy Ingress Controller在叢集的pod中執行,並使用NodePort型別的Service資源釋出對外部客戶端的訪問。在上面顯示的輸出中,你可以看到為HTTP選擇了埠31704,為HTTPS選擇了埠32255。你還可以在埠30347上檢視HAProxy資訊統計頁面。HAProxy Ingress Controller會提供有關流經它的流量的詳細指標,因此你可以更好地觀察到進入叢集的流量。

在controller建立型別為NodePort的服務時,這意味著需要分配一個隨機的埠並且埠編號往往很高,但是現在你只需管理幾個此類埠,也就是隻需管理連線到Ingress Controller的埠,無需再為每個服務建立一個埠。你也可以將其配置為使用LoadBalancer型別,只要在雲端進行操作即可。它看起來如下:

總體而言,不需要管理太多Ingress Controller。安裝後,它基本上會在後臺執行其工作。你只需要定義Ingress manifest,controller就會立即將它們連線起來。Ingress manifest的定義與引用的服務有所區別,因此你可以控制何時暴露服務。

結 論

Ingress資源通過允許API閘道器樣式的流量路由,整合了外部客戶端如何訪問Kubernetes叢集中的服務。代理服務通過公共入口點(entrypoint)進行中轉,你可以使用intent-driven、YAML宣告來控制何時以及如何公開服務。

當Ingress API這一功能GA之後,你一定會看到這種模式變得越來越流行。當然,可能產生一些細微的變化,主要是為了使API與現有controller中已經實現的功能保持一致。其他改進可能會指導controller如何繼續發展以符合Kubernetes維護者的願景。總而言之,現在是開始使用此功能的好時機!