使用 Google Kubernetes Engine 進行分散式工作負載測試

Last reviewed 2024-08-13 UTC

本文件說明如何使用 Google Kubernetes Engine (GKE) 部署分散式負載測試架構,該架構會使用多個容器為簡易的 REST 型 API 建立流量。本文件會對部署至 App Engine 的網路應用程式進行負載測試,該應用程式會公開 REST 樣式的端點,以便回應傳入的 HTTP POST 要求。

您可以使用相同的模式,針對各種情境和應用程式建立工作負載測試架構,例如訊息系統、資料串流管理系統和資料庫系統。

目標

  • 定義環境變數來控制部署設定。
  • 建立 GKE 叢集。
  • 執行工作負載測試。
  • 視需要擴大使用者人數或將模式擴展至其他用途。

費用

在本文件中,您會使用 Google Cloud的下列計費元件:

  • App Engine
  • Artifact Registry
  • Cloud Build
  • Cloud Storage
  • Google Kubernetes Engine

您可以使用 Pricing Calculator 根據預測用量產生預估費用。 新 Google Cloud 使用者可能符合申請免費試用的資格。

事前準備

  1. Sign in to your Google Cloud account. If you're new to Google Cloud, create an account to evaluate how our products perform in real-world scenarios. New customers also get $300 in free credits to run, test, and deploy workloads.
  2. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Go to project selector

  3. Make sure that billing is enabled for your Google Cloud project.

  4. Enable the App Engine, Artifact Registry, Cloud Build, Compute Engine, Resource Manager, Google Kubernetes Engine, and Identity and Access Management APIs.

    Enable the APIs

  5. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Go to project selector

  6. Make sure that billing is enabled for your Google Cloud project.

  7. Enable the App Engine, Artifact Registry, Cloud Build, Compute Engine, Resource Manager, Google Kubernetes Engine, and Identity and Access Management APIs.

    Enable the APIs

  8. 完成本文件所述工作後,您可以刪除已建立的資源,避免繼續計費。詳情請參閱「清除所用資源」。

  9. Grant roles to your user account. Run the following command once for each of the following IAM roles: roles/serviceusage.serviceUsageAdmin, roles/container.admin, roles/appengine.appAdmin, roles/appengine.appCreator, roles/artifactregistry.admin, roles/resourcemanager.projectIamAdmin, roles/compute.instanceAdmin.v1, roles/iam.serviceAccountUser, roles/cloudbuild.builds.builder, roles/iam.serviceAccountAdmin

    gcloud projects add-iam-policy-binding PROJECT_ID --member="user:USER_IDENTIFIER" --role=ROLE
    • Replace PROJECT_ID with your project ID.
    • Replace USER_IDENTIFIER with the identifier for your user account. For example, user:myemail@example.com.

    • Replace ROLE with each individual role.
  10. 工作負載範例

    下圖為要求從用戶端傳送到應用程式的工作範例。

    從用戶端傳送到應用程式的要求。

    如要對這類的互動建立模型,您可以使用 Locust (以 Python 為基礎的分散式工作負載測試工具,可將要求分配至多個目標路徑)。舉例來說,Locust 能夠將要求分配給 /login/metrics 目標路徑。在 Locust 中,工作負載模型是以一組工作形式呈現。

    架構

    這個架構包含兩個主要元件:

    • Locust Docker 容器映像檔。
    • 容器自動化調度管理與管理機制。

    Locust Docker 容器映像檔包含 Locust 軟體。Dockerfile (複製本文件隨附的 GitHub 存放區時即可取得) 使用基本 Python 映像檔,並包含可啟動 Locust 服務及執行工作的指令碼。如要估算實際用戶端,每個 Locust 工作都需要加權計算。舉例來說,註冊是每千個用戶端要求總數才發生一次。

    GKE 提供容器自動化調度管理與管理功能。只要使用 GKE,即可指定容器節點的數量,做為工作負載測試架構的基礎。您也可以將工作負載測試工作站組織成 Pod,並指定讓 GKE 維持運作的 Pod 數量。

    如要部署工作負載測試工作,請執行下列操作:

    1. 部署工作負載測試主要執行個體,在 Locust 中稱為「主要執行個體」
    2. 部署工作負載測試工作站的群組。這些工作負載測試工作站可讓您建立大量流量,以便進行測試。

    下圖顯示使用範例應用程式負載測試的架構。主 Pod 會提供用於執行及監控負載測試的網頁介面。worker Pod 會為進行測試的應用程式產生 REST 要求流量,並將指標傳送至主機。

    主要 Pod 會提供用於執行及監控負載測試的網頁介面。工作 Pod 會為進行測試的應用程式產生 REST 要求流量。

    關於工作負載測試主要執行個體

    Locust 主要執行個體是執行工作負載測試工作的進入點。Locust 主要執行個體設定會指定幾個元素,包括容器使用的預設通訊埠:

    • 8089 適用於網頁介面
    • 55575558 適用於與工作站通訊

    這個資訊之後會用來設定 Locust 工作站。

    您必須部署服務,以確保必要的通訊埠可從叢集中的 hostname:port 供其他 Pod 存取,而且可透過通訊埠敘述名稱進行參照。

    這項服務可讓 Locust 工作站輕鬆找到主要執行個體,並與該執行個體穩定通訊,即使主要執行個體發生錯誤,並由部署作業以新的 Pod 取代,也一樣。

    我們會部署第二個服務,並加上必要的註解,以建立內部直通網路負載平衡器,讓叢集外的客戶 (使用相同的 VPC 網路,且位於與叢集相同的 Google Cloud 區域) 可以存取 Locust 網頁應用程式服務。

    部署 Locust 主要執行個體後,您可以使用內部直通式網路負載平衡器提供的內部 IP 位址開啟網頁介面。在部署 Locust 工作站後,您可以啟動模擬並透過 Locust 網頁介面查看匯總後的統計資料。

    關於工作負載測試工作站

    Locust 工作站負責執行工作負載測試工作。您必須使用單一部署建立多個 Pod,而這些 Pod 會分散到 Kubernetes 叢集上。每個 Pod 會使用環境變數控制設定資訊,例如測試狀態下的系統主機名稱以及 Locust 主要執行個體的主機名稱。

    下圖顯示 Locust 主要執行個體與 Locust 工作站之間的關係。

    Locust 主要執行個體位於階層頂端,下方有多個工作站。

    初始化常見變數

    您必須定義多個變數,以控制基礎架構的元素部署位置。

    1. 開啟 Cloud Shell:

      開啟 Cloud Shell

      您將透過 Cloud Shell 執行本文件中的所有終端機指令。

    2. 設定需要自訂的環境變數:

      export GKE_CLUSTER=GKE_CLUSTER
      export AR_REPO=AR_REPO
      export REGION=REGION
      export ZONE=ZONE
      export SAMPLE_APP_LOCATION=SAMPLE_APP_LOCATION
      

      更改下列內容:

      • GKE_CLUSTER:GKE 叢集名稱。
      • AR_REPO:Artifact Registry 存放區名稱
      • REGION:要建立 GKE 叢集和 Artifact Registry 存放區的區域
      • ZONE:您要建立 Compute Engine 執行個體的區域中的可用區
      • SAMPLE_APP_LOCATION:範例 App Engine 應用程式將部署至的(區域) 位置

      指令應如下所示:

      export GKE_CLUSTER=gke-lt-cluster
      export AR_REPO=dist-lt-repo
      export REGION=us-central1
      export ZONE=us-central1-b
      export SAMPLE_APP_LOCATION=us-central
      
    3. 設定下列其他環境變數:

      export GKE_NODE_TYPE=e2-standard-4
      export GKE_SCOPE="https://www.googleapis.com/auth/cloud-platform"
      export PROJECT=$(gcloud config get-value project)
      export SAMPLE_APP_TARGET=${PROJECT}.appspot.com
      
    4. 設定預設區域,這樣您就不必在後續指令中指定這些值:

      gcloud config set compute/zone ${ZONE}
      

    建立 GKE 叢集

    1. 建立服務帳戶,並授予叢集所需的最低權限:

      gcloud iam service-accounts create dist-lt-svc-acc
      gcloud projects add-iam-policy-binding  ${PROJECT} --member=serviceAccount:dist-lt-svc-acc@${PROJECT}.iam.gserviceaccount.com --role=roles/artifactregistry.reader
      gcloud projects add-iam-policy-binding  ${PROJECT} --member=serviceAccount:dist-lt-svc-acc@${PROJECT}.iam.gserviceaccount.com --role=roles/container.nodeServiceAccount
      
    2. 建立 GKE 叢集:

      gcloud container clusters create ${GKE_CLUSTER} \
      --service-account=dist-lt-svc-acc@${PROJECT}.iam.gserviceaccount.com \
      --region ${REGION} \
      --machine-type ${GKE_NODE_TYPE} \
      --enable-autoscaling \
      --num-nodes 3 \
      --min-nodes 3 \
      --max-nodes 10 \
      --scopes "${GKE_SCOPE}"
      
    3. 連線至 GKE 叢集:

      gcloud container clusters get-credentials ${GKE_CLUSTER} \
         --region ${REGION} \
         --project ${PROJECT}
      

    設定環境

    1. 從 GitHub 複製範例存放區:

      git clone https://github.com/GoogleCloudPlatform/distributed-load-testing-using-kubernetes
      
    2. 將工作目錄變更為複製的存放區:

      cd distributed-load-testing-using-kubernetes
      

    建構容器映像檔

    1. 建立 Artifact Registry 存放區:

      gcloud artifacts repositories create ${AR_REPO} \
          --repository-format=docker  \
          --location=${REGION} \
          --description="Distributed load testing with GKE and Locust"
    2. 建構容器映像檔並儲存在 Artifact Registry 存放區中:

      export LOCUST_IMAGE_NAME=locust-tasks
      export LOCUST_IMAGE_TAG=latest
      gcloud builds submit \
          --tag ${REGION}-docker.pkg.dev/${PROJECT}/${AR_REPO}/${LOCUST_IMAGE_NAME}:${LOCUST_IMAGE_TAG} \
          docker-image
      

      隨附的 Locust Docker 映像檔會嵌入測試工作,在範例應用程式中呼叫 /login/metrics 端點。在這個示例測試工作組合中,提交至這兩個端點的要求比率分別為 1999

      
      class MetricsTaskSet(TaskSet):
          _deviceid = None
      
          def on_start(self):
              self._deviceid = str(uuid.uuid4())
      
          @task(1)
          def login(self):
              self.client.post(
                  '/login', {"deviceid": self._deviceid})
      
          @task(999)
          def post_metrics(self):
              self.client.post(
                  "/metrics", {"deviceid": self._deviceid, "timestamp": datetime.now()})
      
      
      class MetricsLocust(FastHttpUser):
          tasks = {MetricsTaskSet}
      

    3. 確認 Docker 映像檔是否位於 Artifact Registry 存放區中:

      gcloud artifacts docker images list ${REGION}-docker.pkg.dev/${PROJECT}/${AR_REPO} | \
          grep ${LOCUST_IMAGE_NAME}
      

      輸出結果會與下列內容相似:

      Listing items under project PROJECT, location REGION, repository AR_REPO
      
      REGION-docker.pkg.dev/PROJECT/AR_REPO/locust-tasks  sha256:796d4be067eae7c82d41824791289045789182958913e57c0ef40e8d5ddcf283  2022-04-13T01:55:02  2022-04-13T01:55:02
      

    部署範例應用程式

    1. 建立並部署範例網頁應用程式,做為 App Engine:

      gcloud app create --region=${SAMPLE_APP_LOCATION}
      gcloud app deploy sample-webapp/app.yaml \
      --project=${PROJECT}
      
    2. 出現提示時,請輸入 y 繼續部署作業。

      輸出結果會與下列內容相似:

      File upload done.
      Updating service [default]...done.
      Setting traffic split for service [default]...done.
      Deployed service [default] to [https://PROJECT.appspot.com]
      

      範例 App Engine 應用程式會實作 /login/metrics 端點:

      @app.route('/login',  methods=['GET', 'POST'])
      def login():
          deviceid = request.values.get('deviceid')
          return '/login - device: {}\n'.format(deviceid)
      
      @app.route('/metrics',  methods=['GET', 'POST'])
      def metrics():
          deviceid = request.values.get('deviceid')
          timestamp = request.values.get('timestamp')
      
          return '/metrics - device: {}, timestamp: {}\n'.format(deviceid, timestamp)

    部署 Locust 主要執行個體與工作站 Pod

    1. locust-master-controller.yamllocust-worker-controller.yaml 檔案中的目標主機、專案和圖片參數替換為環境變數值,然後建立 Locust 主控台和 worker 部署:

      envsubst < kubernetes-config/locust-master-controller.yaml.tpl | kubectl apply -f -
      envsubst < kubernetes-config/locust-worker-controller.yaml.tpl | kubectl apply -f -
      envsubst < kubernetes-config/locust-master-service.yaml.tpl | kubectl apply -f -
      
    2. 驗證 Locust 部署作業:

      kubectl get pods -o wide
      

      輸出結果看起來會與下列內容相似:

      NAME                             READY   STATUS    RESTARTS   AGE   IP           NODE
      locust-master-87f8ffd56-pxmsk    1/1     Running   0          1m    10.32.2.6    gke-gke-load-test-default-pool-96a3f394
      locust-worker-58879b475c-279q9   1/1     Running   0          1m    10.32.1.5    gke-gke-load-test-default-pool-96a3f394
      locust-worker-58879b475c-9frbw   1/1     Running   0          1m    10.32.2.8    gke-gke-load-test-default-pool-96a3f394
      locust-worker-58879b475c-dppmz   1/1     Running   0          1m    10.32.2.7    gke-gke-load-test-default-pool-96a3f394
      locust-worker-58879b475c-g8tzf   1/1     Running   0          1m    10.32.0.11   gke-gke-load-test-default-pool-96a3f394
      locust-worker-58879b475c-qcscq   1/1     Running   0          1m    10.32.1.4    gke-gke-load-test-default-pool-96a3f394
      
    3. 驗證服務:

      kubectl get services
      

      輸出結果看起來會與下列內容相似:

      NAME                TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)             AGE
      kubernetes          ClusterIP      10.87.240.1     <none>        443/TCP             12m
      locust-master       ClusterIP      10.87.245.22    <none>        5557/TCP,5558/TCP    1m
      locust-master-web   LoadBalancer   10.87.246.225   <pending>     8089:31454/TCP       1m
      
    4. 為 Locust 主要執行個體網路應用程式服務佈建內部直通式網路負載平衡器的內部 IP 位址 (GKE 外部 IP 位址) 時,執行觀察循環:

      kubectl get svc locust-master-web --watch
      
    5. EXTERNAL-IP 位址佈建完成後,按下 Ctrl+C 即可退出觀察循環。

    連線至 Locust 網路前端

    您可以使用 Locust 主要執行個體網頁介面,對測試狀態下的系統執行工作負載測試工作。

    1. 記下網站主機服務的內部負載平衡器 IP 位址:

      export INTERNAL_LB_IP=$(kubectl get svc locust-master-web  \
                                     -o jsonpath="{.status.loadBalancer.ingress[0].ip}") && \
                                     echo $INTERNAL_LB_IP
      
    2. 視網路設定而定,您可以透過已配置的 IP 位址,以兩種方式連線至 Locust 網頁應用程式:

      • 網路路由。如果網路已設定為允許從工作站路由至專案 VPC 網路,您就可以直接從工作站存取內部轉送網路負載平衡器 IP 位址。

      • Proxy 和 SSH 通道如果工作站和 VPC 網路之間沒有網路路徑,您可以建立 Compute Engine 執行個體,並在工作站和執行個體之間建立 nginx Proxy 和 SSH 通道,將流量轉送至內部直通式網路負載平衡器的 IP 位址。

    網路路由

    如果工作站和Google Cloud 專案 VPC 網路之間有網路流量路徑,請開啟瀏覽器,然後開啟 Locust 主要執行個體網頁介面。如要開啟 Locust 介面,請前往下列網址:

    http://INTERNAL_LB_IP:8089
    

    INTERNAL_LB_IP 替換為您在上一個步驟中記下的網址和 IP 位址。

    Proxy 和 SSH 通道

    1. 使用執行個體名稱設定環境變數。

      export PROXY_VM=locust-nginx-proxy
      
    2. 啟動執行個體時,使用 ngnix Docker 容器,並將其設定為在內部直通式網路負載平衡器上代理 Locust 網路應用程式通訊埠 8089

      gcloud compute instances create-with-container ${PROXY_VM} \
         --zone ${ZONE} \
         --container-image gcr.io/cloud-marketplace/google/nginx1:latest \
         --container-mount-host-path=host-path=/tmp/server.conf,mount-path=/etc/nginx/conf.d/default.conf \
         --metadata=startup-script="#! /bin/bash
           cat <<EOF  > /tmp/server.conf
           server {
               listen 8089;
               location / {
                   proxy_pass http://${INTERNAL_LB_IP}:8089;
               }
           }
      EOF"
      
    3. 開啟從 Cloud Shell 到 Proxy 執行個體的 SSH 通道:

      gcloud compute ssh --zone ${ZONE} ${PROXY_VM} \
                       -- -N -L 8089:localhost:8089
      
    4. 按一下「Web Preview」圖示 (Cloud Shell 網頁預覽圖示),然後從列出的選項中選取「Change Port」

    5. 在「Change Preview Port」(變更預覽通訊埠) 對話方塊的「Port Number」(通訊埠編號) 欄位中輸入 8089,然後選取「Change and Preview」(變更並預覽)

      瀏覽器分頁隨即會開啟,並顯示 Locust 網路介面。

    對範例應用程式執行基本負載測試

    1. 在瀏覽器中開啟 Locust 前端後,您會看到可用於啟動新負載測試的對話方塊。

      Locust 主要執行個體網頁介面提供了對話方塊,可用來啟動新的群集,並指定使用者人數和產生率。

    2. 指定「使用者人數」總數為 10,以及「產生率」(使用者啟動/秒) 為每秒 5 位使用者。

    3. 按一下 [Start swarming] (開始群集) 即可開始進行模擬。

      要求開始群集後,系統會開始匯總模擬指標的統計資料,例如要求數量以及每秒要求數量,如下圖所示:

      Locust 網頁介面顯示統計資料開始匯總。

    4. 您可以透過 Google Cloud 控制台查看已部署的服務和其他指標。

      App Engine 資訊主頁顯示一小時內按類型細分的要求數量圖表。

    5. 觀察測試中的應用程式行為後,請按一下「停止」終止測試。

    擴大使用者人數 (選用)

    如果您要測試應用程式的載入量增加,可以新增模擬使用者。新增模擬使用者前,您必須確保有足夠的資源可支援增加的載入量。使用 Google Cloud時,只要擁有基礎 VM 資源可支援增加的 Pod 數量,就可以將 Locust 工作站 Pod 加入部署作業,而不必重新部署現有的 Pod。初始 GKE 叢集從 3 個節點開始,最多可自動擴充至 10 個節點。

    • 將 Locust 工作站 Pod 的集區比例調整成 20。

      kubectl scale deployment/locust-worker --replicas=20
      

      部署並啟動新的 Pod 需要幾分鐘的時間。

    如果系統顯示 Pod 無法排程的錯誤,您必須在叢集中新增更多節點。詳情請參閱「調整 GKE 叢集大小」。

    在 Pod 啟動後,請返回 Locust 主要執行個體網頁介面,並重新啟動負載測試。

    擴展模式

    如要擴展這個模式,您可以建立新的 Locust 工作,或甚至是切換至不同的工作負載測試架構。

    您可以自訂要收集的指標。舉例來說,您可能想要測量每秒要求數、在工作負載增加時監控回應延遲時間,或是檢查回應失敗率和錯誤類型。

    詳情請參閱 Cloud Monitoring 說明文件。

    清除所用資源

    如要避免系統向您的 Google Cloud 帳戶收取本文件所用資源的費用,請刪除含有相關資源的專案,或者保留專案但刪除個別資源。

    刪除專案

    1. In the Google Cloud console, go to the Manage resources page.

      Go to Manage resources

    2. In the project list, select the project that you want to delete, and then click Delete.
    3. In the dialog, type the project ID, and then click Shut down to delete the project.

    刪除 GKE 叢集

    如果您不想刪除整個專案,請執行下列指令以刪除 GKE 叢集:

       gcloud container clusters delete ${GKE_CLUSTER} --region ${REGION}
       

    後續步驟