Service Mesh (ASM) を使用すると、さまざまなプログラミング言語を使用する gRPC サーバーにリクエストを均等に分散できます。このトピックでは、Container Service for Kubernetes (ACK) クラスターに gRPC サービスをデプロイして、gRPC サーバー間のロードバランシングを実装する方法について説明します。このトピックでは、ロードバランシングの効果を検証する方法についても説明します。
背景情報
このトピックでは、4 つの gRPC クライアントも異なるプログラミング言語を使用します。GRPC_SERVER 変数で指定された grpc-server-svc.grpc-best.svc.cluster.local サービスを gRPC クライアントが呼び出すと仮定します。ASM が内部リクエストを受信すると、リクエストは 4 つの gRPC サーバーに均等にルーティングされます。さらに、ロードバランシングポリシーに基づいて外部リクエストを 4 つの gRPC サーバーにルーティングするようにイングレスゲートウェイを設定できます。
サンプルプロジェクト
gRPC のサンプルプロジェクトについては、hello-servicemesh-grpc をダウンロードしてください。このトピックのディレクトリは、hello-servicemesh-grpc のディレクトリです。
このトピックのイメージリポジトリは参考用です。イメージスクリプトを使用して、イメージをビルドし、セルフマネージドイメージリポジトリにプッシュします。イメージスクリプトの詳細については、「hello-servicemesh-grpc」をご参照ください。
ステップ 1: gRPC サーバー上に gRPC サービスを作成する
この例では、grpc-server-svc という名前の gRPC サービスがすべての gRPC サーバー上に作成されます。
spec.ports.name パラメーターの値は grpc で始まる必要があります。
次の内容を含む grpc-server-svc ファイルを作成します。
apiVersion: v1 kind: Service metadata: namespace: grpc-best name: grpc-server-svc labels: app: grpc-server-svc spec: ports: - port: 9996 name: grpc-port selector: app: grpc-server-deploy次のコマンドを実行して gRPC サービスを作成します。
kubectl apply -f grpc-server-svc.yaml
ステップ 2: 各 gRPC サーバー上に Deployment を作成する
以下の手順では、Node.js 言語の gRPC サーバーの grpc-server-node.yaml ファイルを使用して gRPC サーバー上に Deployment を作成する方法を示します。他の言語の gRPC サーバーの Deployment の詳細については、「サンプルプロジェクト」セクションでダウンロードした hello-servicemesh-grpc ファイルをご参照ください。
ステップ 1 で作成した gRPC サービスのセレクターに一致させるには、gRPC サーバー上の 4 つの Deployment の app ラベルを grpc-server-deploy に設定する必要があります。異なる言語の 4 つの gRPC サーバー上の各 Deployment には、一意の version ラベルが必要です。
次の内容を含むgrpc-server-node YAML ファイルを作成します:
apiVersion: apps/v1 kind: Deployment metadata: namespace: grpc-best name: grpc-server-node labels: app: grpc-server-deploy version: v3 spec: replicas: 1 selector: matchLabels: app: grpc-server-deploy version: v3 template: metadata: labels: app: grpc-server-deploy version: v3 spec: containers: - name: grpc-server-deploy image: registry.cn-hangzhou.aliyuncs.com/aliacs-app-catalog/asm-grpc-server-node:1.0.0 imagePullPolicy: Always ports: - containerPort: 9996 name: grpc-port次のコマンドを実行して Deployment を作成します。
kubectl apply -f grpc-server-node.yaml
ステップ 3: 各 gRPC クライアント上に Deployment を作成する
gRPC クライアントの Deployment と gRPC サーバーの Deployment は、次の点で異なります。
gRPC サーバーは起動後、継続的に実行されます。gRPC クライアントはリクエストが完了すると実行を停止します。したがって、クライアント側のコンテナーが停止しないようにするには、無限ループが必要です。
gRPC クライアントで GRPC_SERVER 変数を設定する必要があります。gRPC クライアントの Pod が起動すると、GRPC_SERVER 変数の値が gRPC クライアントに渡されます。
4 つの gRPC クライアントのそれぞれに Deployment を作成する必要があります。以下の手順では、Go 言語の gRPC クライアントの grpc-client-go.yaml ファイルを使用して gRPC クライアント上に Deployment を作成する方法を示します。
次の内容を含む grpc-client-go ファイルを作成します。
apiVersion: apps/v1 kind: Deployment metadata: namespace: grpc-best name: grpc-client-go labels: app: grpc-client-go spec: replicas: 1 selector: matchLabels: app: grpc-client-go template: metadata: labels: app: grpc-client-go spec: containers: - name: grpc-client-go image: registry.cn-hangzhou.aliyuncs.com/aliacs-app-catalog/asm-grpc-client-go:1.0.0 command: ["/bin/sleep", "3650d"] env: - name: GRPC_SERVER value: "grpc-server-svc.grpc-best.svc.cluster.local" imagePullPolicy: Always次のコマンドを実行して Deployment を作成します。
kubectl apply -f grpc-client-go.yaml
command: ["/bin/sleep", "3650d"] の行は、Pod の起動後に Go 言語の gRPC クライアントの Pod をスリープモードで実行し続けるために実行されるコマンドを示します。env の GRPC_SERVER 変数は grpc-server-svc.grpc-best.svc.cluster.local に設定されます。
ステップ 4: gRPC サービスと Deployment をデプロイする
次のコマンドを実行して、ACK クラスターに grpc-best という名前の名前空間を作成します。
alias k="kubectl --kubeconfig $USER_CONFIG" k create ns grpc-best次のコマンドを実行して、名前空間の自動サイドカーインジェクションを有効にします。
k label ns grpc-best istio-injection=enabled次のコマンドを実行して、gRPC サービスと 8 つの Deployment をデプロイします。
kubectl apply -f grpc-svc.yaml kubectl apply -f deployment/grpc-server-java.yaml kubectl apply -f deployment/grpc-server-python.yaml kubectl apply -f deployment/grpc-server-go.yaml kubectl apply -f deployment/grpc-server-node.yaml kubectl apply -f deployment/grpc-client-java.yaml kubectl apply -f deployment/grpc-client-python.yaml kubectl apply -f deployment/grpc-client-go.yaml kubectl apply -f deployment/grpc-client-node.yaml
結果の検証
Pod を使用して gRPC サービスのロードバランシングを検証する
gRPC クライアントの Pod から gRPC サーバー上の gRPC サービスにリクエストを送信することで、gRPC サーバー間のロードバランシングを検証できます。
次のコマンドを実行して、4 つの gRPC クライアントの Pod の名前を取得します。
client_java_pod=$(k get pod -l app=grpc-client-java -n grpc-best -o jsonpath={.items..metadata.name})client_go_pod=$(k get pod -l app=grpc-client-go -n grpc-best -o jsonpath={.items..metadata.name})client_node_pod=$(k get pod -l app=grpc-client-node -n grpc-best -o jsonpath={.items..metadata.name})client_python_pod=$(k get pod -l app=grpc-client-python -n grpc-best -o jsonpath={.items..metadata.name})次のコマンドを実行して、gRPC クライアントの Pod から 4 つの gRPC サーバー上の gRPC サービスにリクエストを送信します。
k exec "$client_java_pod" -c grpc-client-java -n grpc-best -- java -jar /grpc-client.jark exec "$client_go_pod" -c grpc-client-go -n grpc-best -- ./grpc-clientk exec "$client_node_pod" -c grpc-client-node -n grpc-best -- node proto_client.jsk exec "$client_python_pod" -c grpc-client-python -n grpc-best -- sh /grpc-client/start_client.shFOR ループを使用して、gRPC サーバー間のロードバランシングを検証します。この例では、Node.js 言語の gRPC クライアントが使用されます。
for ((i = 1; i <= 100; i++)); do kubectl exec "$client_node_pod" -c grpc-client-node -n grpc-best -- node kube_client.js > kube_result done sort kube_result | grep -v "^[[:space:]]*$" | uniq -c | sort -nrk1期待される出力:
26 Talk:PYTHON 25 Talk:NODEJS 25 Talk:GOLANG 24 Talk:JAVA出力は、gRPC サービスがデプロイされている 4 つの gRPC サーバーがほぼ同数のリクエストを受信したことを示しています。ロードバランシングの結果は、ASM がロードバランシングポリシーに基づいて、gRPC サービスがデプロイされている 4 つの gRPC サーバーに外部リクエストをルーティングできることを示しています。
イングレスゲートウェイを使用して gRPC サービスのロードバランシングを検証する
イングレスゲートウェイを使用して、gRPC サーバー間のロードバランシングを検証できます。
ポート 9996 を公開するイングレスゲートウェイを作成します。
詳細については、「イングレスゲートウェイサービスの作成」をご参照ください。
次の YAML コードを使用して Istio ゲートウェイを作成します。
詳細については、「Istio ゲートウェイの管理」をご参照ください。
apiVersion: networking.istio.io/v1alpha3 kind: Gateway metadata: namespace: grpc-best name: grpc-gateway spec: selector: istio: ingressgateway servers: - port: number: 9996 name: grpc protocol: GRPC hosts: - "*"次の YAML コードを使用して仮想サービスを作成します。
詳細については、「仮想サービスの管理」をご参照ください。
apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: namespace: grpc-best name: grpc-vs spec: hosts: - "*" gateways: - grpc-gateway http: - route: - destination: host: grpc-server-svc.grpc-best.svc.cluster.local port: number: 9996次のコマンドを実行して、イングレスゲートウェイの IP アドレスを取得します。
INGRESS_IP=$(k -n istio-system get service istio-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].ip}')FOR ループを使用して、gRPC サーバー間のロードバランシングを検証します。
docker run -d --name grpc_client_node -e GRPC_SERVER="${INGRESS_IP}" registry.cn-hangzhou.aliyuncs.com/aliacs-app-catalog/asm-grpc-client-node:1.0.0 /bin/sleep 3650d client_node_container=$(docker ps -q) docker exec -e GRPC_SERVER="${INGRESS_IP}" -it "$client_node_container" node kube_client.js for ((i = 1; i <= 100; i++)); do docker exec -e GRPC_SERVER="${INGRESS_IP}" -it "$client_node_container" node kube_client.js >> kube_result done sort kube_result | grep -v "^[[:space:]]*$" | uniq -c | sort -nrk1期待される出力:
26 Talk:PYTHON 25 Talk:NODEJS 25 Talk:GOLANG 24 Talk:JAVA出力は、gRPC サービスがデプロイされている 4 つの gRPC サーバーがほぼ同数のリクエストを受信したことを示しています。ロードバランシングの結果は、ASM がロードバランシングポリシーに基づいて、gRPC サービスがデプロイされている 4 つの gRPC サーバーに外部リクエストをルーティングできることを示しています。