透過 ESP 開始使用 Kubernetes 適用的 Endpoints

本教學課程說明如何在非執行於Google Cloud的 Kubernetes 叢集上,部署簡單的範例 gRPC 服務和可擴充服務 Proxy (ESP)。本教學課程使用 Python 版本的 bookstore-grpc 範例。如需其他語言的 gRPC 範例,請參閱「後續步驟」一節。

本教學課程使用範例程式碼與 ESP 預先建構的容器映像檔,這些映像檔儲存在 Artifact Registry 中。 如果您對於容器不熟悉,請參閱以下詳細資訊:

如需 Cloud Endpoints 的總覽,請參閱關於 EndpointsEndpoints 架構

設定 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 輸入檔案使用不同的目錄,請變更 --proto_path 以讓編譯器能夠搜尋您儲存 bookstore.proto 的目錄。

  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 名稱為 endpoints.examples.bookstore.Bookstore,就像 api_config.yaml 檔案中的名稱一樣。

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

詳情請參閱設定 Endpoints 一文。

部署 Endpoints 設定

如要部署 Endpoints 設定,請使用 gcloud endpoints services deploy 指令。這個指令使用了服務基礎架構,也就是 Google 的基礎服務平台。Endpoints 和其他服務都是使用這個基礎架構來建立和管理 API 及服務。

  1. 確認您所在的目錄有 api_descriptor.pbapi_config.yaml 檔案。
  2. 確認 gcloud 指令列工具目前使用的預設專案,就是您要部署 Endpoints 設定的 Google Cloud 專案。請利用下列指令傳回的專案 ID 進行驗證,以確保系統沒有將服務建立在錯誤的專案中。
    gcloud config list project
    

    如要變更預設的專案,請執行下列指令:

    gcloud config set project YOUR_PROJECT_ID
    
  3. 使用 Google Cloud CLI 部署 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

在大多數情況下,gcloud endpoints services deploy 指令會啟用這些必要服務。不過在以下情況中,即便您成功執行 gcloud 指令,還是無法啟用必要服務:

  • 您使用 Terraform 之類的第三方應用程式,而其中未包含這些服務。

  • 您已將 Endpoints 設定部署至現有Google Cloud 專案,但在專案中已明確停用這些服務。

請使用下列指令確認必要服務已啟用:

gcloud services list

如果必要的服務並未列出,請執行下列指令加以啟用:

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

同時啟用 Endpoints 服務:

gcloud services enable ENDPOINTS_SERVICE_NAME

如要判斷 ENDPOINTS_SERVICE_NAME,您可以採取下列任一做法:

  • 部署 Endpoints 設定後,請前往 Cloud 控制台的「Endpoints」頁面。「服務名稱」欄下方會顯示可能的 ENDPOINTS_SERVICE_NAME 清單。

  • 如果是 OpenAPI,ENDPOINTS_SERVICE_NAME 是您在 OpenAPI 規格的 host 欄位中指定的內容。如果是 gRPC,ENDPOINTS_SERVICE_NAME 是您在 gRPC Endpoints 設定的 name 欄位中指定的內容。

如要進一步瞭解 gcloud 指令,請參閱 gcloud 服務

如果您收到錯誤訊息,請參閱排解 Endpoints 設定部署問題一文。

詳情請參閱部署 Endpoints 設定一文。

為服務建立憑證

為了妥善管理您的 API,ESP 和 ESPv2 都需要使用服務基礎架構中的服務。 ESP 和 ESPv2 必須使用存取憑證才能呼叫這些服務。 當您將 ESP 或 ESPv2 部署至 GKE 或 Compute Engine 等 Google Cloud 環境時,ESP 和 ESPv2 會透過 Google Cloud 中繼資料服務為您取得存取權杖。

如果您要將 ESP 或 ESPv2 部署至非Google Cloud 環境 (像是您的本機電腦、內部部署的 Kubernetes 叢集,或是其他雲端服務平台),則必須提供含有私密金鑰的服務帳戶 JSON 檔案。ESP 和 ESPv2 會使用該服務帳戶產生存取權杖,以呼叫管理 API 所需的服務。

您可以使用 Google Cloud 控制台或 Google Cloud CLI 建立服務帳戶和私密金鑰檔案:

