Google Kubernetes Engine とプロキシレス gRPC サービスを設定する

このガイドでは、Google Kubernetes Engine、gRPC アプリケーション、Cloud Service Mesh に必要なロード バランシング コンポーネントを構成する方法について説明します。

このガイドの手順に進む前に、プロキシレス gRPC サービスで Cloud Service Mesh を設定する準備を確認してください。

概要

GKE とプロキシレス gRPC サービスで Cloud Service Mesh をセットアップするには、次の作業が必要です。

  1. GKE クラスタを準備します。
  2. gRPC サーバー アプリケーションを Kubernetes Service としてデプロイします。GKE のデプロイ仕様にアノテーションを付けて、サービスのネットワーク エンドポイント グループ(NEG)を自動的に作成します。
  3. NEG とその他の Google Cloud ロード バランシング コンポーネントを使用して Cloud Service Mesh を構成します。
  4. プロキシレス gRPC クライアント アプリケーションを使用してトラフィックを gRPC サーバー アプリケーションに送信することで、デプロイが正しく機能していることを確認する。

Cloud Service Mesh 用に GKE クラスタを構成する

このセクションでは、GKE クラスタを Cloud Service Mesh と連携できるようにする方法について説明します。

GKE クラスタの要件

GKE クラスタは次の要件を満たす必要があります。

GKE クラスタの作成

次の例では、us-central1-a zone 内に grpc-td-cluster という GKE クラスタを作成する方法を示します。

Console

Google Cloud コンソールを使用してクラスタを作成するには、次の手順を行います。

  1. Google Cloud コンソールで Google Kubernetes Engine のメニューに移動します。

    Google Kubernetes Engine のメニューに移動

  2. [クラスタを作成] をクリックします。

  3. 標準クラスタ テンプレートを選択するか、ワークロードに適したテンプレートを選択します。

  4. 必要に応じて、テンプレートをカスタマイズします。次のフィールドに値を入力する必要があります。

    • 名前:grpc-td-cluster」と入力します。
    • ロケーション タイプ: Zonal
    • ゾーン: us-central1-a
    • ノードプール:
  5. 左側のメニューで、[default-pool] をクリックします。

  6. [名前] を grpc-td-cluster に変更します。

  7. [サイズ] に、作成するノード数を入力します。ノードとそのリソース(ファイアウォール ルートなど)に使用できるリソース割り当てが必要です。

  8. 左側のメニューで [ノード] をクリックします。

  9. [マシンの構成] の [マシン ファミリー] で、[コンピューティング最適化] をクリックします。

  10. マシンタイプを選択します。マシンタイプごとの料金については、Compute Engine の料金のページをご覧ください。

  11. [ネットワーキング] で、ネットワーク タグ allow-health-checks を追加します。

  12. 左側のメニューで [セキュリティ] をクリックします。

  13. [アクセス スコープ] で [すべての Cloud API に完全アクセス権を許可] を選択します。

  14. [作成] をクリックします。

Google Cloud コンソールでクラスタを作成したら、クラスタとやり取りするように kubectl を構成する必要があります。詳細については、kubeconfig エントリの生成をご覧ください。

gcloud

クラスタを作成します。

gcloud container clusters create grpc-td-cluster \
   --zone us-central1-a \
   --scopes=https://www.googleapis.com/auth/cloud-platform \
   --tags=allow-health-checks \
   --enable-ip-alias

必要な GKE クラスタ権限の取得

次のコマンドを実行して、作成したクラスタに切り替えます。これにより、kubectl は正しいクラスタを指すようになります。

gcloud

gcloud container clusters get-credentials grpc-td-cluster \
    --zone us-central1-a

GKE サービスの構成

このセクションでは、Cloud Service Mesh と連携する GKE デプロイ仕様の準備方法について説明します。これは、NEG アノテーションを使用して GKE helloworld サンプル サービスを構成するものです。

helloworld サンプル サービスは、gRPC クライアントのリクエストに応じてメッセージを返す gRPC サーバー アプリケーションです。helloworld サービスには特別な役割はありません。これはプロキシレス gRPC サービスではなく、任意の gRPC クライアントからのリクエストに応答できます。

「プロキシレス」が機能するのは、gRPC クライアント アプリケーションが Cloud Service Mesh に接続されて、helloworld サービスについて学習し、helloworld に関連付けられた Pod にトラフィックを送信できる場合のみです。これは、IP アドレスまたは DNS ベースの名前解決に依存しません。

NEG を使用して GKE サービスを構成する

