Kubernetes 集羣中流量暴露的幾種方案

作者:KaliArch(薛磊),某 Cloud MSP 服務商產品負責人,熟悉企業級高可用 / 高併發架構,包括混合雲架構、異地災備,熟練企業 DevOps 改造優化,熟悉 Shell/Python/Go 等開發語言,熟悉 Kubernetes、 Docker、雲原生、微服務架構等。

背景

在業務使用 Kubernetes 進行編排管理時,針對業務的南北流量的接入,在 Kuberentes 中通常有幾種方案,本文就接入的方案進行簡單介紹。

流量接入方案

Kuberentes 社區通過爲集羣增設入口點的方案,解決對外流量的管理。

通過 kube-proxy 進行代理

通常在最簡單的測試或個人開發環境,可以通過 kubectl port-forward 來啓動一個 kube-proxy 進程代理內部的服務至該命令執行的宿主機節點,如果該宿主機具備公網 IP,且轉發監聽端口爲0.0.0.0就可以實現公網訪問該服務,該方式可以代理單個 Pod,或者 Deployment,或者 Servcie。

$ kubectl port-forward -h
Forward one or more local ports to a pod. This command requires the node to have 'socat' installed.

 Use resource type/name such as deployment/mydeployment to select a pod. Resource type defaults to 'pod' if omitted.

 If there are multiple pods matching the criteria, a pod will be selected automatically. The forwarding session ends
when the selected pod terminates, and rerun of the command is needed to resume forwarding.

Examples:
  # Listen on ports 5000 and 6000 locally, forwarding data to/from ports 5000 and 6000 in the pod
  kubectl port-forward pod/mypod 5000 6000

  # Listen on ports 5000 and 6000 locally, forwarding data to/from ports 5000 and 6000 in a pod selected by the
deployment
  kubectl port-forward deployment/mydeployment 5000 6000

  # Listen on port 8443 locally, forwarding to the targetPort of the service's port named "https" in a pod selected by
the service
  kubectl port-forward service/myservice 8443:https

  # Listen on port 8888 locally, forwarding to 5000 in the pod
  kubectl port-forward pod/mypod 8888:5000

  # Listen on port 8888 on all addresses, forwarding to 5000 in the pod
  kubectl port-forward --address 0.0.0.0 pod/mypod 8888:5000

  # Listen on port 8888 on localhost and selected IP, forwarding to 5000 in the pod
  kubectl port-forward --address localhost,10.19.21.23 pod/mypod 8888:5000

  # Listen on a random port locally, forwarding to 5000 in the pod
  kubectl port-forward pod/mypod :5000

NodePort 方式

其次較常用的爲 NodePort 方式,將 K8s 中 service 的類型修改爲 NodePort 方式,會得到一個端口範圍在 30000-32767 端口範圍內的宿主機端口,同樣改宿主機具有公網 IP 就可以實現對服務的暴露,但是 NodePort 會佔用宿主機端口,一個 Service 對應一個 NodePort,該方式僅爲四層,無法實現 SSL 證書的卸載,如果將服務轉發到單個 Node 節點的 NodePort 也無法實現高可用,一般需要在 NodePort 前搭配負載均衡來添加多個後端 NodePort 已實現高可用。

LoadBalancer

四層

四層流量轉發一個 LB 的端口只能對應一個 Service,Servcie 的 Type 爲 NodePort,例如如下圖,LoadBalancer 上的 88 端口對應轉發到後端 NodePort 的 32111 端口,對應到 servcieA;LB 上的 8080 端口對應轉發到後端 NodePort32001 端口;該方案可以通過添加多個 NodePort 方式實現高可用,但是由於爲四層無法實現對 SSL 的卸載,對應 NodePort 需要在 LB 佔用一個端口。

七層

七層可以藉助 LB 的域名轉發,實現一個域名端口對應多個 Service,如圖可以根據 path 路徑,/cmp 對應 NodePort 的 32111,/gateway 對應 NodePort 的 32000 端口,不僅可以實現高可用,而且七層可以實現 SSL 卸載。

目前一般公有云的 LB 級別都具備四層和七層的功能,配合使用可以實現靈活的業務流量暴露。

Ingress

