Extensible Service Proxy をローカルまたは別のプラットフォームで実行する

このページでは、ローカルマシン、別のクラウド プロバイダ(Amazon Web Services(AWS)など)、または Google Cloud 上にはない Kubernetes クラスタで Extensible Service Proxy(ESP)のインスタンスを構成して実行する方法を説明します。

ESP は、Linux や macOS のパソコン上、または仮想マシン(VM)上で実行可能です。Microsoft Windows はサポートされていません。アプリケーションと ESP を同じホストにデプロイすることも、異なるホストにデプロイすることもできます。ESP のローカル インスタンスをホストすると、次のことが可能になります。

  • 本番環境プラットフォームにデプロイする前に ESP を試す。
  • 構成されたセキュリティ設定が適切に動作することや、指標やログが [エンドポイント] の [サービス] ページに想定どおりに表示されることを検証する。

前提条件

前提として、このページでは次の点を想定しています。

  • ESP コンテナをローカルにデプロイする場合、または VM にデプロイする場合は、Docker がインストール済みである。詳しくは、Docker のインストールをご覧ください。

  • API をローカルにデプロイ済みであるか、ESP を実行するホストに到達可能なホストにデプロイ済みである。

  • API のマネージド サービスを作成するように Cloud Endpoints を構成済みで、その構成をデプロイ済みである。

ESP でテストするための API が必要な場合は、オプション: サンプル API の使用のサンプルコードを構成してデプロイできます。API をすでに構成してデプロイしている場合は、サービス アカウントの作成に進んでください。

オプション: サンプル API の使用

このセクションでは、Python バージョンの Endpoints 用 getting-started サンプルをローカルで構成して、デプロイする方法を説明します。このセクションの手順は、ESP でテストするための API がない場合にのみ行ってください。

Cloud Endpoints の getting-started サンプルは他の言語でも用意されています。目的の言語の getting-started サンプルがある GitHub の場所については、サンプルページをご覧ください。サンプルの README.md ファイルに記載されているローカル実行の手順を行った後、このセクションの手順に沿って Endpoints を構成してデプロイします。

必要なソフトウェアを入手する

Python 開発環境をまだ設定していない場合は、Python 開発環境の設定をご覧ください。次のものがインストールされていることを確認します。

サンプルコードを取得する

  1. ローカルマシンにサンプルアプリのリポジトリのクローンを作成します。

    git clone https://github.com/GoogleCloudPlatform/python-docs-samples
    
  2. サンプルコードが入っているディレクトリに移動します。

    cd python-docs-samples/endpoints/getting-started
    

エンドポイントを構成する

  1. サンプルコードのディレクトリで、openapi.yaml 構成ファイルを開きます。

    swagger: "2.0"
    info:
      description: "A simple Google Cloud Endpoints API example."
      title: "Endpoints Example"
      version: "1.0.0"
    host: "echo-api.endpoints.YOUR-PROJECT-ID.cloud.goog"
  2. host フィールドで、YOUR-PROJECT-ID を独自の Google Cloud プロジェクト ID に置き換えます。

  3. openapi.yaml ファイルを保存します。

Endpoints 構成をデプロイする

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

  1. gcloud CLI を更新します。

    gcloud components update
  2. gcloud CLI(gcloud)が、Google Cloud にある対象のデータとサービスにアクセスできるよう許可されていることを確認します。

    gcloud auth login

    表示された新しいブラウザタブで、アカウントを選択します。

  3. デフォルト プロジェクトを実際のプロジェクト ID に設定します。

    gcloud config set project YOUR-PROJECT-ID
    

    YOUR-PROJECT-IDopenapi.yaml ファイルで指定した Google Cloud プロジェクトのプロジェクト ID で置き換えます。

  4. 構成をデプロイします。

    gcloud endpoints services deploy openapi.yaml

