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

このガイドでは、Google Kubernetes Engine、gRPC アプリケーション、負荷分散コンポーネントなど、Traffic Director で必要な要素を構成する方法について説明します。

このガイドに従って作業を行う前に、プロキシレス gRPC サービスで Traffic Director を設定する準備をご覧ください。

概要

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

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

Traffic Director 用の GKE クラスタの構成

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

GKE クラスタの要件

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

GKE クラスタの作成

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

コンソール

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

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

    Google Kubernetes Engine のメニューに移動

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

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

  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 サービスの構成

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

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

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

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

Traffic Director で使用する 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 名が正しいことを確認します。

コンソール

ネットワーク エンドポイント グループのリストを表示するには、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

負荷分散コンポーネントによる Traffic Director の構成

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

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

  • 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 は、Traffic Director では使用されません。これは、helloworld-gke:8000targetPort 50051 でリッスンしている NEG エンドポイントによって直接解決されるためです。通常、URL マップのホストルールのポートと Kubernetes Service 仕様の port および targetPort はすべて、便宜上同じ値に設定されますが、この例では port は Traffic Director では使用されないことを示すために異なる値を使用しています。

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
    

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

構成の確認

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

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

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

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

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

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

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

      initContainers:
      - args:
        - --output
        - "/tmp/bootstrap/td-grpc-bootstrap.json"
        image: gcr.io/trafficdirector-prod/td-grpc-bootstrap:0.11.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.11.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 は環境変数とブートストラップ情報を使用して Traffic Director に接続します。次に、grpc-gke-helloworld-service バックエンド サービスを通じて Traffic Director で構成された 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 クライアントが Traffic Director に接続され、helloworld-gke のバックエンドが xds の名前解決機能を使用して確認されていることが検証されます。クライアントは、IP アドレスの把握や DNS 解決の実行なしに、サービスのバックエンドの 1 つに対してリクエストを送信しています。

次のステップ