Cloud Service Mesh で使用する GKE サービスを構成する最初のステップは、NEG を通じてサービスを公開することです。NEG で公開するには、各仕様に、公開するポートと一致する次のアノテーションが必要です。

...
metadata:
  annotations:
    cloud.google.com/neg: '{"exposed_ports":{"8080":{"name": "example-grpc-server"}}}'

このアノテーションは、サービスを初めてデプロイするときにスタンドアロンの NEG を作成します。この NEG には、Pod の IP アドレスとポートのエンドポイントが含まれています。詳細と例については、スタンドアロン ネットワーク エンドポイント グループをご覧ください。

次の例では、ポート 8080 で公開されている helloworld Kubernetes Service をデプロイします。これは、サービスがクラスタに表示されるポートです。Pod 内の gRPC サービスが targetPort 50051 でリッスンしています。これは、リクエストの送信先の Pod のポートです。通常、便宜上、porttargetPort に同じ値が設定されますが、この例では、NEG のアノテーションで使用する正しい値を示ために異なる値を使用しています。

cat << EOF > grpc-td-helloworld.yaml
apiVersion: v1
kind: Service
metadata:
  name: helloworld
  annotations:
    cloud.google.com/neg: '{"exposed_ports":{"8080":{"name": "example-grpc-server"}}}'
spec:
  ports:
  - port: 8080
    name: helloworld
    protocol: TCP
    targetPort: 50051
  selector:
    run: app1
  type: ClusterIP

---
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    run: app1
  name: app1
spec:
  selector:
    matchLabels:
      run: app1
  replicas: 2
  template:
    metadata:
      labels:
        run: app1
    spec:
      containers:
      - image: grpc/java-example-hostname:1.50.2
        name: app1
        ports:
        - protocol: TCP
          containerPort: 50051
EOF
kubectl apply -f grpc-td-helloworld.yaml

新しい helloworld サービスが作成されたことを確認します。

kubectl get svc

kubectl get svc の出力は次のようになります。

NAME           TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
helloworld     ClusterIP   10.71.9.71   <none>        8080/TCP  41m
[..skip..]

アプリケーション Pod が動作していることを確認します。

kubectl get pods

kubectl get pods の出力は次のようになります。

NAME                        READY     STATUS    RESTARTS   AGE
app1-6db459dcb9-zvfg2   1/1       Running   0          6m
app1-6db459dcb9-hlvhj   1/1       Running   0          6m
[..skip..]

NEG 名が正しいことを確認します。

Console

ネットワーク エンドポイント グループのリストを表示するには、Google Cloud コンソールの [ネットワーク エンドポイント グループ] ページに移動します。example-grpc-server という名前の NEG が表示されます。
[ネットワーク エンドポイント グループ] ページに移動

gcloud

# List the NEGs
gcloud compute network-endpoint-groups list \
    --filter "name=example-grpc-server" --format "value(name)"

# Optionally examine the NEG
gcloud compute network-endpoint-groups describe example-grpc-server \
    --zone us-central1-a

# Optionally examine the endpoint(s) contained
gcloud compute network-endpoint-groups list-network-endpoints example-grpc-server \
    --zone us-central1-a

ロード バランシング コンポーネントを使用した Cloud Service Mesh を構成する

このセクションでは、サービスの Google Cloud 負荷分散コンポーネントを構成する方法について説明します。これらのコンポーネントには、プロキシレス gRPC クライアントと GKE サービスとの通信を可能にする構成情報が含まれています。

以下の Cloud Service Mesh の構成例では、次のことを前提としています。

  • NEG とその他のリソースはすべて、ゾーン us-central1-a の自動モードのデフォルト ネットワークに作成されます。
  • Google Cloud CLI を使用する場合、クラスタの NEG 名は example-grpc-server になります。

ヘルスチェック、ファイアウォール ルール、バックエンド サービスの作成

このセクションでは、ヘルスチェックとヘルスチェック用のファイアウォール ルールを作成します。ヘルスチェックでは gRPC ヘルスチェック プロトコルを使用する必要があります。このファイアウォール ルールにより、ヘルスチェック プローブはデプロイメント内の VM に接続できます。--use-serving-port ディレクティブは、ヘルスチェックで各エンドポイントに構成されているリスニング ポートを取得するために使用されます。

このファイアウォール ルールは、ネットワーク内におけるインスタンスへのヘルスチェックの受信接続を許可します。

このセクションでは、INTERNAL_SELF_MANAGED とプロトコル GRPC の負荷分散方式でグローバル バックエンド サービスを作成し、ヘルスチェックをバックエンド サービスに関連付けます。

詳細については、ヘルスチェックの作成をご覧ください。