Service Management は、openapi.yaml ファイルの host フィールドで指定されたテキストを使用して、echo-api.endpoints.YOUR-PROJECT-ID.cloud.goog の名前で新しい Endpoints サービスを作成し(存在しない場合)、OpenAPI 構成ファイルに基づいてサービスを構成します。

Service Management によってサービスの作成と構成が行われるとき、その情報がターミナルに出力されます。openapi.yaml ファイル内のパスが API キーを要求していないことを示す警告は無視して問題ありません。正常に完了すると、次のようにサービス構成 ID とサービス名が括弧の中に表示されます。

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

上の例では、2017-02-13r0 がサービス構成 ID で、echo-api.endpoints.example-project-12345.cloud.goog がサービス名です。

ローカル サーバーを起動する

  1. virtualenv を作成して有効化し、アプリケーションの依存関係をインストールします。

    virtualenv env
    source env/bin/activate
    pip install -r requirements.txt
  2. サーバーを開始します。

    python main.py
    
  3. 別のターミナル ウィンドウを開き、curl を使用してリクエストを送信します。

    curl --request POST \
      --header "content-type:application/json" \
      --data '{"message":"hello world"}' \
      http://localhost:8080/echo
    

    API によって送信メッセージがエコーバックされ、次のようなレスポンスが返されます。

    {
    "message": "hello world"
    }

サービス アカウントの作成

API を管理するには、ESP と ESPv2 のどちらにも Service Infrastructure のサービスが必要です。これらのサービスを呼び出すには、ESP と ESPv2 ではアクセス トークンを使用する必要があります。GKE や Compute Engine などの Google Cloud 環境に ESP または ESPv2 をデプロイする場合、ESP と ESPv2 は Google Cloud メタデータ サービスを通じてアクセス トークンを取得します。

ローカル デスクトップ、オンプレミスの Kubernetes クラスタ、別のクラウド プロバイダなど、Google Cloud 以外の環境に ESP または ESPv2 をデプロイする場合は、秘密鍵を含むサービス アカウントの JSON ファイルを指定する必要があります。ESP と ESPv2 は、サービス アカウントを使用してアクセス トークンを生成し、API の管理に必要なサービスを呼び出します。

Google Cloud コンソールまたは Google Cloud CLI を使用して、サービス アカウントと秘密鍵ファイルを作成できます。

Console

  1. Google Cloud コンソールで [サービス アカウント] ページを開きます。

    [サービス アカウント] ページに移動

  2. [プロジェクトの選択] をクリックします。
  3. API が作成されたプロジェクトを選択し、[開く] をクリックします。
  4. [+ サービス アカウントを作成] をクリックします。
  5. [サービス アカウント名] 項目に、サービス アカウントの名前を入力します。
  6. [作成] をクリックします。
  7. [続行] をクリックします。
  8. [完了] をクリックします。
  9. 新しく作成したサービス アカウントのメールアドレスをクリックします。
  10. [キー] をクリックします。
  11. [鍵を追加]、[新しい鍵を作成] の順にクリックします。
  12. [CREATE] をクリックします。JSON キーファイルがパソコンにダウンロードされます。

    鍵ファイルは、サービス アカウントとしての認証で使用できるため、安全な場所に保管してください。このファイルは任意の場所に移動できます。名前の変更も可能です。

  13. [閉じる] をクリックします。

