ESPv2 を使用した GKE 用 Endpoints のスタートガイド

このチュートリアルでは、Google Kubernetes Engine(GKE)上の Extensible Service Proxy V2(ESPv2)を使用して、単純な gRPC サービスの例をデプロイする方法について説明します。このチュートリアルでは、bookstore-grpc サンプルの Python 版を使用しています。他の言語の gRPC サンプルについては、次のステップ セクションをご覧ください。

このチュートリアルでは、事前にビルドされたサンプルコードと ESPv2 のコンテナ イメージを使用します。これらは、Container Registry に保存されています。コンテナをまだよく理解していない場合は、次の情報をご覧ください。

Cloud Endpoints の概要については、Endpoints についてEndpoints アーキテクチャをご覧ください。

目標

タスクの概要を示す次のリストを参照しながら、チュートリアルを実施してください。API にリクエストを送信するには、すべてのタスクを行う必要があります。

  1. Google Cloud プロジェクトをセットアップして、必要なソフトウェアをダウンロードします。始める前にをご覧ください。
  2. bookstore-grpc サンプルからファイルをコピーして構成します。Endpoints を構成するをご覧ください。
  3. Endpoints 構成をデプロイして Endpoints サービスを作成します。Endpoints 構成をデプロイするをご覧ください。
  4. API を提供するバックエンドを作成し、API をデプロイします。API バックエンドをデプロイするをご覧ください。
  5. サービスの外部 IP アドレスを取得します。サービスの外部 IP アドレスを取得するをご覧ください。
  6. API にリクエストを送信します。API にリクエストを送信するをご覧ください。
  7. Google Cloud アカウントへの課金が発生しないようにします。クリーンアップをご覧ください。

料金

このチュートリアルでは、課金対象である次の Google Cloud コンポーネントを使用します。

料金計算ツールを使うと、予想使用量に基づいて費用の見積もりを生成できます。新しい Google Cloud ユーザーは無料トライアルをご利用いただけます。

このチュートリアルを終了した後、作成したリソースを削除すると、それ以上の請求は発生しません。詳しくは、クリーンアップをご覧ください。

始める前に

  1. Google アカウントにログインします。

    Google アカウントをまだお持ちでない場合は、新しいアカウントを登録します。

  2. Google Cloud Console の [プロジェクト セレクタ] ページで、Google Cloud プロジェクトを選択または作成します。

    [プロジェクトの選択] ページに移動

  3. Cloud プロジェクトに対して課金が有効になっていることを確認します。プロジェクトに対して課金が有効になっていることを確認する方法を学習する

  4. 後で必要になるので、Google Cloud プロジェクト ID はメモしておいてください。
  5. Cloud SDK をインストールし、初期化します
  6. Cloud SDK を更新し、Endpoints コンポーネントをインストールします。
    gcloud components update
  7. Cloud SDK(gcloud)が Google Cloud にある対象のデータとサービスにアクセスできるよう許可されていることを確認します。
    gcloud auth login
    新しいブラウザタブが開き、アカウントの選択を要求するプロンプトが表示されます。
  8. デフォルト プロジェクトを実際のプロジェクト ID に設定します。
    gcloud config set project YOUR_PROJECT_ID

    YOUR_PROJECT_ID を実際のプロジェクト ID に置き換えます。

    他にも Google Cloud プロジェクトがあり、gcloud を使用してそのプロジェクトを管理する場合は、Cloud SDK 構成の管理をご覧ください。

  9. kubectl をインストールします。
    gcloud components install kubectl
  10. アプリケーションのデフォルト認証情報用に使用する新しいユーザー認証情報を取得します。ユーザー認証情報は kubectl を承認するために必要です。
    gcloud auth application-default login
    表示された新しいブラウザタブで、アカウントを選択します。
  11. gRPC Python クイックスタートの手順に従い、gRPC と gRPC ツールをインストールします。

Endpoints の設定