gcloud

  1. ヘルスチェックを作成します。

    gcloud compute health-checks create grpc grpc-gke-helloworld-hc \
     --use-serving-port
    
  2. ファイアウォール ルールを作成します。

    gcloud compute firewall-rules create grpc-gke-allow-health-checks \
      --network default --action allow --direction INGRESS \
      --source-ranges 35.191.0.0/16,130.211.0.0/22 \
      --target-tags allow-health-checks \
      --rules tcp:50051
    
  3. バックエンド サービスを作成します。

    gcloud compute backend-services create grpc-gke-helloworld-service \
       --global \
       --load-balancing-scheme=INTERNAL_SELF_MANAGED \
       --protocol=GRPC \
       --health-checks grpc-gke-helloworld-hc
    
  4. バックエンド サービスにバックエンド NEG を追加します。

    gcloud compute backend-services add-backend grpc-gke-helloworld-service \
       --global \
       --network-endpoint-group example-grpc-server \
       --network-endpoint-group-zone us-central1-a \
       --balancing-mode RATE \
       --max-rate-per-endpoint 5
    

ルーティング ルール マップの作成

このセクションでは、URL マップ、パスマッチャー、ホストルールを作成して、ホスト名とパスに基づいてサービスのトラフィックをルーティングします。次の例では、サービス名として helloworld-gke を使用しています。gRPC クライアントは、helloworld サービスに接続するときに、ターゲット URI でこのサービス名を使用します。また、ターゲット gRPC プロキシと転送ルールを作成します。

詳細については、ルーティング ルールマップをご覧ください。

次の例では、サービス名 helloworld-gke とポート 8000 を使用します。つまり、このサービスへの接続には、gRPC クライアントが xds:///helloworld-gke:8000 を使用する必要があり、URL マップにホストルール helloworld-gke:8000 を構成する必要があります。前のセクションの Kubernetes Service 仕様に示されているサービスポート 8080 は、Cloud Service Mesh では使用されません。これは、helloworld-gke:8000targetPort 50051 でリッスンしている NEG エンドポイントによって直接解決されるためです。通常、URL マップのホストルールのポートと Kubernetes Service 仕様の port および targetPort はすべて、便宜上同じ値に設定されますが、この例では port は Cloud Service Mesh では使用されないことを示すために異なる値を使用しています。

gcloud

  1. URL マップを作成します。

    gcloud compute url-maps create grpc-gke-url-map \
    --default-service grpc-gke-helloworld-service
    
  2. パスマッチャーを作成します。

    gcloud compute url-maps add-path-matcher grpc-gke-url-map \
    --default-service grpc-gke-helloworld-service \
    --path-matcher-name grpc-gke-path-matcher \
    --new-hosts helloworld-gke:8000
    
  3. ターゲット gRPC プロキシを作成します。

    gcloud compute target-grpc-proxies create grpc-gke-proxy \
    --url-map grpc-gke-url-map \
    --validate-for-proxyless
    
  4. 転送ルールを作成します。

    gcloud compute forwarding-rules create grpc-gke-forwarding-rule \
    --global \
    --load-balancing-scheme=INTERNAL_SELF_MANAGED \
    --address=0.0.0.0 \
    --target-grpc-proxy=grpc-gke-proxy \
    --ports 8000 \
    --network default
    

これで、Cloud Service Mesh は、URL マップで指定されたサービスの NEG のエンドポイント間でトラフィックを負荷分散するように構成されます。

構成の確認

構成プロセスが完了したら、プロキシレス gRPC クライアントを使用して helloworld gRPC サーバーに到達できることを確認します。このクライアントは Cloud Service Mesh に接続して helloworld サービス(grpc-gke-helloworld-service バックエンド サービスを使用して Cloud Service Mesh で構成された)に関する情報を取得し、この情報を使用してトラフィックをサービスのバックエンドに送信します。

また、Google Cloud コンソールの Cloud Service Mesh セクションで構成済みのサービス helloworld-gke に関する情報を確認し、バックエンドが正常であると報告されたかどうかも確認できます。

プロキシレス gRPC クライアントによる確認

次の例では、gRPC クライアントを異なる言語で、または grpcurl ツールを使用して、Cloud Service Mesh がメッシュでトラフィックが正しくルーティングされていることを確認します。クライアント Pod を作成してから、シェルを開き、シェルから検証コマンドを実行します。

環境変数とブートストラップ ファイルの設定

クライアント アプリケーションには、ブートストラップ構成ファイルが必要です。ブートストラップ ファイルとファイル転送用のボリュームを生成する initContainer を追加して、Kubernetes アプリケーションのデプロイ仕様を変更します。既存のコンテナを更新してファイルを探します。

