Kubernetes 中的 Ingress 與負載均衡器
一、簡介
對於許多軟件應用程序,必須與外部服務通信才能完成它們的任務。無論是發送消息還是使用 API,大多數應用程序都依賴其他系統才能正常運行。
然而,隨著越來越多的用戶將他們的應用程序遷移到 Kubernetes 中,為它們提供安全可靠的訪問變得更具挑戰性。瀏覽各種部署和服務會使網絡流量難以到達正確的位置。
幸運的是,有許多不同的機制可以幫助管理網絡流量並確保請求到達集群內所需的目的地。在本教程中,我們將研究其中兩種機制:入口和負載均衡器。
2. 工作負載和服務
在我們討論其中任何一個之前,我們必須先退後一步,看看應用程序是如何在 Kubernetes 中部署和管理的。
2.1。工作負載和 Pod
我們首先將我們的應用程序打包到 docker 鏡像中。然後使用這些 docker 映像創建預定義的工作負載類型之一,例如:
-
ReplicaSet
:確保始終有最少數量的pods
可用 -
StatefulSet
:在增加或減少pods
數量時提供可預測且唯一的排序 -
DameonSet
:確保始終在某些或所有nodes
上運行特定數量的pods
所有這些工作負載都會創建一個或多個部署在集群中的pods
。 pod
是我們可以在 Kubernetes 中使用的最小可部署單元。它本質上表示在集群中某處運行的應用程序。
默認情況下,每個pod
都有一個唯一的 IP,可供集群的其他成員訪問。但是,出於多種原因,使用其 IP 地址訪問pod
並不是一個好習慣。
首先,要提前知道會為pod
分配什麼 IP 並不容易。這使得幾乎不可能將 IP 信息存儲在其他應用程序可以訪問的配置中。其次,許多工作負載會創建多個 Pod——在某些情況下是動態的。這意味著,在任何時候,我們都可能不知道給定應用程序正在運行多少個 pod。
最後, pods
是非永久性資源。它們會隨著時間的推移而開始和停止,每次發生這種情況時,它們很可能會獲得一個新的 IP 地址。
由於所有這些原因,使用它們的 IP 地址與 pod 通信是一個壞主意。相反,我們應該使用services
。
2.2.服務
Kubernetes service
是一種將一組 pod 公開為網絡服務的抽象。該service
處理識別正在運行的 pod 及其 IP 地址的所有復雜性。每個service
都有一個唯一的 URL,可以跨集群訪問。因此,Pod 無需使用 IP 進行通信,只需使用提供的服務 URL。
讓我們看一個示例服務定義:
apiVersion: v1
kind: Service
metadata:
name: api-service
spec:
selector:
app: api-app
ports:
- protocol: TCP
port: 80
targetPort: 8080
這將在集群中創建一個名為api-service
service
此service
綁定到任何運行應用程序api-app
的 pod,無論這些pods
存在多少或它們在哪裡運行。而且,隨著這種類型的新pods
啟動, service
會自動發現它們。
使用service
是將 pod 與使用它們的應用程序分離的良好開端。但是,就其本身而言,它們並不總能達到我們期望的目標。這就是入口和負載均衡器的用武之地。
3.入口
默認情況下,Kubernetes service
是集群私有的。這意味著只有集群內的應用程序才能訪問它們。有很多方法可以解決這個問題,最好的方法之一是ingress
。
在 Kubernetes 中, ingress
允許我們將來自集群外部的流量路由到集群內部的一個或多個services
。通常,入口作為所有傳入流量的單一入口點。
一個入口接收一個公共 IP,這意味著它可以在集群外部訪問。然後,使用一組規則,它將所有流量轉發到適當的service
。反過來,該service
會將請求發送到可以實際處理請求的pod
。
創建ingress.
首先,它們旨在處理網絡流量(HTTP 或 HTTPS) 。雖然可以將ingress
與其他類型的協議一起使用,但它通常需要額外的配置。
其次, ingress
可以做的不僅僅是路由。其他一些用例包括負載平衡和 SSL 終止。
最重要的是, ingress
對象本身實際上並沒有做任何事情。所以,為了讓ingress
真正做任何事情,我們需要有一個ingress controller
可用。
3.1。入口控制器
與大多數 Kubernetes 對像一樣, ingress
需要關聯的控制器來管理它。然而,雖然 Kubernetes 為大多數對象(如deployments
和services
)提供**con
troller
,但默認情況下它不包括ingress
控制器**。因此,由集群管理員來確保適當的控制器可用。
大多數雲平台都提供自己的ingress controllers
,但也有很多開源選項可供選擇。也許最流行的是nginx 入口控制器,它建立在流行的同名 Web 服務器之上。
讓我們看看使用 nginx ingress controller
的示例配置:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-example
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
ingressClassName: nginx-example
rules:
- http:
paths:
- path: /api
pathType: Prefix
backend:
service:
name: api-service
port:
number: 80
在此示例中,我們創建了一個ingress
,它將任何以/api
開頭的請求路由到名為api-service
的 Kubernetes service
。
請注意, annotations
字段包含特定於 nginx 的值。因為所有ingress controllers
都使用相同的 API 對象,所以我們通常使用 annotations 字段將特定配置傳遞給ingress controller
。
Kubernetes 生態系統中有幾十個可用的ingress controllers
,涵蓋所有這些控制器遠遠超出了本文的範圍。但是,因為它們使用相同的 API 對象,所以它們有一些共同的特點:
- 入口規則:定義如何將流量路由到特定服務的一組規則(通常基於 URL 或主機名)
- 默認後端:處理不匹配任何規則的流量的默認資源
- TLS:定義私鑰和證書以允許 TLS 終止的秘密
不同的入口控制器建立在這些概念之上,並添加了自己的功能和特性。
4.負載均衡器
Kubernetes 中的負載均衡器與ingresses
有相當多的重疊。這是因為它們主要用於向互聯網公開services
,正如我們在上面看到的,這也是ingresses
的一個特性。
但是,負載均衡器具有與ingresses
不同的特性。負載均衡器不是像ingress
這樣的獨立對象,而是service
的擴展。
讓我們看一個帶有負載均衡器的服務的簡單示例:
apiVersion: v1
kind: Service
metadata:
name: api-service
spec:
selector:
app: api-app
ports:
- protocol: TCP
port: 80
targetPort: 8080
type: LoadBalancer
就像我們之前的服務示例一樣,在這裡,我們正在創建一個service
,將流量路由到運行我們的 API 應用程序的任何pod
。在本例中,我們包含了一個LoadBalancer
配置。
為此,集群必須在支持外部負載均衡器的提供程序上運行。所有主要的雲提供商都支持使用自己的資源類型的外部負載均衡器:
就像我們看到不同的ingress controllers
一樣,不同的負載均衡器提供者有自己的設置。通常,我們使用 CLI 或特定於基礎架構的工具直接管理這些設置,而不是使用 YAML。不同的負載均衡器實現還將提供額外的功能,例如 SSL 終止。
因為負載平衡器是按service
定義的,所以它們只能路由到單個service
。這與ingress
不同,它能夠路由到集群內的多個services
。
此外,請記住,無論供應商如何,使用外部負載平衡器通常都會帶來額外費用。這是因為,與入口及其控制器不同,外部負載均衡器存在於 Kubernetes 集群之外ingresses
正因為如此,大多數雲提供商將對集群本身之外的額外資源使用收費。
5. 結論
在本文中,我們研究了ingresses
的一些核心概念,包括deployments
、 services
和入口。這些對像中的每一個都在各種pods.
雖然ingresses
和負載均衡器在功能上有很多重疊,但它們的行為不同。主要區別在於ingresses
是集群內的本機對象,可以路由到多個services
,而負載均衡器位於集群外部,只能路由到單個service.