bookstore-grpc サンプルには、ローカルにコピーして構成する必要のあるファイルが含まれています。

  1. サービスの .proto ファイルから、自己完結型 protobuf 記述子ファイルを作成します。
    1. サンプル リポジトリから、bookstore.proto のコピーを保存します。このファイルは Bookstore サービスの API を定義します。
    2. 次のコマンドでディレクトリを作成します。mkdir generated_pb2
    3. protoc プロトコル バッファ コンパイラを使用して、記述子ファイル api_descriptor.pb を作成します。bookstore.proto を保存したディレクトリで次のコマンドを実行します。
      python -m grpc_tools.protoc \
          --include_imports \
          --include_source_info \
          --proto_path=. \
          --descriptor_set_out=api_descriptor.pb \
          --python_out=generated_pb2 \
          --grpc_python_out=generated_pb2 \
          bookstore.proto
      

      上記のコマンドでは、--proto_path が現在の作業ディレクトリに設定されています。gRPC ビルド環境で、.proto 入力ファイルに別のディレクトリを使用する場合は、bookstore.proto を保存したディレクトリをコンパイラが検索するように --proto_path を変更します。

  2. gRPC API 構成 YAML ファイルを作成します。
    1. api_config.yaml ファイルのコピーを保存します。このファイルは、Bookstore サービスの gRPC API 構成を定義します。
    2. api_config.yaml ファイルの MY_PROJECT_ID は、実際の Google Cloud プロジェクト ID で置き換えます。例:
      #
      # Name of the service configuration.
      #
      name: bookstore.endpoints.example-project-12345.cloud.goog
      

      このファイルの apis.name フィールド値は、.proto ファイルの完全修飾 API 名と完全に一致させる必要があります。一致しなければ、デプロイは機能しません。Bookstore サービスは、パッケージ endpoints.examples.bookstore 内の bookstore.proto で定義されています。この完全修飾 API 名は、api_config.yaml ファイルと同じように endpoints.examples.bookstore.Bookstore になります。

      apis:
        - name: endpoints.examples.bookstore.Bookstore
      

詳細については、Endpoints を構成するをご覧ください。

Endpoints 構成をデプロイする

Endpoints の構成をデプロイするには、gcloud endpoints services deploy コマンドを使用します。このコマンドを実行すると、Service Management を使用してマネージド サービスが作成されます。

  1. api_descriptor.pb ファイルと api_config.yaml ファイルがあるディレクトリにいることを確認します。
  2. gcloud コマンドライン ツールが現在使用しているデフォルト プロジェクトが、エンドポイント構成をデプロイする Google Cloud プロジェクトであることを確認します。それには、次のコマンドを使用して返されるプロジェクト ID を確認してください。これは、間違ったプロジェクト内にサービスが作成されないようにするためです。
    gcloud config list project
    

    デフォルト プロジェクトを変更する必要がある場合は、次のコマンドを実行します。

    gcloud config set project YOUR_PROJECT_ID
    
  3. 次の gcloud コマンドライン ツールを使用して、proto descriptor ファイルと構成ファイルをデプロイします。
    gcloud endpoints services deploy api_descriptor.pb api_config.yaml
    

    Service Management でサービスの作成と構成が行われるとき、情報がデバイスに出力されます。デプロイが完了すると、次のようなメッセージが表示されます。

    Service Configuration [CONFIG_ID] uploaded for service [bookstore.endpoints.example-project.cloud.goog]

    CONFIG_ID は、デプロイによって作成される一意の Endpoints サービス構成 ID です。例:

    Service Configuration [2017-02-13r0] uploaded for service [bookstore.endpoints.example-project.cloud.goog]
    

    上記の例では、2017-02-13r0 はサービス構成 ID で、bookstore.endpoints.example-project.cloud.goog はサービス名です。サービス構成 ID は、日付スタンプとそれに続くリビジョン番号で構成されます。Endpoints の構成を同じ日に再デプロイすると、サービス構成 ID のリビジョン番号が増分されます。

必要なサービスの確認

Endpoints と ESP を使用するには、少なくとも次の Google サービスの有効化が必要です。
名前 タイトル
servicemanagement.googleapis.com Service Management API
servicecontrol.googleapis.com Service Control API
endpoints.googleapis.com Google Cloud Endpoints

ほとんどの場合、gcloud endpoints services deploy コマンドによってこれらの必須サービスが有効化されます。ただし、以下の状況では、gcloud コマンドは正常に完了しますが、必須サービスが有効になりません。

  • Terraform などのサードパーティのアプリケーションを使用していて、上記のサービスを含めていない場合。

  • 上記のサービスが明示的に無効にされている既存の Google Cloud プロジェクトに Endpoints 構成をデプロイした場合。

必要なサービスが有効になっていることを確認するには、次のコマンドを実行します。