控制台

  1. 在 Google Cloud 控制台中,開啟「Service Accounts」(服務帳戶) 頁面。

    前往「Service Accounts」(服務帳戶) 頁面

  2. 按一下 [Select a project] (選取專案)。
  3. 選取您已建立 API 的專案,並按一下 [Open] (開啟)。
  4. 按一下 [+ Create Service Account] (+ 建立服務帳戶)
  5. 在「Service account name」(服務帳戶名稱) 欄位中,輸入服務帳戶的名稱。
  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 角色位於端點服務設定中,而非專案。 一個專案可能有多個端點服務設定。

使用下列 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 服務,將追蹤記錄匯出至專案。這個專案稱為追蹤專案。在 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

部署 API 後端

到目前為止,您已將服務設定部署至 Service Management,但尚未部署為 API 後端提供服務的程式碼。本節會逐步引導您針對 API 範例和 ESP,將預先建置的容器部署至 Kubernetes。

為 ESP 提供服務憑證

在容器內部執行的 ESP 必須能存取儲存在本機 service-account-creds.json 檔案中的憑證。如要讓 ESP 存取憑證,請建立 Kubernetes 密鑰,並將 Kubernetes 密鑰掛接為 Kubernetes 磁碟區

如何建立 Kubernetes 密鑰並掛接磁碟區:

  1. 如果您使用 Google Cloud 主控台建立服務帳戶,請將 JSON 檔案重新命名為 service-account-creds.json。將檔案移至 api_descriptor.pbapi_config.yaml 檔案所在的相同目錄中。

  2. 使用服務帳戶憑證建立 Kubernetes 密鑰

     kubectl create secret generic service-account-creds
          --from-file=service-account-creds.json

    成功後,您會看見此訊息:secret "service-account-creds" created

您用來將 API 和 ESP 部署至 Kubernetes 的部署資訊清單檔案,已包含密鑰磁碟區,如下列檔案的兩個區段所示:

volumes:
  - name: service-account-creds
    secret:
      secretName: service-account-creds
volumeMounts:
  - mountPath: /etc/nginx/creds
    name: service-account-creds
    readOnly: true

設定服務名稱並啟動服務

ESP 必須知道您的服務名稱,才能使用 gcloud endpoints services deploy指令找出先前部署的設定。

如何設定服務名稱及啟動服務:

  1. 將部署資訊清單檔案 k8s-grpc-bookstore.yaml 的複本儲存至 service-account-creds.json 所在的相同目錄中。

  2. 開啟 k8s-grpc-bookstore.yaml,並將 SERVICE_NAME 替換為 Endpoints 服務名稱。這是您在 api_config.yaml 檔案的 name 欄位中設定的名稱相同。

    containers:
      - name: esp
        image: gcr.io/endpoints-release/endpoints-runtime:1
        args: [
          "--http2_port=9000",
          "--service=SERVICE_NAME",
          "--rollout_strategy=managed",
          "--backend=grpc://127.0.0.1:8000",
          "--service_account_key=/etc/nginx/creds/service-account-creds.json"
        ]

    --rollout_strategy=managed 選項可將 ESP 設為使用最新部署的服務設定。指定此選項時,在您部署新服務設定後最多 5 分鐘內,ESP 會偵測到變更並自動開始使用新設定。建議您指定此選項而非讓 ESP 使用特定的設定 ID。 如要進一步瞭解 ESP 引數,請參閱 ESP 啟動選項一文。

  3. 啟動服務以在 Kubernetes 上部署服務:

    kubectl create -f k8s-grpc-bookstore.yaml

    如果您看到類似以下內容的錯誤訊息:

    The connection to the server localhost:8080 was refused - did you specify the right host or port?

    這表示您未正確設定 kubectl,詳情請參閱「設定 kubectl」一節。

取得服務的外部 IP 位址

您需要取得服務的外部 IP 位址,才能向範例 API 傳送要求。當您在容器中啟動服務後,系統可能需要幾分鐘的時間才能備妥外部 IP 位址。

  1. 查看外部 IP 位址:

    kubectl get service

  2. 記下 EXTERNAL-IP 的值,然後將它儲存在 SERVER_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. 傳送要求至範例 API:

    python bookstore_client.py --host SERVER_IP --port 80
    

如果您未取得成功的回應,請參閱排解回應錯誤一文。

您已在 Endpoints 中部署並測試了 API!