Istio 可以同時代理 REST(HTTP)與 gRPC。官方文件說明,Istio 會代理所有 TCP 流量,包括 HTTP、HTTPS、gRPC 與純 TCP。不過,要使用路由或豐富的指標等功能,就必須知道協定,而要讓它自動判斷,還是自己寫明告知,正是這篇文章的主題。以下內容整理自 Istio 官方文件 Protocol Selection(2026-10-20 確認,文件標示版本為 1.31.2)。
要怎麼告知協定?
有兩種方式。一種是把 Service 的連接埠名稱取成 <protocol>[-<suffix>] 的格式,另一種是在 Kubernetes 1.18 以上使用 appProtocol 欄位。兩者都寫時,appProtocol 優先於連接埠名稱。
apiVersion: v1
kind: Service
metadata:
name: orders
spec:
ports:
- name: http-web # 以名稱指定: REST
port: 80
- name: grpc-api # 以名稱指定: gRPC
port: 9090
- name: backend # 以 appProtocol 指定
port: 8081
appProtocol: grpc
在官方文件的支援表中,grpc 與 grpc-web 在 sidecar 和閘道上都與 http2 同樣處理。所以 gRPC 連接埠不管寫 grpc 還是 http2,都會以相同的 HTTP/2 處理。
交給自動偵測可以嗎?
Sidecar 會自動偵測 HTTP 與 HTTP/2。偵測不到時,該流量就視為純 TCP。這樣在看起來是 TCP 的連線上,就無法使用以 HTTP 為單位的路由與指標。另外,像 MySQL 這種由伺服器先開口(Server First)的協定,與自動偵測不相容,必須用名稱直接指定。所以對於自己營運的服務,一開始就依規則命名連接埠比較安全。
為什麼閘道要另外看?
與 sidecar 不同,閘道預設不會自動判斷要送往後端的是哪種 HTTP。沒有明確指定時,所有進來的 HTTP 請求都會以 HTTP/1.1 轉送。因此如果後端是 gRPC,必須指定 grpc 或 http2,才會以 HTTP/2 轉送。
除了明確指定,也可以在 Service 加上 useClientProtocol 選項。這個選項會讓閘道以與進來的請求相同的協定轉送。不過官方文件警告,用在不支援 HTTP/2 的服務上可能有風險。因為 HTTPS 閘道一律會宣告支援 HTTP/1.1 與 HTTP/2,即使後端不能用 HTTP/2,新的用戶端也可能選擇 HTTP/2。
和 Kubernetes 預設的 Service 有什麼不同?
Kubernetes 預設的 Service 以 L4(連線)為單位分配負載。gRPC 會長時間開著一條連線,並在上面送出多個請求,所以連線一旦接到某個 Pod,請求也會集中到那裡。相對地,Istio 的代理(Envoy)知道 gRPC 是 HTTP/2,可以逐個請求分配。這就是替 gRPC 服務加上網格的代表性理由。這部分不是上面那份文件頁面的內容,而是說明 L4 與 L7 分配的一般差異,實際的分配結果請在自己的環境中直接確認。
常見問題
UDP 也會被代理嗎?
不會。依文件所述,UDP 這類非 TCP 協定不會被代理,會照常運作,也不會被 Istio 代理攔截。所以在入口或出口閘道這類僅限代理的元件中也無法使用。
連接埠名稱與 appProtocol 都寫了,哪一個優先?
appProtocol。兩者都有定義時,連接埠名稱會退居次位。
gRPC 連接埠名稱用 grpc 還是 http2 比較好?
行為相同。官方表格中 grpc 與 http2 同樣處理,所以用讓讀者一眼就知道是 gRPC 的 grpc 即可。