gcloud services list

必要なサービスが表示されない場合は、次のコマンドを使用してサービスを有効にします。

gcloud services enable servicemanagement.googleapis.com
gcloud services enable servicecontrol.googleapis.com
gcloud services enable endpoints.googleapis.com

Endpoints サービスも有効にします。

gcloud services enable ENDPOINTS_SERVICE_NAME

ENDPOINTS_SERVICE_NAME を確認するには、次のいずれかを行います。

  • Endpoints 構成をデプロイ後、Cloud Console の [Endpoints] ページに移動します。[サービス名] 列に、考えられる ENDPOINTS_SERVICE_NAME のリストが表示されます。

  • OpenAPI の場合、ENDPOINTS_SERVICE_NAME は OpenAPI 仕様の host フィールドで指定したものです。gRPC の場合、ENDPOINTS_SERVICE_NAME は gRPC Endpoints 構成の name フィールドで指定したものです。

gcloud コマンドの詳細については、gcloud サービスをご覧ください。

エラー メッセージが表示された場合は、Endpoints 構成のデプロイのトラブルシューティングをご覧ください。

詳しくは、Endpoints 構成をデプロイするをご覧ください。

API バックエンドをデプロイする

ここまでの手順でサービス構成を Service Management にデプロイしましたが、API バックエンドを処理するコードはまだデプロイしていません。ここでは、API バックエンドをホストする GKE クラスタを作成して API をデプロイする手順を説明します。

コンテナ クラスタの作成

コンテナ ネイティブの負荷分散を使用するには、クラスタに IP エイリアスが必要です。この例では、IP エイリアスを持つコンテナ クラスタを作成します。

gcloud container clusters create espv2-demo-cluster \
    --enable-ip-alias \
    --create-subnetwork="" \
    --network=default \
    --zone=us-central1-a

上記のコマンドにより、ゾーン us-central1-a で自動プロビジョニングされるサブネットワークを持つクラスタ espv2-demo-cluster が作成されます。

コンテナ クラスタに対する kubectl の認証

kubectl を使用してクラスタ リソースを作成し、管理するには、クラスタの認証情報を取得して kubectl で使用可能にする必要があります。この操作を行うには、次のコマンドを実行します。NAME は新しいクラスタ名、ZONE はクラスタゾーンで置き換えます。

gcloud container clusters get-credentials NAME --zone ZONE

必要な権限を確認する

この権限に関する推奨事項に従って、Google サービスと通信する ID として適切なノードサービス アカウントを選択してください。ESP と ESPv2 は Google ServiceController と Stackdriver と通信する必要があり、ESP と ESPv2 を実行するノードサービス アカウントには追加の IAM ロールが必要です。

ノードサービス アカウントが Compute Engine のデフォルトのサービス アカウントでない場合は、次の手順に従って、必要な IAM のロールを追加します。

必要な IAM ロールを追加する

ESP と ESPv2 に使用されるサービス アカウントには、次の IAM ロールが必要です。

サービス アカウントにサービス コントローラと Cloud Trace エージェントの IAM ロールを追加するには、次の手順に従います。

Console

  1. Cloud Console で、サービス アカウントが作成されたプロジェクトを選択します。
  2. [IAM] / [Iam] ページを開きます。

    [IAM] / [Iam] ページに移動

    . このページには、すべてのサービス アカウントを含む、すべての IAM メンバーが一覧表示されます。
  3. サービス アカウントを選択し、右側の [編集] ピンをクリックします。
  4. [権限の編集] パネルが開きます。
  5. [+ 別の役割を追加] をクリックします。
  6. [役割を選択] をクリックし、[サービス管理] > [サービス コントローラ] の順に選択します。
  7. [+ 別の役割を追加] をクリックします。
  8. [役割を選択] をクリックし、[Cloud Trace] > [Cloud Trace エージェント] の順に選択します。
  9. [保存] をクリックします。
  10. [IAM] ページのサービス アカウントの role 列に、サービス コントローラCloud Trace エージェントのロールが表示されます。

gcloud

  1. サービス コントローラの役割を追加します。

    gcloud projects add-iam-policy-binding PROJECT_ID \
            --member serviceAccount:SERVICE_ACCOUNT_NAME@PROJECT_ID.iam.gserviceaccount.com \
            --role roles/servicemanagement.serviceController
  2. Cloud Trace エージェントのロールを追加して、Cloud Trace を有効にします。

    gcloud projects add-iam-policy-binding PROJECT_ID \
            --member serviceAccount:SERVICE_ACCOUNT_NAME@PROJECT_ID.iam.gserviceaccount.com \
            --role roles/cloudtrace.agent

