連結 Cloud Spanner 與 GKE Autopilot

1. 簡介

Cloud Spanner 是全代管且遍及全球的關聯資料庫服務,提供 ACID 交易和 SQL 語意,但不會犧牲效能及高可用性。

GKE Autopilot 是 GKE 的作業模式,Google 會管理您的叢集設定,包括節點、資源調度、安全性,以及遵循最佳做法的其他預設設定。舉例來說,GKE Autopilot 會啟用 Workload Identity 來管理服務權限。

本研究室的目標是逐步引導您將多項在 GKE Autopilot 上執行的後端服務連結至 Cloud Spanner 資料庫。

3d810aa9ec80a271.png

在本研究室中,您將先設定專案並啟動 Cloud Shell。接著,您會透過 Terraform 部署基礎架構。

完成後,您需要與 Cloud Build 和 Cloud Deploy 互動,為遊戲資料庫執行初始結構定義遷移作業、部署後端服務,然後部署工作負載。

本程式碼研究室中的服務與「Cloud Spanner 開始使用遊戲開發」程式碼研究室中的服務相同。即使沒有參加該程式碼研究室,也能在 GKE 中執行服務並連線至 Spanner。不過,如果您有意進一步瞭解能在 Spanner 中運作的服務,歡迎多加參考。

工作負載和後端服務開始運作之後,您就可以開始產生負載,並觀察這些服務如何搭配運作。

最後,您將清除在這個研究室中建立的資源。

建構項目

在這個研究室中,您將完成以下工作:

  • 使用 Terraform 佈建基礎架構
  • 在 Cloud Build 中使用結構定義遷移程序建立資料庫結構定義
  • 部署四個使用 Workload Identity 來連線至 Cloud Spanner 的 Golang 後端服務
  • 部署四個工作負載服務,用來模擬後端服務的負載。

課程內容

  • 如何使用 Terraform 佈建 GKE Autopilot、Cloud Spanner 和 Cloud Deploy 管道
  • Workload Identity 如何讓 GKE 上的服務以服務帳戶的身分存取 IAM 權限,以便與 Cloud Spanner 搭配使用
  • 如何使用 Locust.io 在 GKE 和 Cloud Spanner 中產生類似實際工作環境的負載

軟硬體需求

  • 連結至帳單帳戶的 Google Cloud 專案。
  • 使用網路瀏覽器,例如 ChromeFirefox

2. 設定和需求

建立專案

如果您還沒有 Google 帳戶 (Gmail 或 Google Apps),請先建立帳戶。登入 Google Cloud Platform 控制台 ( console.cloud.google.com),並建立新專案。

如果您已有專案,請按一下控制台左上方的專案選取下拉式選單:

6c9406d9b014760.png

並按一下 [新增專案]按鈕,用於建立新專案:

949d83c8a4ee17d9.png

如果您還沒有專案,系統會顯示如下的對話方塊,讓您建立第一個專案:

870a3cbd6541ee86.png

後續的專案建立對話方塊可讓您輸入新專案的詳細資料:

6a92c57d3250a4b3.png

請記住,專案 ID 在所有的 Google Cloud 專案中是不重複的名稱 (已經有人使用上述名稱,目前無法為您解決問題!)。稍後在本程式碼研究室中會稱為 PROJECT_ID

接下來,如果您尚未在 Developers Console 中啟用計費功能,必須完成此步驟,才能使用 Google Cloud 資源並啟用 Cloud Spanner API

15d0ef27a8fbab27.png

執行本程式碼研究室所需的費用不應超過數美元,但如果您決定使用更多資源,或讓這些資源繼續運作,費用會增加 (請參閱本文件結尾的「清理」一節)。Google Cloud Spanner 的定價請參閱這裡;GKE Autopilot 請參閱這裡

Google Cloud Platform 的新使用者符合 $300 美元的免費試用資格,應該可以免費使用本程式碼研究室。

Cloud Shell 設定

雖然 Google Cloud 和 Spanner 可以在筆記型電腦上遠端運作,但在本程式碼研究室中,我們會使用 Google Cloud Shell,這是一種在 Cloud 中執行的指令列環境。

這種以 Debian 為基礎的虛擬機器,搭載各種您需要的開發工具。提供永久的 5 GB 主目錄,而且在 Google Cloud 中運作,大幅提高網路效能和驗證能力。換言之,本程式碼研究室只需要在 Chromebook 上運作即可。

  1. 如要透過 Cloud 控制台啟用 Cloud Shell,只要點選「啟用 Cloud Shell」圖示 gcLMt5IuEcJJNnMId-Bcz3sxCd0rZn7IzT_r95C8UZeqML68Y1efBG_B0VRp7hc7qiZTLAF-TXD7SsOadxn8uadgHhaLeASnVS3ZHK39eOlKJOgj9SJua_oeGhMxRrbOg3qigddS2A,即可佈建並連線至環境,操作只需幾分鐘的時間。

JjEuRXGg0AYYIY6QZ8d-66gx_Mtc-_jDE9ijmbXLJSAXFvJt-qUpNtsBsYjNpv2W6BQSrDc1D-ARINNQ-1EkwUhz-iUK-FUCZhJ-NtjvIEx9pIkE-246DomWuCfiGHK78DgoeWkHRw

Screen Shot 2017-06-14 at 10.13.43 PM.png

連線至 Cloud Shell 後,您應會發現自己通過驗證,且專案已設為 PROJECT_ID

gcloud auth list

指令輸出

Credentialed accounts:
 - <myaccount>@<mydomain>.com (active)
gcloud config list project

指令輸出