アプリケーションのデプロイ仕様に、次の initContainer を追加します。

      initContainers:
      - args:
        - --output
        - "/tmp/bootstrap/td-grpc-bootstrap.json"
        image: gcr.io/trafficdirector-prod/td-grpc-bootstrap:0.16.0

        imagePullPolicy: IfNotPresent
        name: grpc-td-init
        resources:
          limits:
            cpu: 100m
            memory: 100Mi
          requests:
            cpu: 10m
            memory: 100Mi
        volumeMounts:
        - name: grpc-td-conf
          mountPath: /tmp/bootstrap/
      volumes:
      - name: grpc-td-conf
        emptyDir:
          medium: Memory

アプリケーション コンテナの env セクションを更新して、次の記述を含めます。

        env:
        - name: GRPC_XDS_BOOTSTRAP
          value: "/tmp/grpc-xds/td-grpc-bootstrap.json"
        volumeMounts:
        - name: grpc-td-conf
          mountPath: /tmp/grpc-xds/

これは、クライアントの Kubernetes 仕様の完全な例です。

cat << EOF  | kubectl apply -f -
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    run: client
  name: sleeper
spec:
  selector:
    matchLabels:
      run: client
  template:
    metadata:
      labels:
        run: client
    spec:
      containers:
      - image: openjdk:8-jdk
        imagePullPolicy: IfNotPresent
        name: sleeper
        command:
        - sleep
        - 365d
        env:
        - name: GRPC_XDS_BOOTSTRAP
          value: "/tmp/grpc-xds/td-grpc-bootstrap.json"
        resources:
          limits:
            cpu: "2"
            memory: 2000Mi
          requests:
            cpu: 300m
            memory: 1500Mi
        volumeMounts:
        - name: grpc-td-conf
          mountPath: /tmp/grpc-xds/
      initContainers:
      - args:
        - --output
        - "/tmp/bootstrap/td-grpc-bootstrap.json"
        image: gcr.io/trafficdirector-prod/td-grpc-bootstrap:0.16.0
        imagePullPolicy: IfNotPresent
        name: grpc-td-init
        resources:
          limits:
            cpu: 100m
            memory: 100Mi
          requests:
            cpu: 10m
            memory: 100Mi
        volumeMounts:
        - name: grpc-td-conf
          mountPath: /tmp/bootstrap/
      volumes:
      - name: grpc-td-conf
        emptyDir:
          medium: Memory
EOF

デプロイの準備ができたら、クライアント Pod へのシェルを開きます。

kubectl exec -it $(kubectl get pods -o custom-columns=:.metadata.name \
    --selector=run=client) -- /bin/bash

構成を確認するには、Pod シェルで適切な例を実行します。

Java

gRPC Java クライアントでサービスを確認するには:

  1. gRPC Java の最新バージョンをダウンロードし、最新のパッチを適用して xds-hello-world クライアント アプリケーションをビルドします。

     curl -L https://github.com/grpc/grpc-java/archive/v1.37.0.tar.gz | tar -xz
     cd grpc-java-1.37.0/examples/example-xds
     ../gradlew --no-daemon installDist
     

  2. クライアントの名前を "world" に指定し、サービス URI とポートとして "xds:///helloworld-gke:8000" を実行します。

    ./build/install/example-xds/bin/xds-hello-world-client "world" \
    xds:///helloworld-gke:8000
    

Go

gRPC Go クライアントでサービスを確認するには:

  1. gRPC Go の最新バージョンをダウンロードし、最新のパッチを適用して xds-hello-world クライアント アプリケーションをビルドします。

    apt-get update -y
    apt-get install -y golang git
    curl -L https://github.com/grpc/grpc-go/archive/v1.37.0.tar.gz | tar -xz
    cd grpc-go-1.37.0/examples/features/xds/client
    go get google.golang.org/grpc@v1.37.0
    go build .
    
  2. クライアントの名前を "world" に指定し、サービス URI とポートとして "xds:///helloworld-gke:8000" を実行します。

    ./client "world" xds:///helloworld-gke:8000
    

C++