詳細については、ロールと権限についてをご覧ください。

Workload Identity

Workload Identity を使用する場合、ノードのサービス アカウントとは別のサービス アカウントを使用して Google サービスと通信できます。Pod 用の Kubernetes サービス アカウントを作成して ESP と ESPv2 を実行し、Google サービス アカウントを作成して Kubernetes サービス アカウントを Google サービス アカウントに関連付けることができます。

この手順に沿って、Kubernetes サービス アカウントを Google サービス アカウントに関連付けます。

Google サービス アカウントには、上記の必要な IAM ロールが必要です。それ以外の場合は、必要な IAM ロールの追加の手順に沿ってロールを追加します。

SSL 鍵と証明書を構成する

コンテナ ネイティブの負荷分散は、TLS で暗号化する必要がある HTTP2 LB を使用します。そのため、TLS 証明書を GKE Ingress と ESPv2 にデプロイする必要がありました。独自の証明書を使用するか、Google マネージド SSL 証明書を使用できます。この例では、自己署名証明書を使用します。

  1. openssl を使用して、自己署名証明書と鍵を作成します。「共通名(CN)」で尋ねられた FQDN bookstore.endpoints.MY_PROJECT_ID.cloud.goog と同じものを入力していることを確認します。この名前は、クライアントがサーバー証明書を確認するために使用します。

    openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
    -keyout ./server.key -out ./server.crt
  2. SSL 鍵と証明書を使用して Kubernetes secret を作成します。Secret は GKE Ingress と ESPv2 の両方に渡されるため、証明書は server.crttls.crt の 2 か所にコピーされることに注意してください。GKE Ingress は証明書パス tls.crt を探し、ESPv2 が証明書パス server.crt を探します。

    kubectl create secret generic esp-ssl \
    --from-file=server.crt=./server.crt --from-file=server.key=./server.key \
    --from-file=tls.crt=./server.crt --from-file=tls.key=./server.key

サンプル API と ESPv2 のクラスタへのデプロイ