gcloud

  1. 次のコマンドを入力して、Google Cloud プロジェクトのプロジェクト ID を表示します。

    gcloud projects list
  2. 次のコマンドの PROJECT_ID の部分を API が含まれているプロジェクトに置き換えて、デフォルトのプロジェクトに設定します。

    gcloud config set project PROJECT_ID
  3. Google Cloud CLI(gcloud)が、Google Cloud にある対象のデータとサービスにアクセスできるよう許可されていることを確認します。

    gcloud auth login

    アカウントが複数ある場合は、API がある Google Cloud プロジェクトのアカウントを選択してください。gcloud auth list を実行すると、選択したアカウントがプロジェクトの有効なアカウントとして表示されます。

  4. サービス アカウントを作成するには、次のコマンドを実行します。このとき、SERVICE_ACCOUNT_NAMEMy Service Account は、使用する名前と表示名に置き換えます。

    gcloud iam service-accounts create SERVICE_ACCOUNT_NAME \
       --display-name "My Service Account"

    このコマンドは、サービス アカウントのメールアドレスを次の形式で割り当てます。

    SERVICE_ACCOUNT_NAME@PROJECT_ID.iam.gserviceaccount.com

    このメールアドレスは、後で実行するコマンドで必要になります。

  5. サービス アカウントのキーファイルを作成します。

    gcloud iam service-accounts keys create ~/service-account-creds.json \
       --iam-account SERVICE_ACCOUNT_NAME@PROJECT_ID.iam.gserviceaccount.com

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

このセクションでは、ESP と ESPv2 で使用される IAM リソースと、これらのリソースにアクセスするために接続されたサービス アカウントに必要な IAM ロールについて説明します。

エンドポイント サービスの構成

ESP と ESPv2 は、エンドポイント サービス構成を使用する Service Control を呼び出します。エンドポイント サービスの構成は IAM リソースであり、ESP と ESPv2 にはサービス コントローラ ロールが必要です。

IAM ロールは、プロジェクトではなく、エンドポイント サービスの構成に対するものです。1 つのプロジェクトには、複数のエンドポイント サービス構成が存在する場合があります。

次の gcloud コマンドを使用して、エンドポイント サービス構成の接続されたサービス アカウントにロールを追加します。

gcloud endpoints services add-iam-policy-binding SERVICE_NAME \
  --member serviceAccount:SERVICE_ACCOUNT_NAME@DEPLOY_PROJECT_ID.iam.gserviceaccount.com \
  --role roles/servicemanagement.serviceController

ここで、
* SERVICE_NAME は、エンドポイント サービス名です。
* SERVICE_ACCOUNT_NAME@DEPLOY_PROJECT_ID.iam.gserviceaccount.com は、接続されたサービス アカウントです。

Cloud Trace

ESP と ESPv2 は Cloud Trace サービスを呼び出して、Trace をプロジェクトにエクスポートします。このプロジェクトはトレース プロジェクトと呼ばれます。ESP では、トレース プロジェクトと、エンドポイント サービス構成を有するプロジェクトは同じです。ESPv2 では、トレース プロジェクトはフラグ --tracing_project_id で指定できます。デフォルトはデプロイ プロジェクトです。

ESP と ESPv2 では、Cloud Trace を有効にするために、Cloud Trace エージェント ロールが必要です。

次の gcloud コマンドを使用して、接続されたサービス アカウントにロールを追加します。

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

ここで、
* TRACING_PROJECT_ID は、トレース プロジェクト ID です。
* SERVICE_ACCOUNT_NAME@DEPLOY_PROJECT_ID.iam.gserviceaccount.comは、接続されたサービス アカウントです。詳細については、ロールと権限についてをご覧ください。

コマンドの詳細については、gcloud iam service-accounts をご覧ください。

コンテナでの ESP の実行

このセクションでは、ESP コンテナをデプロイする方法を説明します。使用する手順は、ESP コンテナをデプロイする場所によって異なります。

以下の例で使用している ESP オプション --http_port は、gRPC サービスに HTTP/JSON のコード変換が構成されている場合にのみ機能します。詳細については、HTTP/JSON の gRPC へのコード変換をご覧ください。

ローカルまたは別のプラットフォームの Docker コンテナで ESP を実行する

  1. サービス アカウントの秘密鍵が格納されている JSON ファイルの名前を service-account-creds.json に変更します。そのファイルが別のディレクトリにダウンロードされている場合は、$HOME/Downloads/ にコピーします。これにより、フルパス名が、下記の docker run コマンドの --service_account_key の値と一致します。

  2. 下記の docker run コマンドで、YOUR_SERVICE_NAME を、ご使用のサービス名に置き換えます。

