Istioは、REST(HTTP)とgRPCの両方をプロキシできます。公式ドキュメントは、IstioがHTTP、HTTPS、gRPC、素のTCPを含むすべてのTCPトラフィックをプロキシすると説明しています。ただし、ルーティングや豊富なメトリクスといった機能を使うにはプロトコルを知る必要があり、それを自動で判別させるのか、自分で書いて伝えるのかが、この記事のテーマです。以下の内容は、Istio公式ドキュメントProtocol Selection(2026-10-20確認、ドキュメント表記バージョン1.31.2)を整理したものです。
プロトコルはどうやって伝えるのですか?
方法は2つです。1つはServiceのポート名を <protocol>[-<suffix>] の形式で付けること、もう1つは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 は、サイドカーでもゲートウェイでも http2 と同じ扱いです。そのため、gRPCのポートに grpc と書いても http2 と書いても、同じHTTP/2として処理されます。
自動検出に任せてもよいですか?
サイドカーは、HTTPとHTTP/2を自動で検出します。検出できなければ、そのトラフィックは素のTCPとして扱います。するとTCPに見える接続では、HTTP単位のルーティングやメトリクスが使えません。またMySQLのように、サーバーが先に話しかける(Server First)プロトコルは自動検出と合わないため、名前で直接指定する必要があります。ですから、運用するサービスでは、最初からポート名を規則どおりに付けるほうが安全です。
ゲートウェイはなぜ別に見る必要があるのですか?
サイドカーと違い、ゲートウェイは既定ではバックエンドに送る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は1本の接続を長く開いたままにして、その上で複数のリクエストを送るため、接続が1つのPodに付くと、リクエストもそちらに偏ります。一方、Istioのプロキシ(Envoy)は、gRPCがHTTP/2であることを知っているので、リクエスト単位で分散できます。これが、gRPCサービスにメッシュを付ける代表的な理由です。この部分は上のドキュメントのページの内容ではなく、L4とL7の分散の一般的な違いを説明したものなので、実際の分散結果は環境で直接確認してください。
よくある質問
UDPもプロキシされますか?
いいえ。ドキュメントによると、UDPのようなTCP以外のプロトコルはプロキシされず、いつもどおりに動作し、Istioプロキシによる横取りを受けません。そのため、インバウンドやエグレスのゲートウェイのような、プロキシ専用の構成要素でも使えません。
ポート名とappProtocolを両方書いたら、どちらが優先されますか?
appProtocol です。両方が定義されている場合、ポート名は後回しになります。
gRPCのポート名は、grpcとhttp2のどちらがよいですか?
動作は同じです。公式の表で grpc は http2 と同じ扱いなので、読む人がすぐにgRPCだと分かる grpc を使えばよいでしょう。