gRPC サンプル サービスをクラスタにデプロイし、クライアントで使用可能にするには:

  1. このリポジトリgit clone して開き、grpc-bookstore.yaml デプロイ マニフェスト ファイルを編集します。
  2. SERVICE_NAME は、Ingress および ESPv2 コンテナの Endpoints サービスの名前に置き換えます。これは、api_config.yaml ファイルの name フィールドで構成した名前と同じです。
    # Copyright 2016 Google Inc.
    #
    # Licensed under the Apache License, Version 2.0 (the "License");
    # you may not use this file except in compliance with the License.
    # You may obtain a copy of the License at
    #
    #     http://www.apache.org/licenses/LICENSE-2.0
    #
    # Unless required by applicable law or agreed to in writing, software
    # distributed under the License is distributed on an "AS IS" BASIS,
    # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    # See the License for the specific language governing permissions and
    # limitations under the License
    
    # Use this file to deploy the container for the grpc-bookstore sample
    # and the container for the Extensible Service Proxy (ESP) to
    # Google Kubernetes Engine (GKE).
    
    apiVersion: networking.k8s.io/v1beta1
    kind: Ingress
    metadata:
      name: esp-grpc-bookstore
      annotations:
        kubernetes.io/ingress.class: "gce"
        kubernetes.io/ingress.allow-http: "false"
    spec:
      tls:
      - hosts:
        - SERVICE_NAME
        secretName: esp-ssl
      backend:
        serviceName: esp-grpc-bookstore
        servicePort: 443
    ---
    apiVersion: cloud.google.com/v1
    kind: BackendConfig
    metadata:
      name: esp-grpc-bookstore
    spec:
      healthCheck:
        type: HTTP2
        requestPath: /healthz
        port: 9000
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: esp-grpc-bookstore
      annotations:
        service.alpha.kubernetes.io/app-protocols: '{"esp-grpc-bookstore":"HTTP2"}'
        cloud.google.com/neg: '{"ingress": true, "exposed_ports": {"443":{}}}'
        cloud.google.com/backend-config: '{"default": "esp-grpc-bookstore"}'
    spec:
      ports:
      # Port that accepts gRPC and JSON/HTTP2 requests over TLS.
      - port: 443
        targetPort: 9000
        protocol: TCP
        name: esp-grpc-bookstore
      selector:
        app: esp-grpc-bookstore
      type: ClusterIP
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: esp-grpc-bookstore
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: esp-grpc-bookstore
      template:
        metadata:
          labels:
            app: esp-grpc-bookstore
        spec:
          volumes:
          - name: esp-ssl
            secret:
              secretName: esp-ssl
          containers:
          - name: esp
            image: gcr.io/endpoints-release/endpoints-runtime:2
            args: [
              "--listener_port=9000",
              "--service=SERVICE_NAME",
              "--rollout_strategy=managed",
              "--backend=grpc://127.0.0.1:8000",
              "--healthz=/healthz",
              "--ssl_server_cert_path=/etc/esp/ssl",
            ]
            ports:
              - containerPort: 9000
            volumeMounts:
            - mountPath: /etc/esp/ssl
              name:  esp-ssl
              readOnly: true
          - name: bookstore
            image: gcr.io/endpointsv2/python-grpc-bookstore-server:1
            ports:
              - containerPort: 8000
    

    --rollout_strategy=managed オプションを指定すると、デプロイ済みの最新のサービス構成を使用するように ESPv2 が構成されます。このオプションを指定すると、新しいサービス構成をデプロイしてから 1 分以内に ESPv2 が変更を検出し、自動的に使用します。ESPv2 が特定の構成 ID でなく、このオプションを使用するようにしてください。ESPv2 引数の詳細については、ESPv2 スタートアップ オプションをご覧ください。

    次に例を示します。

        spec:
          containers:
          - name: esp
            image: gcr.io/endpoints-release/endpoints-runtime:2
            args: [
              "--listener_port=9000",
              "--service=bookstore.endpoints.example-project-12345.cloud.goog",
              "--rollout_strategy=managed",
              "--backend=grpc://127.0.0.1:8000"
            ]
    
  3. サービスを起動します。
    kubectl create -f grpc-bookstore.yaml
    

エラー メッセージが表示された場合は、GKE での Endpoints のトラブルシューティングをご覧ください。

サービスの外部 IP アドレスを取得する

サンプル API にリクエストを送信するには、サービスの外部 IP アドレスが必要です。コンテナでサービスを開始してから外部 IP アドレスを確認できるまで数分かかる場合があります。

  1. 外部 IP アドレスを表示します。

    kubectl get ingress

  2. EXTERNAL-IP の値をメモしておき、SERVER_IP 環境変数に保存します。この外部 IP アドレスは、リクエストをサンプル API に送信するために使用されます。

    export SERVER_IP=YOUR_EXTERNAL_IP
    

API にリクエストを送信する

サンプル API にリクエストを送信するには、Python で作成された gRPC クライアントを使用できます。

  1. gRPC クライアント コードがホストされる git リポジトリのクローンを作成します。

    git clone https://github.com/GoogleCloudPlatform/python-docs-samples.git
       

  2. 作業ディレクトリに移動します。

    cd python-docs-samples/endpoints/bookstore-grpc/
      

  3. 依存関係をインストールします。

    pip install virtualenv
    virtualenv env
    source env/bin/activate
    python -m pip install -r requirements.txt
    

  4. 自己署名証明書のルート CA を作成する

    openssl x509 -in server.crt -out client.pem -outform PEM
      

  5. サンプル API にリクエストを送信します。

    python bookstore_client.py --host SERVER_IP --port 443 \
    --servername bookstore.endpoints.MY_PROJECT_ID.cloud.goog --use_tls true --ca_path=client.pem
    

正常なレスポンスが返されない場合は、レスポンス エラーのトラブルシューティングをご覧ください。

これで Endpoints の API のデプロイとテストが完了しました。

クリーンアップ

このチュートリアルで使用したリソースについて、Google Cloud アカウントに課金されないようにするには、リソースを含むプロジェクトを削除するか、プロジェクトを維持して個々のリソースを削除します。

  1. API を削除します。

    gcloud endpoints services delete SERVICE_NAME
    

    SERVICE_NAME は、API の名前に置き換えます。

  2. GKE クラスタを削除します。

    gcloud container clusters delete NAME --zone ZONE
    

次のステップ