從概念、部署到優化,Kubernetes Ingress 閘道器的落地實踐

語言: CN / TW / HK

作者:範揚(揚少)

Kubernetes Ingress 簡介

通常情況下,Kubernetes 叢集內的網路環境與外部是隔離的,也就是說 Kubernetes 叢集外部的客戶端無法直接訪問到叢集內部的服務,這屬於不同網路域如何連線的問題。解決跨網路域訪問的常規做法是為目標叢集引入一個入口點,所有外部請求目標叢集的流量必須訪問這個入口點,然後由入口點將外部請求轉發至目標節點。

同樣,Kubernetes 社群也是通過增設入口點的方案來解決叢集內部服務如何對外暴露的問題。Kubernetes 一貫的作風是通過定義標準來解決同一類問題,在解決叢集對外流量管理的問題也不例外。Kubernetes 對叢集入口點進行了進一步的統一抽象,提出了 3 種解決方案:NodePort、LoadBalancer 和 Ingress。下圖是這三種方案的對比:

通過對比,可以看到 Ingress 是更適合業務使用的一種方式,可以基於其做更復雜的二次路由分發,這也是目前使用者主流的選擇。

Kubernetes Ingress 現狀

雖然 Kubernetes 對叢集入口流量管理方式進行標準化的統一抽象,但僅僅覆蓋了基本的 HTTP/HTTPS 流量轉發功能,無法滿足雲原生分散式應用大規模複雜的流量治理問題。比如,標準的 Ingress 不支援流量分流、跨域、重寫、重定向等較為常見的流量策略。針對這種問題,存在兩種比較主流的解決方案。一種是在 Ingress 的 Annotation 中定義 Key-Value 的方式來拓展;另一種是利用 Kubernetes CRD 來定義新的入口流量規則。如下圖所示:

Kubernetes Ingress 最佳實踐

本節將從以下 5 個方面展開 Kubernetes Ingress 最佳實踐。

  • 流量隔離:部署多套 IngressProvider,縮小爆炸半徑
  • 灰度釋出:如何利 用 IngressAnnotation 來進行灰度釋出
  • 業務域拆分:如何按照業務域進行 API 設計
  • 零信任:什麼是零信任,為什麼需要零信任,怎麼做
  • 效能調優:一些實用的效能調優方法

流量隔離

在實際業務場景中,叢集中後端服務需要對外部使用者或者內部其他叢集提供服務。通常來說,我們將外部訪問內部的流量稱為南北向流量, 將內部服務之間的流量稱為東西向流量。為了節省機器成本和運維壓力,有些使用者會選擇將南北向流量和東西向流量共用一個 Ingress Provider。這種做法會帶來新的問題,無法針對外部流量或者內部流量做精細化的流量治理,同時擴大了故障影響面。最佳的做法是針對外網、內網的場景分別獨立部署 Ingress Provider,並且根據實際請求規模控制副本數以及硬體資源,在縮小爆炸半徑的同時儘可能提供資源利用率。

灰度釋出

在業務持續迭代發展過程中,業務的應用服務面臨著版本頻繁升級的問題。最原始最簡單的方式,是停掉線上服務的舊版本,然後部署、啟動服務的新版本。這種直接將服務的新版本提供給所有使用者的方式會帶來兩個比較嚴重的問題。首先,在停掉服務舊版本與啟動新版本這段時間內,該應用服務是不可用,流量請求的成功率跌零。其次,如果新版本中存在嚴重的程式 BUG,那麼新版本回滾到舊版本的操作又會導致服務出現短暫的不可用,不僅影響使用者體驗,而且也會對業務整體系統產生諸多不穩定因素。

那麼,如何既能滿足業務快速迭代的訴求,又能保證升級過程中業務應用對外的高可用?​

我認為需要解決以下幾個核心問題:

  1. 如何減小升級的影響面?
  2. 新版本出現 Bug 時如何快速回滾到穩定版本?
  3. 如何解決標準 Ingress 不支援流量分流的缺陷?

針對前兩個問題,業界共識比較通用的做法是採用灰度釋出,俗稱金絲雀釋出。金絲雀釋出的思想則是將少量的請求引流到新版本上,因此部署新版本服務只需極小數的機器。驗證新版本符合預期後,逐步調整流量,使得流量慢慢從老版本遷移至新版本,期間可以根據當前流量在新老版本上的分佈,對新版本服務進行擴容,同時對老版本服務進行縮容,使得底層資源得到最大化利用。