在 K8s 中,存在有 Ingress 資源來實現單個域名轉發根據不同的路徑或其他配置規則轉發到 K8 集羣內部不同的 Service,但是用戶請求需要訪問 Ingress 實現控制器的 NodePort 例如 Ingress-nginx 的 Controller 的 Service 的 NodePort,針對具體的業務域名一般不會帶端口,所以一般前面還需要一層 80/443 的端口轉發。

一般 Ingress 的 Controller 實現業界也有不少解決方案,例如比較知名的 Ingress—nginx/Ingress-traefik 等。

LoadBalancer + Ingress

如下圖所示在最前面有一個四層 LB 實現端口 80/443 轉發至 ingress-provider 的 Service 的 NodePort,K8s 集羣內部配置有多個 service。

Ingress-nginx 詳解

在上面的幾種方案中,均有用到 Ingress,Nginx-ingress 爲 Nginx 官方提供的實現K8s ingress 資源的方案,同時 Kubernetes 官方也提供了基於 Nginx 實現的 Ingress 方案。

Nginx Ingress 由資源對象 Ingress、Ingress 控制器、Nginx 三部分組成,Ingress 控制器的目標是構建完成一個配置文件(nginx.conf),主要通過檢測配置文件發生改變後重載 Nginx 實現,但並不是僅在 Upstream 更改時重載 Nginx(部署應用程序時修改Endpoints),使用 lua-nginx-module 實現。

根據下圖可以更好的理解 Ingress-nginx 的使用場景。

圖中展示如下信息:

  • 一個 K8s 集羣
  • 集羣用戶管理、用戶A和用戶 B,它們通過 Kubernetes API 使用集羣。
  • 客戶端 A 和客戶端 B,它們連接到相應用戶部署的應用程序 A 和 B。
  • IC,由 Admin 部署在名稱空間 nginx-ingress 中的 pod 中,並通過 ConfigMap nginx-ingress 進行配置。Admin 通常部署至少兩個 pod 以實現冗餘。IC 使用 Kubernetes API 獲取集羣中創建的最新入口資源,然後根據這些資源配置 NGINX。
  • 應用程序 A 由用戶 A 在命名空間 A 中部署了兩個吊艙。爲了通過主機 A.example.com 向其客戶機(客戶機 A)公開應用程序,用戶 A 創建入口 A。
  • 用戶 B 在命名空間 B 中部署了一個 pod 的應用程序 B。爲了通過主機 B.example.com 向其客戶機(客戶機 B)公開應用程序,用戶 B 創建 VirtualServer B。
  • 公共端點,它位於 IC 吊艙前面。這通常是一個 TCP 負載均衡器(雲、軟件或硬件),或者這種負載均衡器與 NodePort 服務的組合。客戶端 A 和 B 通過公共端點連接到他們的應用程序。

黃色和紫色箭頭表示與客戶端通信量相關的連接,黑色箭頭表示對 Kubernetes API 的訪問。

爲了簡單,沒有顯示許多必要的 Kubernetes 資源,如部署和服務,管理員和用戶也需要創建這些資源。

其他

在 K8s 中,通常雲廠商的 LB 一般雲廠商提供適配 CNI,會在創建 K8s 集羣時會自動創建 LB 類型的 servcie,例如阿里的 ACK,騰訊的 TKE,華爲的 CCE等,但是在我們自建或個人測試場景,開源的 Metallb是一個不錯的選擇,其作用通過 K8s 原生的方式提供LB類型的Service支持,開箱即用,當然還有青雲科技 KubeSphere 團隊開源的負載均衡器插件 OpenELB,是爲物理機(Bare-metal)、邊緣(Edge)和私有化環境設計的負載均衡器插件,可作爲 Kubernetes、K3s、KubeSphere 的 LB 插件對集羣外暴露 “LoadBalancer” 類型的服務。在 2021 年11 月已進入 CNCF 沙箱(Sandbox)託管,也是解決用戶將 Kubernetes 集羣部署在裸機上,或是私有化環境特別是物理機或邊緣集羣,Kubernetes 並不提供 LoadBalancer 的痛點,提供與基於雲的負載均衡器相同的用戶體驗。

本文由博客一文多發平臺 OpenWrite 發佈!

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