gRPC C++ クライアントでサービスを確認するには:

  1. gRPC C++ の最新バージョンをダウンロードし、最新のパッチを適用して helloworld クライアントのサンプルをビルドします。

    apt-get update -y
    apt-get install -y build-essential cmake git
    git clone --recurse-submodules -b v1.37.1 https://github.com/grpc/grpc
    cd grpc
    mkdir -p cmake/build
    pushd cmake/build
    cmake ../..
    make
    make install
    popd
    mkdir -p third_party/abseil-cpp/cmake/build
    pushd third_party/abseil-cpp/cmake/build
    cmake ../..
    make
    make install
    popd
    cd examples/cpp/helloworld
    mkdir -p cmake/build
    cd cmake/build/
    cmake ../..
    make
    
  2. サービス URI とポートに「xds:///helloworld-gke:8000」を指定してクライアントを実行します。

    ./greeter_client --target=xds:///helloworld-gke:8000
    

grpcurl

grpcurl ツールは、プロキシレス gRPC クライアントとして機能することもできます。この場合、grpcurl は環境変数とブートストラップ情報を使用して Cloud Service Mesh に接続します。次に、grpc-gke-helloworld-service バックエンド サービスを通じて Cloud Service Mesh で構成された helloworld サービスについて学習します。

grpcurl ツールを使用して構成を確認するには:

  1. grpcurl ツールをダウンロードしてインストールします。

    curl -L https://github.com/fullstorydev/grpcurl/releases/download/v1.8.1/grpcurl_1.8.1_linux_x86_64.tar.gz | tar -xz
    
  2. サービス URI として xds:///helloworld-gke:8000 を指定し、サービス名とメソッドとして helloworld.Greeter/SayHello を指定して、grpcurl ツールを実行します。SayHello メソッドのパラメータは -d オプションで渡します。

    ./grpcurl --plaintext \
      -d '{"name": "world"}' \
      xds:///helloworld-gke:8000 helloworld.Greeter/SayHello
    

Python

gRPC Python クライアントでサービスを確認するには、次のコマンドを実行します。最新バージョンの gRPC を使用して最新のパッチを適用します。

apt-get update -y
apt-get install python3-pip -y
pip3 install virtualenv
curl -L https://github.com/grpc/grpc/archive/v1.37.1.tar.gz | tar -xz
cd grpc-1.37.1/examples/python/xds
virtualenv venv -p python3
source venv/bin/activate
pip install -r requirements.txt
python client.py  xds:///helloworld-gke:8000

Ruby

gRPC Ruby クライアントでサービスを確認するには、次のコマンドを実行します。最新バージョンの gRPC を使用して最新のパッチを適用します。

apt-get update -y
apt-get install -y ruby-full
gem install grpc
curl -L https://github.com/grpc/grpc/archive/v1.37.1.tar.gz | tar -xz
cd grpc-1.37.1/examples/ruby
ruby greeter_client.rb john xds:///helloworld-gke:8000

PHP

gRPC PHP クライアントでサービスを確認するには、次のコマンドを実行します。最新バージョンの gRPC を使用して最新のパッチを適用します。

apt-get update -y
apt-get install -y php7.3 php7.3-dev php-pear phpunit python-all zlib1g-dev git
pecl install grpc
curl -sS https://getcomposer.org/installer | php
mv composer.phar /usr/local/bin/composer
curl -L https://github.com/grpc/grpc/archive/v1.37.1.tar.gz | tar -xz
cd grpc-1.37.1
export CC=/usr/bin/gcc
./tools/bazel build @com_google_protobuf//:protoc
./tools/bazel build src/compiler:grpc_php_plugin
cd examples/php
composer install
../../bazel-bin/external/com_google_protobuf/protoc --proto_path=../protos \
--php_out=. --grpc_out=. \
--plugin=protoc-gen-grpc=../../bazel-bin/src/compiler/grpc_php_plugin \
../protos/helloworld.proto
php -d extension=grpc.so greeter_client.php john xds:///helloworld-gke:8000

Node.js

gRPC Node.js クライアントでサービスを確認するには、次のコマンドを実行します。最新バージョンの gRPC を使用して最新のパッチを適用します。

apt-get update -y
apt-get install -y nodejs npm
curl -L https://github.com/grpc/grpc/archive/v1.34.0.tar.gz | tar -xz
cd grpc-1.34.0/examples/node/xds
npm install
node ./greeter_client.js --target=xds:///helloworld-gke:8000

このような出力が表示されます。INSTANCE_HOST_NAME は VM インスタンスのホスト名です。

Greetings: Hello world, from INSTANCE_HOST_NAME

これにより、プロキシレス gRPC クライアントが Cloud Service Mesh に接続され、xds の名前解決機能を使用して helloworld-gke サービスのバックエンドについて学習されたことが検証されます。クライアントは、IP アドレスの把握や DNS 解決の実行なしに、サービスのバックエンドの 1 つに対してリクエストを送信しています。

次のステップ