在 Ingress 現狀小節裡,我們提到了目前比較流行的兩種擴充套件 Ingress 的方案,其中通過為 Annotation 新增 Key-Value 的方式可以解決第三個問題。我們可以在 Annotation 中定義灰度釋出需要的策略配置,比如配置灰度流量的 Header、Cookie 以及對應值的匹配方式 (精確匹配或者正則匹配)。之後由 Ingress Provider 識別新定義的 Annotation 並解析為自身的路由規則,也就是關鍵在於使用者選擇的 Ingress Provider 要支援豐富的路由方式。

灰度釋出——按照 Header 灰度

在進行小流量驗證服務新版本是否符合預期的環節中,我們可以有選擇的將線上具有一部分特徵的流量認為是小流量。請求內容中 Header、Cookie 都可以認為是請求特徵,因此針對同一個 API,我們可以按照 Header 或者 Cookie 對線上流量進行切分。如果真實流量中 Header 無差別,我們可以基於線上環境手動製造一些帶有灰度 Header 的流量進行驗證。此外,我們也可以按照客戶端的重要性來分批進行新版本驗證,比如對於普通使用者的訪問請求優先訪問新版本,待驗證完畢後,再逐步引流 VIP 使用者。一般這些使用者資訊、客戶端資訊都會存在 Cookie 中。

以 Nginx-Ingress 為例,通過 Annotation 支援 Ingress 的流量分流,按照 Header 灰度的示意圖如下:

灰度釋出——按照權重灰度

按照 Header 灰度的方式可以對特定的請求或者使用者提供服務新版本,但是無法很好評估訪問新版本的請求規模,因此在為新版本分配機器時可能無法做到資源最大化利用。而按照權重進行灰度的方式可以精確控制流量比例,在機器資源分配上游刃有餘。通過前期小流量驗證後,後期通過調整流量權重,逐步完成版本升級,這種方式操作簡單,易於管理。然而線上流量會無差別地導向新版本,可能會影響重要使用者的體驗。按照權重灰度的示意圖如下:

業務域拆分

隨著雲原生應用規模不斷擴大,開發者開始對原來的單體架構進行細粒度的拆分,將單體應用中的服務模組拆分成一個個獨立部署執行的微服務,並且這些微服務的生命週期由對應的業務團隊獨自負責,有效的解決了單體架構中存在的敏捷性不足、靈活性不強的問題。但任何架構都不是銀彈,在解決舊問題同時勢必會引入一些新的問題。單體應用通過一個四層 SLB 即可完成對外暴露服務,而分散式應用依賴 Ingress 提供七層流量分發能力,這時如何更好的設計路由規則尤為重要。

通常我們會根據業務域或者功能域進行服務拆分,那麼我們在通過 Ingress 對外暴露服務時同樣可以遵循該原則。為微服務設計對外 API 時可以在原有的 Path 上新增具有代表性意義的業務字首,在請求完成路由匹配之後和轉發請求到後端服務之前時,由 Ingress Provider 通過重寫 Path 完成業務字首消除的工作,工作流程圖如下:

該 API 設計原則易於管理對外暴露的服務集合,基於業務字首做更細粒度的認證鑑權,同時方便對各個業務域服務進行統一的可觀測建設。

零信任

安全問題始終是業務應用的頭號公敵,伴隨著業務發展的整個生命週期。此外,外部網際網路的環境越來越複雜,內部業務架構日益龐大,部署結構涉及公有云、私有云以及混合雲多種形態,安全問題愈演愈烈。零信任作為安全領域的一種新型設計模型應用而生,認為應用網路內外的所有使用者、服務都不可信,在發起請求、處理請求之前都要經過身份認證,所有授權操作遵循最小許可權原則。簡單來說就是 trust no-one, verify everything.

下圖是關於外部使用者->Ingress Provider->後端服務整個端到端落地零信任思想的架構圖:

  • 外部使用者與 Ingress Provider。外部使用者通過向權威證書機構驗證 Ingress Provider 提供的證書完成身份認證;Ingress Provider 通過外部使用者提供 JWT 憑證完成認證鑑權。

  • Ingress Provider 與後端服務。Ingress Provider 通過向內部私有證書機構驗證後端服務提供的證書完成身份認證,後端服務通過向內部私有證書驗證 Ingress Provider 提供的證書完成身份認證,同時後端服務可以基於呼叫方身份向授權服務進行鑑權操作。

效能調優

