Istio は、gRPC アプリケーションのプロキシレス デプロイメント モデルをサポートしています。このモデルでは、サイドカープロキシをデプロイせずに gRPC アプリケーションを構成できます。これは、Istio のコントロールプレーンでオープンソースの xDS API を使用することで実現されます。これにより、Envoy サイドカープロキシをデプロイする必要なく、トラフィックルーティングや相互トランスポート層セキュリティ (mTLS) 認証などの機能を使用して gRPC ワークロードを管理できます。このトピックでは、gRPC サービスでプロキシレス サービスメッシュ機能を使用する方法について説明します。
前提条件
v1.12.4.2-gc5962641-aliyun 以降のサービスメッシュ (ASM) インスタンスが作成されていること。詳細については、「ASM インスタンスの作成」をご参照ください。
クラスターが ASM インスタンスに追加されていること。詳細については、「ASM インスタンスへのクラスターの追加」をご参照ください。
背景
プロキシレス サービスメッシュ機能を使用すると、データプレーンでの通信をプロキシなしで行うことができます。ただし、初期化とコントロールプレーンとの通信には、引き続きエージェントが必要です。エージェントは次の機能を提供します。
エージェントは、データプレーンでの通信に使用される証明書を取得して回転させます。
エージェントは xDS プロキシとして機能し、istiod に接続してアプリケーションに代わって認証を完了します。
エージェントは、起動時に Envoy プロキシの場合と同じ方法でブートストラップファイルを生成します。ブートストラップファイルは、gRPC ライブラリに istiod への接続方法、データプレーン通信用の証明書の場所、およびコントロールプレーンに送信するデータを指示します。
以下は、Istio のプロキシレス サービスメッシュ機能と互換性がある、またはサポートするフレームワークとプラットフォームの一部です。
Apache Dubbo: Dubbo は、パフォーマンス専有型、Java ベースのオープンソース RPC フレームワークであり、Istio と統合してプロキシレスモードでサービスを呼び出すことができます。詳細については、https://cn.dubbo.apache.org/en/overview/tasks/mesh/proxyless/ をご参照ください。
gRPC フレームワーク: gRPC プロジェクトは、xDS API を大幅にサポートしています。詳細については、コミュニティのドキュメント (https://istio.io/latest/blog/2021/proxyless-grpc/) をご参照ください。
Kitex Proxyless: Kitex サービスは、envoy サイドカーなしでサービスメッシュ コントロールプレーン コンポーネントと直接対話し、xDS プロトコルに基づいてコントロールプレーンによって配信されるサービスガバナンスルールを動的に取得できます。そして、これらのルールは Kitex 対応のルールに変換され、いくつかのサービスガバナンス機能を実装します。詳細については、https://www.cloudwego.io/blog/2022/12/20/kitex-proxyless-practicetraffic-lane-implementation-with-istio-and-opentelemetry/ をご参照ください。
使用上の注意
プロキシレス サービスメッシュ機能には、次の制限があります。
PERMISSIVE モードはサポートされていません。その結果、プレーンテキスト トラフィックと mTLS トラフィックは同時にサポートされません。サーバーで STRICT モードを有効にする場合は、クライアントの mTLS 構成で ISTIO_MUTUAL モードを明示的に指定する必要があります。
grpc.Serve(listener)またはgrpc.Dial("xds://...")を呼び出すことによって開始されたリクエストは、ブートストラップファイルまたは xDS プロキシの準備ができる前に失敗する可能性があります。 holdApplicationUntilProxyStarts パラメーターを true に設定することで、この問題を防ぐことができます。gRPC での xDS API の実装は、Envoy プロキシと互換性がない場合があります。特定の機能が欠落しているか、一部の構成が有効にならない場合があります。Istio 構成がプロキシレス gRPC サービスに適用されていることを確認してください。詳細については、「gRPC の xDS 機能」をご参照ください。
プロキシレスモードでサポートされる機能
gRPC の xDS API は、Envoy プロキシと比較して限られた機能セットのみをサポートしています。次の表に、サポートされている機能を示します。
カテゴリ | サポートされる機能 |
サービスディスカバリ | gRPC サービスは、メッシュに登録されている他のポッドを識別できます。 |
デスティネーションルール |
|
仮想サービス |
|
ピア認証 | mTLS の DISABLE モードと STRICT モードがサポートされています。 |
プロキシレス サービスメッシュ機能の使用
この例では、プロキシレス サービスメッシュ機能をサポートする echo という名前の gRPC アプリケーションを使用します。このセクションでは、サイドカープロキシを使用せずに echo アプリケーションのトラフィックルーティングと mTLS 機能を構成する方法について説明します。
echo アプリケーションのデプロイ
echo アプリケーションの YAML ファイルに
inject.istio.io/templates: grpc-agentアノテーションを追加します。アプリケーションがプロキシレスモードをサポートしている場合は、
inject.istio.io/templates: grpc-agentアノテーションをアプリケーションの YAML ファイルに追加して、プロキシレスモードを有効にできます。さらに、gRPC サーバーの初期化前に xDS プロキシとブートストラップファイルが準備されていることを確認するために、proxy.istio.io/config: '{"holdApplicationUntilProxyStarts": true}'アノテーションを gRPC サーバーの YAML ファイルに追加する必要があります。デフォルトでは、ASM は gRPC サーバーの YAML ファイルにアノテーションを自動的に追加します。次のサンプルコードは、echo アプリケーションの YAML ファイルのアノテーションの一部のみを示しています。 echo アプリケーションの完全な YAML ファイルの詳細については、「grpc-echo」をご参照ください。
template: metadata: annotations: inject.istio.io/templates: grpc-agent proxy.istio.io/config: '{"holdApplicationUntilProxyStarts": true}' labels: app: echo version: v1kubectl を使用して ACK クラスターに接続します。詳細については、「クラスターの kubeconfig ファイルを取得し、kubectl を使用してクラスターに接続する」をご参照ください。
次のコマンドを実行して、echo-grpc 名前空間を作成します。
kubectl create namespace echo-grpc次のコマンドを実行して、echo-grpc 名前空間にラベルを追加します。これにより、echo-grpc 名前空間でサイドカープロキシの挿入が有効になります。
プロキシレスモードでは、サイドカープロキシは使用されません。ただし、コントロールプレーンとの通信には引き続きエージェントを使用する必要があります。したがって、名前空間でサイドカープロキシの挿入を有効にする必要があります。
kubectl label namespace echo-grpc istio-injection=enabled次のコマンドを実行して、echo-grpc アプリケーションをデプロイします。
kubectl -n echo-grpc apply -f https://alibabacloudservicemesh.oss-cn-beijing.aliyuncs.com/asm-grpc-proxyless/grpc-echo.yamlecho-grpc アプリケーションがデプロイされていることを確認します。
次のコマンドを実行して、ポート 17171 を公開します。
kubectl -n echo-grpc port-forward $(kubectl -n echo-grpc get pods -l version=v1 -ojsonpath='{.items[0].metadata.name}') 17171 &次のコマンドを実行して、echo-grpc アプリケーションにアクセスします。
grpcurl -plaintext -d '{"url": "xds:///echo.echo-grpc.svc.cluster.local:7070", "count": 5}' :17171 proto.EchoTestService/ForwardEcho | jq -r '.output | join("")' | grep Hostname予期される出力:
[0 body] Hostname=echo-v1-f76996c45-h7plh [1 body] Hostname=echo-v1-f76996c45-h7plh [2 body] Hostname=echo-v2-7d76b7969-ltlkp [3 body] Hostname=echo-v2-7d76b7969-ltlkp [4 body] Hostname=echo-v1-f76996c45-h7plh
シナリオ 1: トラフィックルーティング機能の使用
デスティネーションルールを作成します。
ワークロードの各バージョンにサブセットを追加するためのデスティネーションルールを作成します。
ASM コンソール にログインします。左側のナビゲーションウィンドウで、 を選択します。
[メッシュ管理] ページで、ASM インスタンスの名前をクリックします。左側のナビゲーションウィンドウで、 を選択します。表示されるページで、[作成] をクリックします。
[作成] ページで、[名前空間] パラメーターを echo-grpc に設定し、[名前] フィールドにデスティネーションルール名を入力し、[ホスト] パラメーターを echo.echo-grpc.svc.cluster.local に設定します。
[サービスバージョン (サブセット)] タブをクリックします。次に、[サービスバージョン (サブセット) の追加] をクリックします。[サブセット 1] セクションで、[名前] パラメーターを v1 に設定します。[ラベルの追加] をクリックし、[キー] パラメーターを version に、[値] パラメーターを v1 に設定します。
[サービスバージョン (サブセット) の追加] をクリックします。[サブセット 2] セクションで、[名前] パラメーターを v2 に設定します。[ラベルの追加] をクリックし、[キー] パラメーターを version に、[値] パラメーターを v2 に設定します。
[作成] をクリックします。
仮想サービスを作成します。
この例では、トラフィックの 80% をバージョン v2 に、トラフィックの 20% をバージョン v1 にルーティングする仮想サービスを作成します。
ASM コンソール にログインします。左側のナビゲーションウィンドウで、 を選択します。
[メッシュ管理] ページで、ASM インスタンスの名前をクリックします。左側のナビゲーションウィンドウで、 を選択します。表示されるページで、[作成] をクリックします。
[作成] ページで、[名前空間] パラメーターを echo-grpc に設定し、[名前] フィールドに仮想サービス名を入力します。
[HTTP ルート] をクリックします。次に、[ルートの追加] をクリックします。[名前] フィールドにルーティングルール名を入力し、[ルートデスティネーションの追加] をクリックします。[ホスト] パラメーターを echo.echo-grpc.svc.cluster.local に、[サブセット] パラメーターを v1 に、[重み] パラメーターを 20 に設定します。
[ルートデスティネーションの追加] をクリックします。[ホスト] パラメーターを echo.echo-grpc.svc.cluster.local に、[サブセット] パラメーターを v2 に、[重み] パラメーターを 80 に設定します。
[作成] をクリックします。
次のコマンドを実行して、echo アプリケーションに 10 個のリクエストを送信します。
grpcurl -plaintext -d '{"url": "xds:///echo.echo-grpc.svc.cluster.local:7070", "count": 10}' :17171 proto.EchoTestService/ForwardEcho | jq -r '.output | join("")' | grep ServiceVersion予期される出力:
[0 body] ServiveVersion=v2 [0 body] ServiveVersion=v1 [0 body] ServiveVersion=v2 [0 body] ServiveVersion=v2 [0 body] ServiveVersion=v2 [0 body] ServiveVersion=v2 [0 body] ServiveVersion=v1 [0 body] ServiveVersion=v2 [0 body] ServiveVersion=v2 [0 body] ServiveVersion=v2前の結果は、echo アプリケーションに送信された 10 個のリクエストのうち、8 個のリクエストがバージョン v2 に送信され、2 個のリクエストがバージョン v1 に送信されたことを示しています。これは、トラフィックルーティング構成が有効であることを示しています。
シナリオ 2: mTLS 認証の使用
mTLS 認証を有効にして、サービス間の通信を暗号化できます。
デスティネーションルールを作成します。
クライアントの mTLS を有効にするデスティネーションルールを作成します。
ASM コンソール にログインします。
左側のナビゲーションウィンドウで、 を選択します。
[メッシュ管理] ページで、構成する ASM インスタンスを見つけます。 ASM インスタンスの名前をクリックするか、管理[アクション] 列の をクリックします。
ASM インスタンスの詳細ページで、左側のナビゲーションウィンドウの を選択します。 DestinationRule ページで、[作成] をクリックします。
[作成] ページで、[名前空間] パラメーターを echo-grpc に設定し、[名前] フィールドにデスティネーションルール名を入力し、[ホスト] パラメーターを echo.echo-grpc.svc.cluster.local に設定します。
[トラフィックポリシー] をクリックします。次に、[ポリシーの追加] をクリックし、[クライアント TLS] をオンにし、Istio 相互[TLS モード] ドロップダウンリストから を選択します。
[作成] をクリックします。
次のコマンドを実行して、echo アプリケーションにアクセスします。
grpcurl -plaintext -d '{"url": "xds:///echo.echo-grpc.svc.cluster.local:7070"}' :17171 protoproto.EchoTestService/ForwardEcho | jq -r '.output | join("")'予期される出力:
ERROR: Code: Unknown Message: 1/1 requests had errors; first error: rpc error: code = Unavaliable desc = all SubConna are in TransientFailureサーバーで mTLS が無効になっているため、リクエストは失敗します。
ピア認証ポリシーを作成します。
サーバーで mTLS を有効にするピア認証ポリシーを作成します。
ASM コンソール にログインします。左側のナビゲーションウィンドウで、 を選択します。
[メッシュ管理] ページで、ASM インスタンスの名前をクリックします。左側のナビゲーションウィンドウで、 を選択します。表示されるページで、[mTLS モードの作成] をクリックします。
[mTLS モードの作成] ページで、[名前空間] パラメーターを echo-grpc に設定し、[名前] フィールドにピア認証ポリシー名を入力し、[mTLS モード (名前空間全体)] パラメーターを [STRICT - MTLS を厳密に適用] に設定します。次に、[作成] をクリックします。
次のコマンドを実行して、echo アプリケーションにアクセスします。
grpcurl -plaintext -d '{"url": "xds:///echo.echo-grpc.svc.cluster.local:7070"}' :17171 proto.EchoTestService/ForwardEcho | jq -r '.output | join("")'予期される出力:
[0] grpcecho.Echo(${xds:///echo.echo-grpc.svc.cluster.local:7070 map [] 0 <nil> 5s false }) [0 body] RequestHeader=x-request-id:0 [0 body] Host=echo.echo-grpc.svc.cluster.local [0 body] RequestHeader=:authorit:echo.echo-grpc.svc.cluster.local:7070 ........前の結果は、リクエストが成功したことを示しています。
gRPC サービスのコードの変更
gRPC サービスがプロキシレスモードをサポートしていない場合は、gRPC サービスのクライアントとサーバーのコードを変更して、xDS API のサポートを有効にする必要があります。その後、トラフィックルーティングなどのプロキシレスモードの機能を使用できます。
V1.39.0 以降の gRPC アプリケーションの場合のみ、アプリケーションコードを変更することで xDS API のサポートを有効にできます。
gRPC クライアントのコードの変更
次のコードスニペットに示すように、gRPC クライアントのコードを変更します。これにより、アプリケーションは xDS リゾルバーとバランサーを登録できます。
次のコードをメインパッケージ、または grpc.Dial("xds://...") が呼び出されるパッケージに追加します。
import _ "google.golang.org/grpc/xds"次のコードスニペットに示すように、gRPC クライアントのコードを変更します。これにより、xds:/// スキームを使用する URL を使用して gRPC 接続を確立する必要があります。
conn, err := grpc.DialContext(ctx, "xds:///foo.ns.svc.cluster.local:7070")次のコードスニペットに示すように、gRPC クライアントのコードを変更します。これにより、特別な TransportCredentials オプションが DialContext に渡され、mTLS が有効になります。
FallbackCreds パラメーターの設定により、istiod がセキュリティ構成を送信していない場合に、接続イベントが成功します。
import "google.golang.org/grpc/credentials/xds" ... creds, err := xds.NewClientCredentials(xds.ClientOptions{ FallbackCreds: insecure.NewCredentials() }) // handle err conn, err := grpc.DialContext( ctx, "xds:///foo.ns.svc.cluster.local:7070", grpc.WithTransportCredentials(creds), )
gRPC サーバーのコードの変更
次のコードスニペットに示すように、gRPC サーバーのコードを変更します。これにより、特別なコンストラクターを使用して gRPC サーバーが作成されます。
import "google.golang.org/grpc/xds" ... server = xds.NewGRPCServer() RegisterFooServer(server, &fooServerImpl)プロトコルバッファコンパイラによって生成された Go コードが古い場合は、Go コードを再生成します。これにより、コードが xDS サーバーと互換性があることが保証されます。
次のコードは、生成される RegisterFooServer 関数を示しています。
func RegisterFooServer(s grpc.ServiceRegistrar, srv FooServer) { s.RegisterService(&FooServer_ServiceDesc, srv) }セキュリティサポートを有効にするには、次のコードスニペットに示すように、gRPC サーバーのコードを変更します。
creds, err := xds.NewServerCredentials(xdscreds.ServerOptions{FallbackCreds: insecure.NewCredentials()}) // handle err server = xds.NewGRPCServer(grpc.Creds(creds))