gRPC は HTTP/2 プロトコルを使用し、双方向ストリーミング、ヘッダー圧縮、多重化などの機能によってネットワーク効率を向上させます。このトピックでは、Container Service for Kubernetes クラスターに gRPC アプリケーションをデプロイし、クラウドネイティブゲートウェイを使用してそのトラフィックをルーティングする方法について説明します。
前提条件
手順1:gRPC アプリケーションのデプロイ
詳細については、「Deployment を使用したステートレスワークロードの作成」をご参照ください。
この例では、サンプルバックエンドサービスとして grpcbin アプリケーションを使用します。このアプリケーションは複数の gRPC メソッドを実装しています。次のリソースを ACK クラスターに適用します。
Kubernetes Service では、gRPC トラフィックを処理する port の name に grpc を含める必要があります。
apiVersion: apps/v1
kind: Deployment
metadata:
name: grpcbin
spec:
replicas: 1
selector:
matchLabels:
app: grpcbin
template:
metadata:
labels:
app: grpcbin
spec:
serviceAccountName: grpcbin
containers:
- image: docker.io/moul/grpcbin
imagePullPolicy: IfNotPresent
name: grpcbin
ports:
- containerPort: 9000
- containerPort: 9001
resources:
requests:
cpu: '1'
memory: 2Gi
limit:
cpu: '1'
memory: 2Gi
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: grpcbin
---
apiVersion: v1
kind: Service
metadata:
name: grpcbin-grpc
labels:
app: grpcbin
spec:
ports:
- name: grpc
port: 9000
targetPort: 9000
selector:
app: grpcbin
次のコードは、この gRPC サービスの proto 定義を示しています。
syntax = "proto3";
package grpcbin;
service GRPCBin {
rpc Index(EmptyMessage) returns (IndexReply) {}
// パラメーターがなく、空のレスポンスを返すメソッド。
rpc Empty(EmptyMessage) returns (EmptyMessage) {}
// リクエストパラメーターをレスポンスでエコーします。
rpc DummyUnary(DummyMessage) returns (DummyMessage) {}
// 10 個のメッセージを返すサーバー ストリーミング呼び出し。
rpc DummyServerStream(DummyMessage) returns (stream DummyMessage) {}
// 10 個のリクエストを受け付け、最後の 1 つのボディを返すクライアント ストリーミング呼び出し。
rpc DummyClientStream(stream DummyMessage) returns (DummyMessage) {}
// 双方向ストリーミングメソッド。
rpc DummyBidirectionalStreamStream(stream DummyMessage) returns (stream DummyMessage) {}
// このメソッドは指定された gRPC エラーを返します。
rpc SpecificError(SpecificErrorRequest) returns (EmptyMessage) {}
// このメソッドはランダムなエラーを返します。
rpc RandomError(EmptyMessage) returns (EmptyMessage) {}
// このメソッドはヘッダーを返します。
rpc HeadersUnary(EmptyMessage) returns (HeadersMessage) {}
// このメソッドはレスポンスを返しません。
rpc NoResponseUnary(EmptyMessage) returns (EmptyMessage) {}
}
message HeadersMessage {
message Values {
repeated string values = 1;
}
map<string, Values> Metadata = 1;
}
message SpecificErrorRequest {
uint32 code = 1;
string reason = 2;
}
message EmptyMessage {}
message DummyMessage {
message Sub {
string f_string = 1;
}
enum Enum {
ENUM_0 = 0;
ENUM_1 = 1;
ENUM_2 = 2;
}
string f_string = 1;
repeated string f_strings = 2;
int32 f_int32 = 3;
repeated int32 f_int32s = 4;
Enum f_enum = 5;
repeated Enum f_enums = 6;
Sub f_sub = 7;
repeated Sub f_subs = 8;
bool f_bool = 9;
repeated bool f_bools = 10;
int64 f_int64 = 11;
repeated int64 f_int64s= 12;
bytes f_bytes = 13;
repeated bytes f_bytess = 14;
float f_float = 15;
repeated float f_floats = 16;
}
message IndexReply {
message Endpoint {
string path = 1;
string description = 2;
}
string description = 1;
repeated Endpoint endpoints = 2;
}
gRPC は HTTP/2 プロトコル上に構築されており、そのパスは {PackageName}.{ServiceName}/{MethodName} というフォーマットに従います。これにより、クラウドネイティブゲートウェイはパスに基づいてリクエストをルーティングできます。たとえば、grpcbin サービスの Index メソッドへの gRPC コールは、パスが grpcbin.GRPCBin/Index となります。
手順2:gRPC ルーティングの設定
ゲートウェイのサービスソースとして ACK クラスターを追加し、次に grpcbin サービスを追加します。
サービスソースの追加
MSE コンソール にログインします。上部のナビゲーションバーで、リージョンを選択します。
左側のナビゲーション ウィンドウで、Cloud-Native Gateway > ゲートウェイリスト を選択します。 [ゲートウェイ] ページで、ゲートウェイの名前をクリックします。
左側のナビゲーションウィンドウで、Routes をクリックします。表示されるページで、[ソース] タブをクリックします。
-
ソースの作成 をクリックします。ソースの作成 パネルで、[Source Type] を コンテナサービス に設定して、パラメーターを設定してから OK をクリックします。
パラメーター
説明
[ACK/サーバーレス Kubernetes クラスター]
バックエンドサービスが配置されているクラスターを選択します。
説明ゲートウェイを作成する際には、バックエンドクラスターと同じ Virtual Private Cloud (VPC) を選択する必要があります。その後、サービスソースを追加すると、システムはその VPC 内のクラスターを自動的に検出します。
[K8s Ingress リスナー]
-
このオプションを有効にすると、クラウドネイティブゲートウェイは Ingress リソースへの変更を自動的にリッスンして、それらのリソースからドメインとルートの設定を適用します。
-
このオプションを無効にすると、クラウドネイティブゲートウェイは Ingress リソースのリッスンを停止して、以前にそれらのリソースから適用された設定を無効にします。このオプションは注意して使用してください。
重要コンソールで手動で設定されたドメインおよびルート設定は、Ingress リソースからの設定よりも優先度が高くなります。
[IngressClass]
指定された IngressClass に関連付けられた Ingress リソースをリッスンします。
-
空のままにした場合、ゲートウェイはクラスター内のすべての Ingress リソースをリッスンします。
-
値を指定した場合 (単一の値のみサポート)、ゲートウェイは
classアノテーションまたはSpec.IngressClassNameフィールドが指定された値と一致する Ingress リソースをリッスンします。たとえば、これをnginxに設定すると、ゲートウェイは IngressClass がnginxの Ingress リソースと、どの IngressClass にも関連付けられていない Ingress リソースの両方をリッスンします。
[名前空間]
特定の名前空間内の Ingress リソースをリッスンします。
-
空のままにした場合、ゲートウェイはクラスター内のすべての名前空間の Ingress リソースをリッスンします。
-
値を指定した場合 (単一の値のみサポート)、ゲートウェイは指定された名前空間内の Ingress リソースをリッスンします。
[Ingress ステータスの更新]
このオプションを有効にすると、システムは監視対象の Ingress の
Statusフィールド内の IP アドレスを、クラウドネイティブゲートウェイに関連付けられた Server Load Balancer (SLB) インスタンスの IP アドレスに更新します。説明この機能には、ゲートウェイバージョン 1.2.9 以降が必要です。
[セキュリティグループの権限付与]
コンテナクラスターのノードプールにはセキュリティグループが設定されています。クラスター外のコンポーネントがクラスター内のサービスにアクセスできるようにするには、セキュリティグループで必要なサービスポートを開く必要があります。
セキュリティグループは変更できます。詳細については、「セキュリティグループルールの設定」をご参照ください。
-
サービスの追加
MSE コンソールにログオンし、上部のナビゲーションバーでリージョンを選択します。
左側のナビゲーション ウィンドウで、Cloud-Native Gateway > ゲートウェイリスト を選択します。 [ゲートウェイ] ページで、ゲートウェイの名前をクリックします。
左側のナビゲーションウィンドウで、Routes をクリックします。表示されるページで、[サービス] タブをクリックします。
-
Create Service をクリックして、パネルでパラメーターを設定してから OK をクリックします。
パラメーター
説明
[サービスソース]
コンテナサービス を選択します。
[名前空間]
対象クラスターの名前空間を選択します。
[サービス一覧]
リストからサービスを選択します。
grpcbin ルートの追加
MSE コンソールにログオンし、上部のナビゲーションバーでリージョンを選択します。
左側のナビゲーション ウィンドウで、Cloud-Native Gateway > ゲートウェイリスト を選択します。 [ゲートウェイ] ページで、ゲートウェイの名前をクリックします。
左側のナビゲーションウィンドウで、Routes をクリックし、[ルート] タブをクリックします。
-
ルーティングの作成 をクリックします。ルーティングの作成 ページでルートパラメーターを設定して、保存・公開 をクリックします。詳細については、「ルートの追加」をご参照ください。
パラメーター
説明
[ルーティング名]
grpcに設定します。[ドメイン名]
デフォルトのドメイン * を選択します。
[パス]
一致条件を プレフィックスは に設定して、パスの値を
/grpcbin.GRPCBinに設定します。説明gRPC サービスのパス形式は {PackageName}.{ServiceName}/{MethodName} です。この形式に基づいて前方一致のルートを設定できます。
[使用シナリオ]
[Scenario] を 単一サービス に設定します。
[バックエンドサービス]
対象のサービスとサービスポートを選択します。
結果の検証
bloomrpc を使用して gRPC サービスをテストします。レスポンスが正常であれば、サービスが利用可能であることが確認できます。
テストには他の gRPC クライアントを使用することもできます。
BloomRPC を使用して、grpcbin.GRPCBin.DummyUnary メソッドへの Unary Call を実行します。リクエストボディの例:
{
"f_string": "Hello",
"f_strings": [
"Hello"
],
"f_int32": 10,
"f_int32s": [
10
],
"f_enum": 0,
"f_enums": [
0
],
"f_sub": {
"f_string": "Hello"
},
"f_subs": [
{
"f_string": "Hello"
}
],
"f_bool": true,
"f_bools": [
true
],
"f_int64": 20,
"f_int64s": [
20
],
"f_bytes": {}
}
サーバーレスポンスの例 (レイテンシー:約 0.14 秒):
{
"f_strings": [
"Hello"
],
"f_int32s": [
10
],
"f_enums": [
"ENUM_0"
],
"f_subs": [
{
"f_string": "Hello"
}
],
"f_bools": [
true
],
"f_int64s": [
"20"
],
"f_bytess": [],
"f_floats": [
1.100000023841858
],
"f_string": "Hello",
"f_int32": 10,
"f_enum": "ENUM_0",
"f_sub": {
"f_string": "Hello"
}
}