[core]
project = <PROJECT_ID>

如因故未設定專案,請直接發出以下指令:

gcloud config set project <PROJECT_ID>

正在尋找 PROJECT_ID 嗎?查看您在設定步驟中使用的 ID,或在 Cloud 控制台資訊主頁查詢:

158fNPfwSxsFqz9YbtJVZes8viTS3d1bV4CVhij3XPxuzVFOtTObnwsphlm6lYGmgdMFwBJtc-FaLrZU7XHAg_ZYoCrgombMRR3h-eolLPcvO351c5iBv506B3ZwghZoiRg6cz23Qw

根據預設,Cloud Shell 也會設定一些環境變數,方便您之後執行指令。

echo $GOOGLE_CLOUD_PROJECT

指令輸出

<PROJECT_ID>

下載程式碼

在 Cloud Shell 中,您可以下載本研究室的程式碼:

git clone https://github.com/cloudspannerecosystem/spanner-gaming-sample.git

指令輸出

Cloning into 'spanner-gaming-sample'...
*snip*

本程式碼研究室是以 v0.1.3 版本為基礎,因此請查看該標記:

cd spanner-gaming-sample
git fetch --all --tags

# Check out v0.1.3 release
git checkout tags/v0.1.3 -b v0.1.3-branch

指令輸出

Switched to a new branch 'v0.1.3-branch'

現在,將目前的工作目錄設為 DEMO_HOME 環境變數。這可讓您在使用程式碼研究室的不同部分時輕鬆瀏覽。

export DEMO_HOME=$(pwd)

摘要

在這個步驟中,您設定了新專案、已啟用 Cloud Shell,並下載這個研究室的程式碼。

下一步

接下來,您將透過 Terraform 佈建基礎架構。

3. 佈建基礎架構

總覽

專案準備就緒後,就可以開始執行基礎架構了。這類元件包括虛擬私有雲網路、Cloud Spanner、GKE Autopilot 和 Artifact Registry,可用於儲存要在 GKE 上執行的映像檔、後端服務和工作負載的 Cloud Deploy 管道,以及使用這些服務的服務帳戶和 IAM 權限。

它有很多種。幸好,Terraform 可以簡化這項設定程序。Terraform 是「基礎架構即程式碼」方便我們在一系列「.tf」中為這項專案指定所需項目檔案。這麼一來,您就能輕鬆佈建基礎架構。

熟悉 Terraform 並非完成本程式碼研究室的必要條件。不過,如果您想查看接下來的幾個步驟,可以前往 infrastructure 目錄查看這些檔案建立的所有內容:

  • vpc.tf
  • backend_gke.tf
  • spanner.tf
  • artifact_registry.tf
  • pipelines.tf
  • iam.tf

設定 Terraform

在 Cloud Shell 中,您要變更為 infrastructure 目錄並初始化 Terraform:

cd $DEMO_HOME/infrastructure
terraform init

指令輸出

Initializing the backend...

Initializing provider plugins...
*snip*
Terraform has been successfully initialized!

You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.

If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.

接著,複製 terraform.tfvars.sample 並修改專案值來設定 Terraform。您也可以變更其他變數,但專案是唯一要變更的專案,才能與您的環境搭配運作。

cp  terraform.tfvars.sample terraform.tfvars
# edit gcp_project using the project environment variable
sed -i "s/PROJECT/$GOOGLE_CLOUD_PROJECT/" terraform.tfvars

佈建基礎架構

現在要佈建基礎架構了!

terraform apply
# review the list of things to be created
# type 'yes' when asked

指令輸出

Plan: 46 to add, 0 to change, 0 to destroy.

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: yes

google_project_service.project["container.googleapis.com"]: Creating...
*snip*
Apply complete! Resources: 46 added, 0 changed, 0 destroyed.

查看建立的內容

如要確認建立的內容,請查看 Cloud 控制台中的產品。

Cloud Spanner

首先,前往漢堡選單並點選 Spanner,查看 Cloud Spanner。您可能需要點選「查看更多產品」以便從清單中找出該代碼

系統會將您導向 Spanner 執行個體清單。點進執行個體,即可查看資料庫。如下所示:

10b7fc0c4a86c59.png

GKE Autopilot

接著,前往漢堡選單並點選「Kubernetes Engine => Clusters」,查看 GKE。這裡會顯示 sample-games-gke 叢集在 Autopilot 模式下執行。

9cecb1a702e6b7ff.png

Artifact Registry

接著,您需要查看圖片的儲存位置。因此,請按一下漢堡選單,然後找出「Artifact Registry=>Repositories」。Artifact Registry 位於選單的「CI/CD」專區中。

在這裡,您會看到名為 spanner-game-images 的 Docker Registry。目前沒有任何內容。

3f805eee312841b.png

Cloud Deploy

Cloud Deploy 是建立管道的位置,可讓 Cloud Build 提供建構映像檔的步驟,然後將映像檔部署至 GKE 叢集。

前往漢堡選單並找出 Cloud Deploy,它也位於選單的「CI/CD」部分中。

您會在這裡看到兩個管道,一個用於後端服務,另一個用於工作負載。兩者都會將映像檔部署至同一個 GKE 叢集,但這麼做可以將部署作業區隔開來。

d2e4a659145ddf5e.png

IAM

最後,請前往 Cloud 控制台的「IAM」頁面,驗證建立的服務帳戶。前往漢堡選單並找到 IAM and Admin=>Service accounts。如下所示:

bed3d1af94974916.png

