In-cluster gRPC Load Balancing?
矽谷牛的耕田筆記背景
想必大家應該已經有經驗 gRPC 在 Kubernetes 上無法做負載均衡了吧!原因是 gRPC 是建立於 HTTP/2 ,而 HTTP/2 的設計本身是複用了同一條長連接 TCP(long-lived TCP)在這條 TCP 連線裡做到多路複用 (multiplexing) 減少建立 TCP 連線所需的開銷及時間。
正因為如此在 Kubernetes 上建立的 Service 底下的工作機制 kube-proxy (iptables) 對 TCP 連接做負載均衡,但 HTTP/2 複用同一條 TCP 連接導致 In-cluster 負載均衡失效是可以預見的。

解決方案
- 實作 client-side Load Balancing (Thick client): 直接在 gRPC client-side 引用 gRPC 函式庫裡的 LB 演算法實作
- 直上 Service Mesh: 透過使用 Linkerd, Istio 等服務網格工具擺脫 kube-proxy 的低階LB
- 加一個能夠 load balance HTTP/2 Protocol 的反向代理: 使用能夠辨識 gRPC 或 HTTP/2 的代理(Envoy)協助 LB
- xDS based load balancing: gRPC 最近宣布支援 xDS LB, 可以達到 Proxyless gRPC LB
建議方案
- 方案1. 對於已經寫好 client 端的團隊需要時間成本再重新改寫具體做法可以是: client-side 改寫引入 LB 的 gRPC 函式庫,service-side 使用 Headless Service 創建多個 A record DNS
- 方案2. 對於團隊中已經將 Kubernetes 引入 Service Mesh 那應該就可以達到 LB 效果,特別注意沒有必要為了 gRPC LB 直上 Service Mesh 殺雞焉用牛刀,想要引入的團隊可以先參考上一篇 Service Mesh 所帶來的好處
- 方案3. 入門成本較低,配好 Envoy 做為一個 gRPC 的反向代理及service-side 使用 Headless Service 創建多個 A record DNS 即可以完成
- 方案4. 此方案還未成熟,屬於非常新且進階的方式需要撰寫 xDS Server 監控 Kubernetes Service,不太建議使用。
總結
總結本篇文章,這裡提出一個假設。讀者已經在使用 gRPC 於服務於團隊中的 Kubernetes 上,不論是否在閱讀完本文之後,已經意識到 gRPC 不能適當的被 kube-proxy 所 load balance,在這個假設之下,想要嘗試最小時間及開發成本達到 gRPC load balance 效果,可以嘗試使用 方案3 (原為方案2係筆誤) . 因為不論是引入的時間成本或是源碼侵入性都是影響最小的方案。
下集預告
如何優雅地使用及配置 Envoy 反向代理達到 gRPC load balance