所有的外部訪問流量都需要先經過 Ingress Provider,因此主要效能瓶頸體現在 Ingress Provider,在高併發、高效能上有了更高的要求。拋開各個 Ingress Provider 之間的效能差異,我們可以通過調整核心引數來進一步釋放效能。經過阿里巴巴多年在叢集接入層的實踐經驗,我們可以適當調整以下核心引數:

  1. 調大 TCP 連線佇列的容量:net.core.somaxconn
  2. 調大可用埠範圍:net.ipv4.ip_local_port_range
  3. 複用 TCP 連線:net.ipv4.tcp_tw_reuse

另一個優化角度是從硬體著手,充分釋放底層硬體算力來進一步提高應用層的效能。當下 HTTPS 已經成為公網請求的主要使用方式,全部使用 HTTPS 後由於其要做 TLS 握手,相比 HTTP 勢必效能上會有很大損耗。目前隨著 CPU 效能的大幅提升,利用 CPU 的 SIMD 機制可以很好的加速 TLS 的效能。該優化方案依賴機器硬體的支援以及 Ingresss Provider 內部實現的支援。

目前,依託 Istio-Envoy 架構的 MSE 雲原生閘道器結合阿里雲第七代 ECS 率先完成了 TLS 硬體加速,在不增加使用者資源成本的同時大幅度提升 HTTPS 的效能。

Ingress Provider 新選擇——MSE 雲原生閘道器

隨著雲原生技術持續演進,雲原生應用微服務化不斷深入,Nginx Ingress 在面對複雜路由規則配置、支援多種應用層協議(Dubbo 和 QUIC 等)、服務訪問的安全性以及流量的可觀測性等問題上略顯疲憊。另外,Nignx Ingress 在處理配置更新問題上是通過 Reload 方式來生效配置,在面對大規模長連線的情況下是會出現閃斷情況,頻繁變更配置可能會造成業務流量有損。

為了解決使用者對大規模流量治理的強烈訴求,MSE 雲原生閘道器應運而生,這是阿里雲推出的相容標準 Ingress 規範的下一代閘道器,具備低成本、安全、高整合和高可用的產品優勢。將傳統的 WAF 閘道器、流量閘道器和微服務網關合並,在降低 50% 資源成本的同時為使用者提供了精細化的流量治理能力,支援 ACK 容器服務、Nacos、Eureka、固定地址、FaaS 等多種服務發現方式,支援多種認證登入方式快速構建安全防線,提供全方面、多視角的監控體系,如指標監控、日誌分析以及鏈路追蹤,並且支援解析單、多 Kubernetes 叢集模式下的標準 Ingress 資源,幫助使用者在雲原生應用場景下以宣告式進行統一流量治理,此外我們引入了 WASM 外掛市場滿足使用者定製化的需求。

Nginx Ingress VS MSE 雲原生閘道器

以下是 Nginx Ingress 與 MSE 雲原生閘道器的對比總結:

平滑遷移

MSE 雲原生閘道器由阿里雲託管,免運維,降成本,功能豐富,且與阿里雲周邊產品深度整合,下圖是從 Nginx Ingress 如何無縫遷移至 MSE 雲原生閘道器,其他 Ingress Provider 也可以參考該方法。

動手實踐

接下來,我們會基於阿里雲容器服務 ACK 進行 Ingress Provider——MSE 雲原生閘道器相關的實踐操作,您可以瞭解到如何通過 MSE Ingress Controller 來管理叢集入口流量。

操作文件地址:

https://help.aliyun.com/document_detail/426544.html

前提條件

安裝 MSE Ingress Controller

我們可以在阿里雲容器服務的應用市場中找到 ack-mse-ingress-controller,並且按照元件下方的操作文件完成安裝。

通過 CRD 的方式建立 MSE 雲原生閘道器

MseIngressConfig 是由 MSE Ingress Controller 提供的 CRD 資源,MSE Ingress Controller 使用 MseIngressConfig 來管理 MSE 雲原生閘道器例項的生命週期。一個MseIngressConfig 對應一個 MSE 雲原生閘道器例項,如果您需要使用多個 MSE 雲原生閘道器例項,需要建立多個 MseIngressConfig 配置。為了簡單展示,我們以一個最小化配置的方式來建立閘道器。

apiVersion: mse.alibabacloud.com/v1alpha1 kind: MseIngressConfig metadata: name: test spec: name: mse-ingress common: network: vSwitches: - "vsw-bp1d5hjttmsazp0ueor5b"