Terraform 建立的服務帳戶總共有六個:

  • 預設電腦服務帳戶。未在本程式碼研究室中用到。
  • cloudbuild-cicd 帳戶會用於 Cloud Build 和 Cloud Deploy 步驟。
  • 四個「應用程式」,透過這個帳戶與 Cloud Spanner 互動。

接下來,您要設定 kubectl 來與 GKE 叢集互動。

設定 kubectl

# Name of GKE cluster from terraform.tfvars file
export GKE_CLUSTER=sample-game-gke 

# get GKE credentials
gcloud container clusters get-credentials $GKE_CLUSTER --region us-central1

# Check that no errors occur
kubectl get serviceaccounts

指令輸出

#export GKE_CLUSTER=sample-game-gke

# gcloud container clusters get-credentials $GKE_CLUSTER --region us-central1
Fetching cluster endpoint and auth data.
kubeconfig entry generated for sample-game-gke.

# kubectl get serviceaccounts
NAME              SECRETS   AGE
default           0         37m
item-app          0         35m
matchmaking-app   0         35m
profile-app       0         35m
tradepost-app     0         35m

摘要

太好了!您已成功佈建 Cloud Spanner 執行個體,也就是 GKE Autopilot 叢集,所有作業都在虛擬私有雲中,以建立私人網路。

此外,您也為後端服務和工作負載建立了兩個 Cloud Deploy 管道,以及一個用於儲存建構映像檔的 Artifact Registry 存放區。

最後,已建立並設定服務帳戶,藉此與 Workload Identity 搭配使用,好讓後端服務能使用 Cloud Spanner。

在部署後端服務和工作負載後,您也將 kubectl 設為在 Cloud Shell 中與 GKE 叢集互動。

下一步

您必須先定義資料庫結構定義,才能使用服務。接下來,您會完成設定。

4. 建立資料庫結構定義

總覽

執行後端服務前,您必須確保資料庫結構定義已設置妥當。

如果您在示範存放區中查看「$DEMO_HOME/schema/migrations目錄中的檔案,就會看到一系列定義結構定義的 .sql 檔案。這種作法是模仿的開發週期,存放區本身會追蹤結構定義變更,並且可與應用程式的特定功能連結。

在此範例環境中,扳手是可使用 Cloud Build 套用結構定義遷移的工具。

Cloud Build

$DEMO_HOME/schema/cloudbuild.yaml 檔案說明將執行的步驟:

serviceAccount: projects/${PROJECT_ID}/serviceAccounts/cloudbuild-cicd@${PROJECT_ID}.iam.gserviceaccount.com
steps:
- name: gcr.io/cloud-builders/curl
 id: fetch-wrench
 args: ['-Lo', '/workspace/wrench.tar.gz', 'https://github.com/cloudspannerecosystem/wrench/releases/download/v1.4.1/wrench-1.4.1-linux-amd64.tar.gz' ]

- name: gcr.io/cloud-builders/gcloud
 id: migrate-spanner-schema
 entrypoint: sh
 args:
 - '-xe'
 - '-c'
 - |
   tar -xzvf wrench.tar.gz

   chmod +x /workspace/wrench

   # Assumes only a single spanner instance and database. Fine for this demo in a dedicated project
   export SPANNER_PROJECT_ID=${PROJECT_ID}
   export SPANNER_INSTANCE_ID=$(gcloud spanner instances list | tail -n1 | awk '{print $1}')
   export SPANNER_DATABASE_ID=$(gcloud spanner databases list --instance=$$SPANNER_INSTANCE_ID | tail -n1 | awk '{print $1}')

   if [ -d ./migrations ]; then
     /workspace/wrench migrate up --directory .
   else
     echo "[Error] Missing migrations directory"
   fi
timeout: 600s

基本上包含兩個步驟

  • 將扳手下載至 Cloud Build 工作區
  • 執行扳手遷移

必須要有 Spanner 專案、執行個體和資料庫環境變數,扳手才能連線至寫入端點。

Cloud Build 會以 cloudbuild-cicd@${PROJECT_ID}.iam.gserviceaccount.com 服務帳戶的身分執行,因此可以進行這些變更:

serviceAccount: projects/${PROJECT_ID}/serviceAccounts/cloudbuild-cicd@${PROJECT_ID}.iam.gserviceaccount.com

這個服務帳戶由 Terraform 新增 spanner.databaseUser 角色,可讓服務帳戶 updateDDL。

結構定義遷移作業

系統會根據 $DEMO_HOME/schema/migrations 目錄中的檔案執行五個遷移步驟。以下是建立 players 資料表和索引的 000001.sql 檔案範例:

CREATE TABLE players (
   playerUUID STRING(36) NOT NULL,
   player_name STRING(64) NOT NULL,
   email STRING(MAX) NOT NULL,
   password_hash BYTES(60) NOT NULL,
   created TIMESTAMP,
   updated TIMESTAMP,
   stats JSON,
   account_balance NUMERIC NOT NULL DEFAULT (0.00),
   is_logged_in BOOL,
   last_login TIMESTAMP,
   valid_email BOOL,
   current_game STRING(36)
) PRIMARY KEY (playerUUID);

CREATE UNIQUE INDEX PlayerAuthentication ON players(email) STORING(password_hash);
CREATE UNIQUE INDEX PlayerName ON players(player_name);
CREATE INDEX PlayerGame ON players(current_game);

提交結構定義遷移作業

如要提交版本來執行結構定義遷移,請切換至 schema 目錄並執行下列 gcloud 指令:

cd $DEMO_HOME/schema
gcloud builds submit --config=cloudbuild.yaml

指令輸出