Linux

sudo docker run \
    --detach \
    --name="esp" \
    --net="host" \
    --volume=$HOME/Downloads:/esp \
    --publish=8082 \
    gcr.io/endpoints-release/endpoints-runtime:1 \
    --service=YOUR_SERVICE_NAME \
    --rollout_strategy=managed \
    --http_port=8082 \
    --http2_port=8083 \
    --backend=grpc://localhost:8080 \
    --service_account_key=/esp/service-account-creds.json
  

macOS

Docker の --net="host" オプションは、macOS では機能しません。代わりに、ホストからコンテナへの明示的なポート マッピングを行う必要があり、それを行うには、--net="host"--publish 8082:8082 に置き換えます。また、localhost を、macOS 専用の特別な DNS 名の docker.for.mac.localhost に置き換える必要があります。詳しくは、Docker ドキュメントのユースケースと回避策をご覧ください。

sudo docker run \
  --detach \
  --name="esp" \
  --publish=8082:8082 \
  --volume=$HOME/Downloads:/esp \
  gcr.io/endpoints-release/endpoints-runtime:1 \
  --service=YOUR_SERVICE_NAME \
  --rollout_strategy=managed \
  --http_port=8082 \
  --http2_port=8083 \
  --backend=grpc://docker.for.mac.localhost:8080 \
  --service_account_key=/esp/service-account-creds.json
  

別のプラットフォーム

sudo docker run \
  --detach \
  --name="esp" \
  --net="host" \
  --volume=$HOME/Downloads:/esp \
  --publish=8082 \
  gcr.io/endpoints-release/endpoints-runtime:1 \
  --service=YOUR_SERVICE_NAME \
  --rollout_strategy=managed \
  --http_port=8082 \
  --http2_port=8083 \
  --backend=grpc://IP_Address:PORT \
  --service_account_key=/esp/service-account-creds.json
  

次の表に、上記のコマンドで使用している Docker のオプションを示します。この例で使用している ESP オプションについては、ESP 起動オプションをご覧ください。

オプション 説明
--detach この Docker オプションは、コンテナを接続解除モードで起動します。そのため、コンテナはバックグラウンドで実行されます。
--name="esp" この Docker オプションは、扱いやすい名前をコンテナに対して指定します。たとえば、コンテナからログを表示するには、docker logs esp のように実行できます。
--net="host" この Docker オプションは、Docker コンテナがホストマシンと同じネットワーク構成を使用することを指定します。これにより、Docker コンテナがホストマシン上の localhost を呼び出せるようにします。このオプションは、macOS 上で ESP をローカル実行する場合には機能しません。
--publish=8082:8082 macOS で ESP をローカル実行する場合は、この Docker オプションを --net="host" の代わりに使用して、ホストからコンテナへの明示的なポート マッピングを行います。
--volume=
$HOME/Downloads:/esp
この Docker オプションは、ローカルの $HOME/Downloads ディレクトリをコンテナ内の /esp ディレクトリにマッピングします。このマッピングは --service_account_key ESP オプションで使用されます。

Kubernetes クラスタのコンテナで ESP を実行する

このセクションでは、Google Cloud 上にない Kubernetes クラスタに ESP をデプロイする方法を説明します。

