技術翻譯 - 我該如何選擇?API Gateway vs. Ingress Controller vs. Service Mesh
How Do I Choose? API Gateway vs. Ingress Controller vs. Service Mesh
定義
API Gateway
簡單來說 API Gateway 就將 API 請求從客戶端導流到正確的服務。但這其中最大的誤解就是,認為他是一項獨特的技術,但其實不是。相反的 API Gateway 描述了一組可以透過不同類型的代理 -- 最常見的就是應用交付控制器 (ADC, Application delivery controller)、反向代理、附載平衡和越來越多的 Ingress controller 和 serivce mesh。這其中並沒有一定要包含哪些功能,都是視客戶需求來決定。例如以下的範例:
- Resilience Use Cases
- A/B testing, canary deployments, and blue‑green deployments
- Protocol transformation (between JSON and XML, for example)
- Rate limiting
- Service discovery
- Traffic Management Use Cases
- Method‑based routing and matching
- Request/response header and body manipulation
- Request routing at Layer 7
- Security Use Cases
- API schema enforcement
- Client authentication and authorization
- Custom responses
- Fine‑grained access control
- TLS termination
Ingress Controller
Ingress controller 是在 Kubernetes 中用來處理 OSI Model 中第四層和第七層代理,引導流量到 Kubernetes 中並返回的服務(又稱 ingress‑egress 或 north‑south traffic)。除了管理流量外,也可用於故障排除、安全性身份驗證等大多數進階的 API Gateway 功能
Service Mesh
Service Mesh 是用來處理 Kubernetes 服務間的流量(又可稱為 service-to-service 或 east-west traffic),通常用於實現 end-to-end encryption(E2EE)。可以用來當作相當輕量化於應用程式的 API gateway。
在 Kubernetes 環境中使用 Kubernetes 原生工具
我們可以從 Mark Church 在 Nginx Sprint 2.0 keynote 中的 Kubernetes and the Future of Application Networking聽到 「API gateways, load balancers, and service meshes will continue to look more and more similar to each other and provide similar capabilities.」。完全取決於您的使用情境。
那麼我們該怎麼選擇適合的工具呢?我們來使其變得簡單。如果你需要 Kubernetes 內部的 API gateway 功能,最好使用原生的 Kubernetes 設定工具(例如 YAML)。並不需要因為聽到說 API gateway 比 Ingress controller 有更多功能就使用。更多功能並不意味著更好的工具,工具的複雜性可能會成為殺手。
注意: Kubernetes-native(不等同於 Knative),指的是為 Kubernetes 設計和建造的工具。通常會與 Kubernetes CLI 一起使用,可以依靠 Helm 安裝,並與 Kubernetes 功能 integrate。
North-South API Gateway 使用案例:使用 Ingress Controller
Ingress controller 可以實現許多 API gateway 的使用情境,其中我們發現大部分的組織會用來實現以下:
- Offload of authentication and authorization
- Authorization‑based routing
- Layer 7 level routing and matching (HTTP, HTTP/S, headers, cookies, methods)
- Protocol compatibility (HTTP, HTTP/2, WebSocket, gRPC)
- Rate limiting
Sample Scenario: Method-Level Routing
您想實現方法級別的匹配和路由:使用 Ingress controller 阻擋 API 請求中的 POST
請求。一些攻擊會透過發送不符合 API 定義的請求來找尋漏洞 -- 例如,將 POST
請求發送到止接受 GET
請求的 API 上。Web 應用程式防火牆(WAF)無法檢查出這種攻擊。WAF 只能檢查 API 請求中的 body 是否包含攻擊。因此最佳實踐是在 ingress 層使用 API gateway 來阻擋這種錯誤的請求。
作為範例,預期將有一個新的 API /coffee/{coffee-store}/brand
要新增到叢集上。第一步是使用 Nginx Ingress Controller 將 API 暴露出來。就如下將 API 增加到 upstreams
欄位
apiVersion: k8s.nginx.org/v1
kind: VirtualServer
metadata:
name: cafe
spec:
host: cafe.example.com
tls:
secret: cafe-secret
upstreams:
-name: tea
service: tea-svc
port: 80
-name: coffee
service: coffee-svc
port: 80
為了啟用 method-level matching,在 routes
欄位加上 /coffee/{coffee-store}/brand
路徑和增加兩個 conditions
利用 $request_method
變數來區分 GET
和 POST
請求。任何的 HTTP GET
請求都會自動的轉送到 coffee
服務,POST
請求則會轉跳到錯誤頁面,並收到 You are rejected!
的訊息。就這樣你從不需要的 POST
流量保護了新的 API。
routes:
- path: /coffee/{coffee-store}/brand
matches:
- conditions:
- variable: $request_method
value: POST
action:
return:
code: 403
type: text/plain
body: "You are rejected!"
- conditions:
- variable: $request_method
value: GET
action:
pass: coffee
- path: /tea
action:
pass:tea
East-West API Gateway 使用案例: 使用 Service Mesh
對於大多數的 API gateway 使用案例來說,service mesh 並不是必須的,甚至沒有太多幫助,因為大多數所需要的事情都可以在 Ingress 曾就處理了。但隨著架構複雜性的增加,才可能開始從 service mesh 中得到其價值。我們發現最有效益的案例是 E2EE 和流量拆分有關 -- 例如 A/B 測試、金絲雀部署和藍綠部署。
Sample Scenario: Canary Deployment
你想要使用基於 HTTP/S 標準的條件下載服務間設定金絲雀部署。優點是你可以逐步的推動 API 變更(例如新功能或是版本)而不需要影響大部分的生產環境的流量。
目前你的 Nginx Ingress controller 引導流量到兩個由 Nginx Service Mesh 管理的服務:Coffee.frontdoor.svc
和 Tea.frontdoor.svc
。這些服務從 Nginx Ingress controller 接收流量後路由到適當的應用程式(其中包括 Tea.cream1.svc
)。
使用 Nginx service mesh,可以開始先在這些服務的前端 Tea.frontdoor.svc
拆分流量。為了開啟 conditional routing(路由條件),建立一個 HTTPRouteGroup
資源並與 TrafficSplit
做關聯。最終結果,只有從 beta 使用者(請求中的 cookie 設定 version=beta
)來的請求才會從 Tea.frontdoor.svc
導流到 Tea.cream2.svc
。而一般的使用者會繼續使用到 Tea.frontdoor.svc
後版本 1 的服務。
apiVersion: split.smi-spec.io/v1alpha3
kind: TrafficSplit
metadata:
name: tea-svc
spec:
service: tea.1
backends:
- service: tea.1
weight: 0
- service: tea.2
weight: 100
matches:
- kind: HTTPRouteGroup
name: tea-hrg
apiVersion: specs.smi-spec.io/v1alpha3
kind: HTTPRouteGroup
metadata:
name: tea-hrg
namespace: default
spec:
matches:
- name: beta-session-cookie
headers:
- cookie: "version=beta"
什麼時候(和如何)為 Kubernetes 應用程式使用 API Gateway 工具
儘管說 Kubernetes 的大多數 API gateway 使用案例可以由 Ingress controller 或 Service mesh 解決。但某些特殊情況下 API gateway 工具(例如 Nginx Plus)是最適合的。
商業需求
雖然多個團隊或專案可以共享同一組 Ingress controller,或者 Ingress controller 可以針對每個環境進行專門的設定。但更好的選擇是在 Kubernetes 中部署專門的 API gateway 而不是讓 Ingress controller 複雜化。同時使用 Ingress controller 和 API gateway 可以為組織提供商業需求上的靈活度。一些場景包括:
- 你的 API gateway 團隊可能不熟悉 Kubernetes 也沒有使用 YAML。例如他們相當熟悉 Nginx config,則在 kubernetes 中部署 Nginx Plus 來作為 API gateway 將可以減少其學習曲線
- 你的平台 Ops 團隊更傾向於將 Ingress controller 專門用於應用程式的流量管理
- 你有一個 API gateway 使用案例,其該場景只適用於叢集中的一項服務。則不需要使用 Ingress controller 將其規則部署到所有的 north-south traffic。可以使用 API gateway 在需要的地方部署規則即可
將 API 搬遷到 Kubernetes 環境中
再將現有的 API 搬遷到 Kubernetes 環境時,可以將這些 API 部署到 Kubernetes 之外的 API gateway 工具。在這種場景下,API 流量通常會透過外部的負載平衡(用於叢集之間的)引導,然後送到當作 API gateway 的附載平衡,最後送到 Kubernetes 叢集中的 Ingress controller。
在 Kubernetes 環境中支援 SOAP APIs
大多數現代的 APIs 都是使用 REST 來建立,但你依舊可能會有一些 SOAP APIs。SOAP APIs 並不建議用於 Kubernetes,因為並沒有針對微服務架構做優化,但是還需要再轉換成 RESTful API 之前部署到 Kubernetes,這時就會需要轉換兩者 protocols。但我們並不建議做在 Ingress controller 因為相當的浪費資源。相反的,我們建議將 API gateway 部署為 per-pod 或 per-service 代理,來作為 SOAP 和 REST 之間的轉換。
同時需要管理 Kubernetes 內部和外部的流量
我們有一寫部分的客戶對於管理跨 Kubernetes 內外環境的 API 很感興趣。如果 API 管理策略優先度高於 Kubernetes-native 工具的話,那部署在 Kubernetes 中的 Kubernetes-friendly API gateway 會是個正確的選擇。