Creating temporary tarball archive of 8 file(s) totalling 11.2 KiB before compression.
Uploading tarball of [.] to [gs://(project)_cloudbuild/source/(snip).tgz]
Created [https://cloudbuild.googleapis.com/v1/projects/(project)/locations/global/builds/7defe982-(snip)].
Logs are available at [ https://console.cloud.google.com/cloud-build/builds/7defe982-(snip)?project=(snip) ].

gcloud builds submit only displays logs from Cloud Storage. To view logs from Cloud Logging, run:
gcloud beta builds submit

ID: 7defe982-(snip)
CREATE_TIME: (created time)
DURATION: 3M11S
SOURCE: gs://(project)_cloudbuild/source/(snip).tgz
IMAGES: -
STATUS: SUCCESS

在上方的輸出內容中,您會看到 Created 雲端建構程序的連結。點選該名稱後,系統會將您導向 Cloud 控制台中的建構作業,方便您監控建構作業的進度及瞭解建構內容。

11b1cf107876d797.png

摘要

在這個步驟中,您使用了 Cloud Build 來提交套用 5 項不同 DDL 作業的初始結構定義遷移作業。這類作業代表了何時新增的特徵,需要變更資料庫結構定義。

在正常的開發情境中,您可能會想要進行與目前應用程式回溯相容的結構定義變更,以免服務中斷。

如果變更無法回溯相容,建議您分階段部署應用程式和結構定義的變更,以免服務中斷。

下一步

備妥結構定義後,下一步就是部署後端服務!

5. 部署後端服務

總覽

本程式碼研究室的後端服務是代表四種不同服務的 golang REST API:

  • 設定檔:讓玩家註冊並驗證我們的「遊戲」範例。
  • 配對:與玩家資料互動,協助配對功能、追蹤已建立遊戲的相關資訊,並在遊戲結束後更新玩家統計資料。
  • 項目:讓玩家在玩遊戲的過程中取得遊戲道具和金錢。
  • Tradepost:讓玩家可以在貿易站上買賣商品

d36e958411d44b5d.png

如要進一步瞭解這些服務,請參閱 Cloud Spanner 開始使用遊戲開發程式碼研究室。基於我們的目的,我們希望這些服務在 GKE Autopilot 叢集中執行。

這些服務必須能夠修改 Spanner 資料。為此,每項服務都具備已建立的服務帳戶,藉此授予「databaseUser」角色。

Workload Identity 可讓 Kubernetes 服務帳戶冒用服務,按照以下步驟操作 Terraform:

  • 建立服務的 Google Cloud 服務帳戶 (GSA) 資源
  • databaseUser 角色指派給該服務帳戶
  • workloadIdentityUser 角色指派給該服務帳戶
  • 建立參照 GSA 的 Kubernetes 服務帳戶 (KSA)

粗略的圖表如下所示:

a8662d31d66b5910.png

Terraform 已為您建立服務帳戶和 Kubernetes 服務帳戶。您也可以使用 kubectl 查看 Kubernetes 服務帳戶:

# kubectl get serviceaccounts
NAME              SECRETS   AGE
default           0         37m
item-app          0         35m
matchmaking-app   0         35m
profile-app       0         35m
tradepost-app     0         35m

建構的運作方式如下:

serviceAccount: projects/${PROJECT_ID}/serviceAccounts/cloudbuild-cicd@${PROJECT_ID}.iam.gserviceaccount.com
steps:

#
# Building of images
#
 - name: gcr.io/cloud-builders/docker
   id: profile
   args: ["build", ".", "-t", "${_PROFILE_IMAGE}"]
   dir: profile
   waitFor: ['-']
 - name: gcr.io/cloud-builders/docker
   id: matchmaking
   args: ["build", ".", "-t", "${_MATCHMAKING_IMAGE}"]
   dir: matchmaking
   waitFor: ['-']
 - name: gcr.io/cloud-builders/docker
   id: item
   args: ["build", ".", "-t", "${_ITEM_IMAGE}"]
   dir: item
   waitFor: ['-']
 - name: gcr.io/cloud-builders/docker
   id: tradepost
   args: ["build", ".", "-t", "${_TRADEPOST_IMAGE}"]
   dir: tradepost
   waitFor: ['-']

#
# Deployment
#
 - name: gcr.io/google.com/cloudsdktool/cloud-sdk
   id: cloud-deploy-release
   entrypoint: gcloud
   args:
     [
       "deploy", "releases", "create", "${_REL_NAME}",
       "--delivery-pipeline", "sample-game-services",
       "--skaffold-file", "skaffold.yaml",
       "--skaffold-version", "1.39",
       "--images", "profile=${_PROFILE_IMAGE},matchmaking=${_MATCHMAKING_IMAGE},item=${_ITEM_IMAGE},tradepost=${_TRADEPOST_IMAGE}",
       "--region", "us-central1"
     ]

artifacts:
 images:
   - ${_REGISTRY}/profile
   - ${_REGISTRY}/matchmaking
   - ${_REGISTRY}/item
   - ${_REGISTRY}/tradepost

substitutions:
 _PROFILE_IMAGE: ${_REGISTRY}/profile:${BUILD_ID}
 _MATCHMAKING_IMAGE: ${_REGISTRY}/matchmaking:${BUILD_ID}
 _ITEM_IMAGE: ${_REGISTRY}/item:${BUILD_ID}
 _TRADEPOST_IMAGE: ${_REGISTRY}/tradepost:${BUILD_ID}
 _REGISTRY: us-docker.pkg.dev/${PROJECT_ID}/spanner-game-images
 _REL_NAME: rel-${BUILD_ID:0:8}
options:
 dynamic_substitutions: true
 machineType: E2_HIGHCPU_8
 logging: CLOUD_LOGGING_ONLY
  • Cloud Build 指令會讀取這個檔案,並按照畫面上列出的步驟操作。首先建構服務映像檔然後執行 gcloud deploy create 指令。這會讀取 $DEMO_HOME/backend_services/skaffold.yaml 檔案,該檔案定義了每個部署檔案的所在位置:
apiVersion: skaffold/v2beta29
kind: Config
deploy:
 kubectl:
   manifests:
     - spanner_config.yaml
     - profile/deployment.yaml
     - matchmaking/deployment.yaml
     - item/deployment.yaml
     - tradepost/deployment.yaml
  • Cloud Deploy 會遵循每項服務 deployment.yaml 檔案的定義。服務的部署檔案包含建立服務的相關資訊,在本例中為在通訊埠 80 上執行的 clusterIP。

"ClusterIP" 類型可避免後端服務 Pod 擁有外部 IP,因此只有可以連線至內部 GKE 網路的實體才能存取後端服務。因此,玩家不應直接存取這些服務,因為這些服務會存取及修改 Spanner 資料。

apiVersion: v1
kind: Service
metadata:
 name: profile
spec:
 type: ClusterIP
 selector:
   app: profile
 ports:
 - port: 80
   targetPort: 80

除了建立 Kubernetes 服務外,Cloud Deploy 也會建立 Kubernetes Deployment。一起來看看 profile 服務的部署部分:

---
apiVersion: apps/v1
kind: Deployment
metadata:
 name: profile
spec:
 replicas: 2 # EDIT: Number of instances of deployment
 selector:
   matchLabels:
     app: profile
 template:
   metadata:
     labels:
       app: profile
   spec:
     serviceAccountName: profile-app
     containers:
     - name: profile-service
       image: profile
       ports:
         - containerPort: 80
       envFrom:
         - configMapRef:
             name: spanner-config
       env:
         - name: SERVICE_HOST
           value: "0.0.0.0"
         - name: SERVICE_PORT
           value: "80"
       resources:
         requests:
           cpu: "1"
           memory: "1Gi"
           ephemeral-storage: "100Mi"
         limits:
           cpu: "1"
           memory: "1Gi"
           ephemeral-storage: "100Mi"

頂部提供了一些服務的相關中繼資料,最重要的是,定義這個部署作業將建立多少備用資源。

replicas: 2 # EDIT: Number of instances of deployment

接著,我們會看到應執行應用程式的服務帳戶,以及應使用哪一個映像檔。這些執行個體與透過 Terraform 建立的 Kubernetes 服務帳戶和 Cloud Build 步驟中建立的映像檔相符。

spec:
  serviceAccountName: profile-app
  containers:
    - name: profile-service
      image: profile

之後,我們會指定網路與環境變數的一些資訊。

spanner_config 是 Kubernetes ConfigMap,指定應用程式連線至 Spanner 所需的專案、執行個體和資料庫資訊。

apiVersion: v1
kind: ConfigMap
metadata:
  name: spanner-config
data:
  SPANNER_PROJECT_ID: ${project_id}
  SPANNER_INSTANCE_ID: ${instance_id}
  SPANNER_DATABASE_ID: ${database_id}
ports:
  - containerPort: 80
envFrom:
  - configMapRef:
    name: spanner-config
env:
  - name: SERVICE_HOST
    value: "0.0.0.0"
  - name: SERVICE_PORT
    value: "80"

SERVICE_HOSTSERVICE_PORT 是服務取得繫結位置所需的其他環境變數。

最後一個部分會向 GKE 說明這個部署作業中各項備用資源允許多少資源。GKE Autopilot 也會使用這個指標視需要調度叢集資源。

resources:
  requests:
    cpu: "1"
    memory: "1Gi"
    ephemeral-storage: "100Mi"
  limits:
    cpu: "1"
    memory: "1Gi"
    ephemeral-storage: "100Mi"

掌握以上資訊後,即可部署後端服務。

部署後端服務

如上所述,部署後端服務會使用 Cloud Build。和遷移結構定義一樣,您可以使用 gcloud 指令列提交建構要求:

cd $DEMO_HOME/backend_services
gcloud builds submit --config=cloudbuild.yaml

指令輸出

Creating temporary tarball archive of 66 file(s) totalling 864.6 KiB before compression.
Uploading tarball of [.] to [gs://(project)_cloudbuild/source/(snip).tgz]
Created [https://cloudbuild.googleapis.com/v1/projects/(project)/locations/global/builds/30207dd1-(snip)].
Logs are available at [ https://console.cloud.google.com/cloud-build/builds/30207dd1-(snip)?project=(snip) ].

gcloud builds submit only displays logs from Cloud Storage. To view logs from Cloud Logging, run:
gcloud beta builds submit

ID: 30207dd1-(snip)
CREATE_TIME: (created time)
DURATION: 3M17S
SOURCE: gs://(project)_cloudbuild/source/(snip).tgz
IMAGES: us-docker.pkg.dev/(project)/spanner-game-images/profile:30207dd1-(snip) (+3 more)
STATUS: SUCCESS

schema migration 步驟的輸出內容不同,此建構作業的輸出內容會指出已建立一些圖片。這些內容會儲存在 Artifact Registry 存放區中。

gcloud build 步驟的輸出內容會包含 Cloud 控制台連結。快來看看這些指標。

收到 Cloud Build 的成功通知後,依序前往 Cloud Deploy,然後前往 sample-game-services 管道,即可監控部署作業的進度。

df5c6124b9693986.png

部署服務後,您可以透過 kubectl 查看 Pod 的狀態:

kubectl get pods

指令輸出

NAME                           READY   STATUS    RESTARTS   AGE
item-6b9d5f678c-4tbk2          1/1     Running   0          83m
matchmaking-5bcf799b76-lg8zf   1/1     Running   0          80m
profile-565bbf4c65-kphdl       1/1     Running   0          83m
profile-565bbf4c65-xw74j       1/1     Running   0          83m
tradepost-68b87ccd44-gw55r     1/1     Running   0          79m

接著,查看服務以瞭解 ClusterIP 的實際運作情形:

kubectl get services

指令輸出

NAME          TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
item          ClusterIP   10.172.XXX.XXX   <none>        80/TCP    84m
kubernetes    ClusterIP   10.172.XXX.XXX   <none>        443/TCP   137m
matchmaking   ClusterIP   10.172.XXX.XXX   <none>        80/TCP    84m
profile       ClusterIP   10.172.XXX.XXX   <none>        80/TCP    84m
tradepost     ClusterIP   10.172.XXX.XXX   <none>        80/TCP    84m

您也可以前往 Cloud 控制台中的 GKE UI,查看 WorkloadsServicesConfigMaps

工作負載

da98979ae49e5a30.png

服務

406ca2fe7ad4818b.png

ConfigMap

a0ebd34ee735ee11.png

3b9ef91c77a4e7f0.png

摘要

在這個步驟中,您已將四項後端服務部署至 GKE Autopilot。您已成功執行 Cloud Build 步驟,並在 Cloud 控制台中檢查 Cloud Deploy 和 Kubernetes 的進度。

您也瞭解這些服務如何利用 Workload Identity 來模擬具有適當權限的服務帳戶,以便讀取 Spanner 資料庫中的資料,以及將資料寫入 Spanner。

後續步驟

在下一節中,您將部署工作負載。

6. 部署工作負載

總覽

現在後端服務在叢集內運作,接下來請部署工作負載。

dd900485e2eeb611.png

這些工作負載可從外部存取,每個後端服務都有各自的工作負載,可用於本程式碼研究室。

這些工作負載是以 Locust 為基礎的負載產生指令碼,模擬了這些範例服務預期的實際存取模式。

以下是 Cloud Build 程序的檔案:

  • $DEMO_HOME/workloads/cloudbuild.yaml (由 Terraform 產生)
  • $DEMO_HOME/workloads/skaffold.yaml
  • 每項工作負載都有一個 deployment.yaml 檔案

工作負載 deployment.yaml 檔案與後端服務部署檔案看起來略有不同。

以下是 matchmaking-workload 的範例:

apiVersion: v1
kind: Service
metadata:
 name: matchmaking-workload
spec:
 type: LoadBalancer
 selector:
   app: matchmaking-workload
 ports:
 - port: 8089
   targetPort: 8089
---
apiVersion: apps/v1
kind: Deployment
metadata:
 name: matchmaking-workload
spec:
 replicas: 1 # EDIT: Number of instances of deployment
 selector:
   matchLabels:
     app: matchmaking-workload
 template:
   metadata:
     labels:
       app: matchmaking-workload
   spec:
     serviceAccountName: default
     containers:
     - name: matchmaking-workload
       image: matchmaking-workload
       ports:
         - containerPort: 8089
       resources:
         requests:
           cpu: "500m"
           memory: "512Mi"
           ephemeral-storage: "100Mi"
         limits:
           cpu: "500m"
           memory: "512Mi"
           ephemeral-storage: "100Mi"

檔案的最上層會定義服務。在此情況下,系統會建立 LoadBalancer,而工作負載會在通訊埠 8089 上執行。

LoadBalancer 會提供外部 IP,可用來連線至工作負載。

apiVersion: v1
kind: Service
metadata:
 name: matchmaking-workload
spec:
 type: LoadBalancer
 selector:
   app: matchmaking-workload
 ports:
 - port: 8089
   targetPort: 8089

「Deployment」(部署) 區段的頂端是工作負載的相關中繼資料。本例中只會部署一個備用資源:

replicas: 1 

但容器規格不同。舉例來說,我們要使用 default Kubernetes 服務帳戶,這個帳戶沒有任何特殊權限,因為工作負載不需要連線至任何 Google Cloud 資源 (在 GKE 叢集中執行的後端服務除外)。

另一個差別在於這些工作負載不需要任何環境變數。這會產生較短的部署作業規格。

spec:
  serviceAccountName: default
  containers:
    - name: matchmaking-workload
      image: matchmaking-workload
  ports:
    - containerPort: 8089

資源設定與後端服務類似。提醒您,GKE Autopilot 會知道需要多少資源,才能滿足叢集中所有 Pod 的要求。

請開始部署工作負載!

部署工作負載

和先前一樣,您可以使用 gcloud 指令列提交建構要求:

cd $DEMO_HOME/workloads
gcloud builds submit --config=cloudbuild.yaml

指令輸出

Creating temporary tarball archive of 18 file(s) totalling 26.2 KiB before compression.
Some files were not included in the source upload.

Check the gcloud log [/tmp/tmp.4Z9EqdPo6d/logs/(snip).log] to see which files and the contents of the
default gcloudignore file used (see `$ gcloud topic gcloudignore` to learn
more).

Uploading tarball of [.] to [gs://(project)_cloudbuild/source/(snip).tgz]
Created [https://cloudbuild.googleapis.com/v1/projects/(project)/locations/global/builds/(snip)].
Logs are available at [ https://console.cloud.google.com/cloud-build/builds/0daf20f6-(snip)?project=(snip) ].

gcloud builds submit only displays logs from Cloud Storage. To view logs from Cloud Logging, run:
gcloud beta builds submit

ID: 0daf20f6-(snip)
CREATE_TIME: (created_time)
DURATION: 1M41S
SOURCE: gs://(project)_cloudbuild/source/(snip).tgz
IMAGES: us-docker.pkg.dev/(project)/spanner-game-images/profile-workload:0daf20f6-(snip) (+4 more)
STATUS: SUCCESS

請務必檢查 Cloud 控制台中的 Cloud Build 記錄檔和 Cloud Deploy 管道,確認狀態。針對工作負載,Cloud Deploy 管道為 sample-game-workloads

部署完成後,請在 Cloud Shell 中透過 kubectl 檢查狀態:

kubectl get pods

指令輸出

NAME                                    READY   STATUS    RESTARTS   AGE
game-workload-7ff44cb657-pxxq2          1/1     Running   0          12m
item-6b9d5f678c-cr29w                   1/1     Running   0          9m6s
item-generator-7bb4f57cf8-5r85b         1/1     Running   0          12m
matchmaking-5bcf799b76-lg8zf            1/1     Running   0          117m
matchmaking-workload-76df69dbdf-jds9z   1/1     Running   0          12m
profile-565bbf4c65-kphdl                1/1     Running   0          121m
profile-565bbf4c65-xw74j                1/1     Running   0          121m
profile-workload-76d6db675b-kzwng       1/1     Running   0          12m
tradepost-68b87ccd44-gw55r              1/1     Running   0          116m
tradepost-workload-56c55445b5-b5822     1/1     Running   0          12m

接著,請檢查工作負載服務,瞭解 LoadBalancer 的實際運作情形:

kubectl get services 

指令輸出

NAME                   TYPE          CLUSTER-IP  EXTERNAL-IP     PORT(S)        AGE
game-workload          LoadBalancer  *snip*      35.XX.XX.XX   8089:32483/TCP   12m
item                   ClusterIP     *snip*      <none>         80/TCP          121m
item-generator         LoadBalancer  *snip*      34.XX.XX.XX   8089:32581/TCP   12m
kubernetes             ClusterIP     *snip*      <none>          443/TCP        174m
matchmaking            ClusterIP     *snip*      <none>          80/TCP         121m
matchmaking-workload   LoadBalancer  *snip*      34.XX.XX.XX   8089:31735/TCP   12m
profile                ClusterIP     *snip*      <none>          80/TCP         121m
profile-workload       LoadBalancer  *snip*      34.XX.XX.XX   8089:32532/TCP   12m
tradepost              ClusterIP     *snip*      <none>          80/TCP         121m
tradepost-workload     LoadBalancer  *snip*      34.XX.XX.XX   8089:30002/TCP   12m

摘要

現在已將工作負載部署至 GKE 叢集。這些工作負載不需要額外的 IAM 權限,且可透過 LoadBalancer 服務從通訊埠 8089 外部存取。

後續步驟

只要是正在執行後端服務和工作負載,就可以遊戲!

7. 開始玩遊戲

總覽

「遊戲」範例的後端服務而且還能產生「播放器」透過工作負載與這些服務互動

每個工作負載都會使用 Locust 來模擬服務 API 的實際負載。在這個步驟中,您將執行數項工作負載,在 GKE 叢集和 Spanner 上產生負載,並將資料儲存在 Spanner 中。

以下是各個工作負載的說明:

  • item-generator 工作負載是快速的工作負載,會產生 game_items 清單。玩家可以透過「玩遊戲」的過程中取得該清單遊戲。
  • profile-workload 會模擬玩家註冊和登入的情況。
  • matchmaking-workload 會模擬排入佇列至遊戲的玩家。
  • game-workload 會在遊戲過程中模擬玩家已取得 game_items 和金錢。
  • tradepost-workload 會模擬玩家在交易郵局上銷售及購買商品的玩家。

本程式碼研究室會特別執行 item-generatorprofile-workload

執行項目產生器

item-generator 會使用 item 後端服務端點,將 game_items 新增至 Spanner。您必須完成這些項目,game-workloadtradepost-workload 才能正常運作。

第一步是取得 item-generator 服務的外部 IP。在 Cloud Shell 中執行下列指令:

# The external IP is the 4th column of the output
kubectl get services | grep item-generator | awk '{print $4}'

指令輸出

{ITEMGENERATOR_EXTERNAL_IP}

接著開啟新的瀏覽器分頁,並指向 http://{ITEMGENERATOR_EXTERNAL_IP}:8089您應該會找到類似下方的頁面:

817307157d66c661.png

您將讓 usersspawn 保留預設值 1。在 host, 欄位中輸入 http://item。按一下進階選項,然後輸入執行時間:10s

設定應如下所示:

f3143165c6285c21.png

按一下「開始群戰」!

針對在 POST /items 端點發出的要求,系統會開始顯示統計資料。10 秒後將停止載入。

按一下 Charts,即可查看這些要求的成效圖表。

abad0a9f3c165345.png

現在,您要檢查資料是否已輸入 Spanner 資料庫。

方法很簡單,只要按一下漢堡選單,然後瀏覽至「Spanner」即可。在這個頁面上,前往 sample-instancesample-database。然後按一下「Query」。

我們要選取 game_items 的數量:

SELECT COUNT(*) FROM game_items;

結果底部會顯示結果。

137ce291a2ff2706.png

我們不需要大量的game_items種子。但現在玩家可以獲得這些獎勵了!

執行設定檔工作負載

完成 game_items種子後,下一步是將玩家註冊加入遊戲行列。

profile-workload 會使用 Locust 模擬玩家建立帳戶、登入、擷取設定檔資訊及登出的動作。在類似實際工作環境的一般工作負載中,所有這些測試都會測試 profile 後端服務的端點。

如要執行這個指令,請取得 profile-workload 外部 IP:

# The external IP is the 4th column of the output
kubectl get services | grep profile-workload | awk '{print $4}'

指令輸出

{PROFILEWORKLOAD_EXTERNAL_IP}

接著開啟新的瀏覽器分頁,並指向 http://{PROFILEWORKLOAD_EXTERNAL_IP}:8089您應該會找到與前一頁相似的 Locust 頁面。

在這種情況下,您將使用 http://profile 做為主機。您也不會在進階選項中指定執行階段。此外,請將 users 指定為 4,這樣就能一次模擬 4 個使用者要求。

profile-workload 測試應如下所示:

f6e0f06efb0ad6e.png

按一下「開始群戰」!

和之前一樣,畫面會顯示多個 profile REST 端點的統計資料。按一下滑鼠,即可檢視圖表來掌握整體成效。

4c2146e1cb3de23e.png

摘要

在這個步驟中,您已產生一些 game_items,接著使用 Cloud 控制台中的 Spanner Query UI 查詢 game_items 資料表。

此外,您也讓玩家註冊您的遊戲,並瞭解 Locust 如何針對後端服務建立類似實際工作環境的工作負載。

後續步驟

執行工作負載後,您可能會想確認 GKE 叢集和 Spanner 執行個體的運作情形。

8. 查看 GKE 和 Spanner 的用量

設定檔服務執行期間,您將有機會瞭解 GKE Autopilot 叢集和 Cloud Spanner 的運作情形。

檢查 GKE 叢集

前往 Kubernetes 叢集。請注意,您已部署工作負載和服務,因此叢集現在多了關於 vCPU 和記憶體總數的詳細資料。如果叢集中沒有任何工作負載,就無法取得這項資訊。

61d2d766c1f10079.png

接著,點選進入 sample-game-gke 叢集,並切換至「觀測能力」分頁:

fa9acc7e26ea04a.png

我們的工作負載和後端服務是在 default 上執行,因此 default Kubernetes 命名空間應已超出 CPU 使用率的 kube-system 命名空間。如果未顯示,請確認 profile workload 仍在執行,然後等待幾分鐘,讓圖表更新。

如要查看哪些工作負載佔用最多資源,請前往 Workloads 資訊主頁。

直接前往資訊主頁的「觀測能力」分頁,而非個別查看各項工作負載。您應該會看到 profileprofile-workload CPU 已增加。

f194b618969cfa9e.png

接著來看看 Cloud Spanner

查看 Cloud Spanner 執行個體

如要查看 Cloud Spanner 的效能,請前往 Spanner 並點選進入 sample-instance 執行個體和 sample-game 資料庫。

登入後,左選單會顯示「System Insights」分頁:

216212182a57dfd1.png

這裡有許多圖表可協助您瞭解 Spanner 執行個體的一般效能,包括 CPU utilizationtransaction latency and lockingquery throughput

除了系統深入分析外,您也可以瀏覽「觀測能力」部分中的其他連結,取得查詢工作負載的詳細資訊:

  • 查詢深入分析結果有助於找出使用 Spanner 資源中的前 N 項查詢。
  • 交易與鎖定深入分析有助於找出高延遲的交易。
  • Key Visualizer 能以視覺化方式呈現存取模式,有助於追蹤資料中的熱點。

摘要

在這個步驟中,您學到瞭如何檢查 GKE Autopilot 和 Spanner 的一些基本成效指標。

舉例來說,在執行設定檔工作負載時,請查詢 players 資料表,取得更多有關該資料表儲存資料的資訊。

後續步驟

接著就可以開始清理儲存空間了!

9. 清除所用資源

在清理之前,您可以探索未涵蓋的其他工作負載。特別是 matchmaking-workloadgame-workloadtradepost-workload

當你結束播放時就能清理遊樂場幸好這很簡單。

首先,如果您的 profile-workload 仍在瀏覽器中執行,請重新進行操作並停止執行:

13ae755a11f3228.png

針對您可能測試的每個工作負載執行同樣的步驟。

接著在 Cloud Shell 中前往「基礎架構」資料夾您將使用 terraform 來destroy基礎架構:

cd $DEMO_HOME/infrastructure
terraform destroy
# type 'yes' when asked

指令輸出

Plan: 0 to add, 0 to change, 46 to destroy.

Do you really want to destroy all resources?
  Terraform will destroy all your managed infrastructure, as shown above.
  There is no undo. Only 'yes' will be accepted to confirm.

  Enter a value: yes

*snip*

Destroy complete! Resources: 46 destroyed.

在 Cloud 控制台中前往 SpannerKubernetes ClusterArtifact RegistryCloud DeployIAM,確認所有資源已移除。

10. 恭喜!

恭喜!您已成功在 GKE Autopilot 上部署範例 golang 應用程式,並透過 Workload Identity 將這類應用程式連線至 Cloud Spanner!

還有一項好處,那就是您可以使用 Terraform 以重複方式輕鬆設定及移除這個基礎架構。

您可以進一步瞭解自己在本程式碼研究室中互動過的 Google Cloud 服務:

後續步驟

現在,您已大致瞭解 GKE Autopilot 和 Cloud Spanner 搭配運作的方式,不妨接著採取行動,開始建構能與這些服務搭配使用的應用程式。