配置 Kubernetes 標準的 IngressClass 來關聯 MseIngressConfig,關聯完畢後雲原生閘道器就會開始監聽叢集中與該 IngressClass 有關的 Ingress 資源。

apiVersion: networking.k8s.io/v1 kind: IngressClass metadata: annotations: ingressclass.kubernetes.io/is-default-class: 'true' name: mse spec: controller: mse.alibabacloud.com/ingress parameters: apiGroup: mse.alibabacloud.com kind: MseIngressConfig name: test

我們可以通過檢視 MseIngressConfig 的 status 來檢視當前狀態。MseIngressConfig 會按照 Pending > Running > Listening 的狀態依次變化。各狀態說明如下:

  • Pending:表示雲原生閘道器正在建立中,需等待 3min 左右。
  • Running:表示雲原生閘道器建立成功,並處於執行狀態。
  • Listening:表示雲原生處於執行狀態,並監聽叢集中 Ingress 資源。
  • Failed:表示雲原生閘道器處於非法狀態,可以檢視 Status 欄位中 Message 來進一步明確原因。

灰度釋出實踐

假設叢集有一個後端服務 httpbin,我們希望在版本升級時可以按照 header 進行灰度驗證,如圖所示:

首先部署 httpbin v1 和 v2 版本,通過 apply 以下資源到 ACK 叢集中:

``` apiVersion: apps/v1 kind: Deployment metadata: name: go-httpbin-v1 spec: replicas: 1 selector: matchLabels: app: go-httpbin-v1 template: metadata: labels: app: go-httpbin-v1 version: v1 spec: containers: - image: specialyang/go-httpbin:v3 args: - "--port=8090" - "--version=v1" imagePullPolicy: Always name: go-httpbin ports: - containerPort: 8090


apiVersion: apps/v1 kind: Deployment metadata: name: go-httpbin-v2 spec: replicas: 1 selector: matchLabels: app: go-httpbin-v2 template: metadata: labels: app: go-httpbin-v2 version: v2 spec: containers: - image: specialyang/go-httpbin:v3 args: - "--port=8090" - "--version=v2" imagePullPolicy: Always name: go-httpbin ports: - containerPort: 8090


apiVersion: v1 kind: Service metadata: name: go-httpbin-v1 spec: ports: - port: 80 targetPort: 8090 protocol: TCP selector: app: go-httpbin-v1


apiVersion: v1 kind: Service metadata: name: go-httpbin-v2 spec: ports: - port: 80 targetPort: 8090 protocol: TCP selector: app: go-httpbin-v2 ```

釋出穩定版本 v1 的 Ingress 資源:

apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: httpbin spec: ingressClassName: mse rules: - host: test.com http: paths: - path: /version pathType: Exact backend: service: name: go-httpbin-v1 port: number: 80

釋出灰度版本 v2 的 Ingress 資源:

apiVersion: networking.k8s.io/v1 kind: Ingress metadata: annotations: "nginx.ingress.kubernetes.io/canary": "true" "nginx.ingress.kubernetes.io/canary-by-header": "stage" "nginx.ingress.kubernetes.io/canary-by-header-value": "gray" name: httpbin-canary-header spec: ingressClassName: mse rules: - host: test.com http: paths: - path: /version pathType: Exact backend: service: name: go-httpbin-v2 port: number: 80

測試驗證

```

測試穩定版本

curl -H "host: test.com" /version

測試結果

version: v1

測試灰度版本

curl -H "host: test.com" -H "stage: gray" /version

測試結果

version: v2 ```

以上就是我們利用 Ingress Annotation 的方式擴充套件標準 Ingress 支援灰度釋出的高階流量治理能力。

寫在最後

MSE - 雲原生閘道器,旨在為使用者提供更可靠的、成本更低、效率更高的,符合 Kubernetes Ingress 標準的企業級閘道器產品,更多釋出詳情移步直播間觀看:

https://yqh.aliyun.com/live/detail/28477

MSE - 雲原生閘道器提供後付費和包年包月兩類付費模式,支援杭州、上海、北京、深圳 、張家口、香港、新加坡、美國(弗吉尼亞)、美國(矽谷)、德國(法蘭克福)10 個 region,並會逐步開放其他 region,雲原生閘道器購買連結在這裡。

現在購買 MSE 雲原生閘道器預付費全規格,立享 7 折優惠,新老同享。

也可釘釘搜尋群號 34754806 可加入使用者群交流、答疑。

點選​此處​,前往 MSE 官網進行搶購吧!