API を Endpoints で管理するには、API コンテナと同じ Kubernetes ポッドに ESP コンテナをデプロイします。API と ESP を実行するポッドのセットは、Kubernetes Service 内でラベルセレクタ(たとえば app: my-api)を使用してグループ化されます。この Kubernetes サービスで指定されたアクセス ポリシーに基づいて、クライアント リクエストがプロキシポートに負荷分散されます。

  1. サービス アカウントの秘密鍵が格納されている JSON ファイルの名前を service-account-creds.json に変更します。そのファイルが別のディレクトリにダウンロードされている場合は、$HOME/Downloads/ にコピーします。このようにすることで、フルパス名が次の手順で使用するコマンドと一致します。

  2. 次のコマンドを実行して Kubernetes Secret を作成し、そのシークレットを Kubernetes ボリュームとしてマウントします。

    kubectl create secret generic service-account-creds \
      --from-file=$HOME/Downloads/service-account-creds.json
    

    成功すると、「secret "service-account-creds" created」のメッセージが表示されます。

  3. Kubernetes 構成ファイルに次のコードを追加します。このとき、YOUR_APP_NAME は API の名前に置き換え、YOUR_SERVICE_NAMEサービス名に置き換えます。

    spec:
    replicas: 1
    template:
      metadata:
        labels:
          app: "YOUR_APP_NAME"
      spec:
        volumes:
          - name: service-account-creds
            secret:
              secretName: service-account-creds
              containers:
          - name: esp
            image: gcr.io/endpoints-release/endpoints-runtime:1
            args: [
              "--http_port=8082",
              "--http2_port=8083",
              "--backend=grpc://127.0.0.1:8081",
              "--service=YOUR_SERVICE_NAME",
              "--rollout_strategy=managed",
              "--service_account_key=/etc/nginx/creds/service-account-creds.json"
            ]
            ports:
              - containerPort: 8080
            volumeMounts:
              - mountPath: /etc/nginx/creds
                name: service-account-creds
                readOnly: true
    

    この例で使用している ESP オプションについては、ESP 起動オプションをご覧ください。

  4. ESP を Kubernetes にデプロイします。YOUR_CONFIGURATION_FILE は、Kubernetes 構成ファイルの名前で置き換えます。

    kubectl apply -f YOUR_CONFIGURATION_FILE

リクエストを送信する

サービス アカウント ファイルが正しいことやポートが正しくマッピングされていることを確認するには、API にリクエストを送信し、リクエストが ESP 経由で送信されていることを確認します。次のコマンドを実行して、ESP ログを確認できます。

sudo docker logs esp

次の例では、サンプル API にリクエストを送信します。サンプル API を使用していない場合は、同様のテストを実行することをおすすめします。

ポート 8082 でリクエストを受信するように ESP コンテナが構成されています。http://localhost:8080 でサーバーに直接リクエストを送信すると、リクエストは ESP をバイパスします。次に例を示します。

curl --request POST \
  --header "content-type:application/json" \
  --data '{"message":"hello world"}' \
  http://localhost:8080/echo

レスポンス:

  {
    "message": "hello world"
  }

ESP を通過するリクエストを http://localhost:8082 に送信し、API キーを送信しない場合、このリクエストは、ESP から拒否されます。次に例を示します。

curl --request POST \
  --header "content-type:application/json" \
  --data '{"message":"hello world"}' \
  http://localhost:8082/echo

レスポンス:

  {
   "code": 16,
   "message": "Method doesn't allow unregistered callers (callers without
    established identity). Please use API Key or other form of API consumer
    identity to call this API.",
   "details": [
    {
     "@type": "type.googleapis.com/google.rpc.DebugInfo",
     "stackEntries": [],
     "detail": "service_control"
    }
   ]
  }

API キーを使用して API をテストするには:

  1. API の認証情報ページで API キーを作成します。

    [ドメインの確認] ページに移動

  2. [認証情報を作成] をクリックし、[API キー] を選択します。

  3. キーをコピーし、以下の環境変数ステートメントに貼り付けます。

    export KEY=AIza...
    
  4. キーを使用してリクエストを送信します。

    curl --request POST \
      --header "content-type:application/json" \
      --data '{"message":"hello world"}' \
      http://localhost:8082/echo?key=$KEY

    成功すると、次のレスポンスが表示されます。

    {
      "message": "hello world"
    }

クリーンアップ

docker ツールを使用して、esp Docker コンテナをシャットダウンして削除します。

    sudo docker stop esp
    sudo docker rm esp
デプロイしたサービス構成をクリーンアップする方法については、API と API インスタンスを削除するをご覧ください。

次のステップ