1. はじめに
Cloud Spanner は、水平スケーリングが可能なフルマネージドでグローバルに分散されたリレーショナル データベース サービスで、パフォーマンスと高可用性を犠牲にすることなく ACID トランザクションと SQL セマンティクスを提供します。
GKE Autopilot は GKE の運用モードの一つで、ノード、スケーリング、セキュリティ、ベスト プラクティスに沿ったその他の事前構成された設定などのクラスタ構成を Google が管理します。たとえば、GKE Autopilot を使用すると、Workload Identity でサービスの権限を管理できます。
このラボの目標は、GKE Autopilot で実行されている複数のバックエンド サービスを Cloud Spanner データベースに接続するプロセスについて説明することです。
このラボでは、まずプロジェクトを設定して Cloud Shell を起動します。その後、Terraform を使用してインフラストラクチャをデプロイします。
完了したら、Cloud Build と Cloud Deploy を操作してゲーム データベースの初期スキーマ移行を実行し、バックエンド サービスをデプロイしてからワークロードをデプロイします。
この Codelab のサービスは、Cloud Spanner のゲーム開発のスタートガイド Codelab のものと同じです。GKE でサービスを実行して Spanner に接続するために、この Codelab を完了する必要はありません。Spanner で動作するこれらのサービスの詳細について関心をお持ちの場合は、
ワークロードとバックエンド サービスが実行されている状態で、負荷の生成を開始して、サービスが連携する様子を観察できます。
最後に、このラボで作成したリソースをクリーンアップします。
作成するアプリの概要
このラボでは、次の作業を行います。
- Terraform を使用してインフラストラクチャをプロビジョニングする
- Cloud Build でスキーマ移行プロセスを使用してデータベース スキーマを作成する
- Workload Identity を利用して Cloud Spanner に接続する 4 つの Golang バックエンド サービスをデプロイする
- バックエンド サービスの負荷のシミュレーションに使用する 4 つのワークロード サービスをデプロイします。
学習内容
- Terraform を使用して GKE Autopilot、Cloud Spanner、Cloud Deploy パイプラインをプロビジョニングする方法
- Workload Identity を使用して、GKE 上のサービスがサービス アカウントの権限を借用し、Cloud Spanner を操作するための IAM 権限にアクセスする仕組み
- Locust.io を使用して GKE と Cloud Spanner で本番環境と同様の負荷を生成する方法
必要なもの
2. 設定と要件
プロジェクトを作成する
Google アカウント(Gmail または Google Apps)をお持ちでない場合は、1 つ作成する必要があります。Google Cloud Platform コンソール(console.cloud.google.com)にログインし、新しいプロジェクトを作成します。
すでにプロジェクトが存在する場合は、コンソールの左上にあるプロジェクト選択プルダウン メニューをクリックします。
[新しいプロジェクト] をクリックします。] ボタンをクリックし、新しいプロジェクトを作成します。
まだプロジェクトが存在しない場合は、次のような最初のプロジェクトを作成するためのダイアログが表示されます。
続いて表示されるプロジェクト作成ダイアログでは、新しいプロジェクトの詳細を入力できます。
プロジェクト ID を忘れないようにしてください。プロジェクト ID は、すべての Google Cloud プロジェクトを通じて一意の名前にする必要があります(上記の名前はすでに使用されているため使用できません)。以降、この Codelab では PROJECT_ID
と表します。
次に、Google Cloud リソースを使用し、Cloud Spanner API を有効にするために、Developers Console で課金を有効にする必要があります。
この Codelab をすべて実行しても費用はかかりませんが、より多くのリソースを使用する場合や実行したままにする場合は、コストが高くなる可能性があります(このドキュメントの最後にある「クリーンアップ」セクションをご覧ください)。Google Cloud Spanner の料金についてはこちらを、GKE Autopilot についてはこちらをご覧ください。
Google Cloud Platform の新規ユーザーの皆さんには、$300 の無料トライアルをご利用いただけます。その場合は、この Codelab を完全に無料でご利用いただけます。
Cloud Shell の設定
Google Cloud と Spanner はノートパソコンからリモートで操作でき、この Codelab では、Google Cloud Shell(Cloud 上で動作するコマンドライン環境)を使用します。
この Debian ベースの仮想マシンには、必要な開発ツールがすべて揃っています。永続的なホーム ディレクトリが 5 GB 用意されており、Google Cloud で稼働するため、ネットワークのパフォーマンスと認証が大幅に向上しています。つまり、この Codelab に必要なのはブラウザだけです(はい、Chromebook で動作します)。
- Cloud コンソールから Cloud Shell を有効にするには、「Cloud Shell をアクティブにする」アイコン をクリックします(環境のプロビジョニングと接続には少し時間がかかります)。
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 コンソール ダッシュボードで調べます。
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*
この Codelab は 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 環境変数として設定します。これにより、Codelab のさまざまな部分に取り組むための移動が容易になります。
export DEMO_HOME=$(pwd)
概要
このステップでは、新しいプロジェクトを設定し、Cloud Shell をアクティブにして、このラボのコードをダウンロードしました。
次のステップ
次に、Terraform を使用してインフラストラクチャをプロビジョニングします。
3. インフラストラクチャのプロビジョニング
概要
プロジェクトの準備ができたら、インフラストラクチャを稼働させます。これには、VPC ネットワーキング、Cloud Spanner、GKE Autopilot、GKE で実行するイメージを保存する Artifact Registry、バックエンド サービスとワークロード用の Cloud Deploy パイプライン、これらのサービスを使用するためのサービス アカウントと IAM 権限が含まれます。
その数は膨大です。幸いなことに、Terraform を使用すれば簡単に設定できます。Terraform は「Infrastructure as Code」このツールを使うと、このプロジェクトに必要なものを一連の「.tf」ファイルにできます。これにより、インフラストラクチャのプロビジョニングがシンプルになります。
Terraform に精通していることは、この Codelab を完了するための要件ではありません。以降のステップで何が行われているかを確認する場合は、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 インスタンスのリストが表示されます。インスタンスをクリックすると、データベースが表示されます。次のようになります。
GKE Autopilot
次に、ハンバーガー メニューに移動して Kubernetes Engine => Clusters
をクリックして、GKE を確認します。ここでは、sample-games-gke
クラスタが Autopilot モードで実行されていることがわかります。
Artifact Registry
次に、画像が保存される場所を確認します。ハンバーガー メニューをクリックして Artifact Registry=>Repositories
を探します。Artifact Registry はメニューの [CI/CD] セクションにあります。
spanner-game-images
という名前の Docker レジストリが表示されます。今は空です。
Cloud Deploy
Cloud Deploy は、イメージをビルドして GKE クラスタにデプロイするステップを Cloud Build が提供できるようにパイプラインが作成された場所です。
ハンバーガー メニューに移動し、Cloud Deploy
を見つけます。これは、メニューの [CI/CD] セクションにもあります。
ここには 2 つのパイプラインがあります。1 つはバックエンド サービス用、もう 1 つはワークロード用です。どちらも同じ GKE クラスタにイメージをデプロイしますが、これによってデプロイを分離できます。
IAM
最後に、Cloud コンソールの [IAM] ページで、作成されたサービス アカウントを確認します。ハンバーガー メニューに移動して、IAM and Admin=>Service accounts
を見つけます。次のようになります。
Terraform によって作成されるサービス アカウントは合計で 6 つあります。
- デフォルトのコンピュータ サービス アカウント。これは、この Codelab では使用しません。
- cloudbuild-cicd アカウントは、Cloud Build と Cloud Deploy のステップで使用されます。
- 4 つの「アプリ」バックエンド サービスが Cloud Spanner とやり取りするために使用するアカウント。
次に、GKE クラスタとやり取りするように kubectl
を構成します。
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 クラスタをすべて VPC にプロビジョニングすることができました。
さらに、バックエンド サービスとワークロード用に 2 つの Cloud Deploy パイプラインと、ビルドされたイメージを保存する Artifact Registry リポジトリが作成されました。
最後に、Workload Identity と連携するようにサービス アカウントを作成して構成し、バックエンド サービスが Cloud Spanner を使用できるようにしました。
また、バックエンド サービスとワークロードをデプロイした後、Cloud Shell で GKE クラスタを操作するように kubectl
が構成されています。
次のステップ
サービスを使用する前に、データベース スキーマを定義する必要があります。次はこれを設定します。
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
基本的には、次の 2 つのステップがあります。
- 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
ロールがあるため、サービス アカウントで DDL をアップデートできます。
スキーマの移行
$DEMO_HOME/schema/migrations
ディレクトリのファイルに基づいて実行される 5 つの移行手順があります。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 Build プロセスへのリンクが含まれています。これをクリックすると、Cloud コンソールのビルドが表示され、ビルドの進捗状況をモニタリングして状況を確認できます。
概要
このステップでは、Cloud Build を使用して、5 つの異なる DDL オペレーションを適用した最初のスキーマ移行を送信しました。これらのオペレーションは、データベース スキーマの変更を必要とする特徴がいつ追加されたかを表します。
通常の開発シナリオでは、サービス停止を避けるために、現在のアプリケーションと下位互換性のあるスキーマ変更を行います。
下位互換性のない変更については、アプリケーションとスキーマへの変更を段階的にデプロイして、サービス停止を防ぐことをおすすめします。
次のステップ
スキーマを配置したら、次はバックエンド サービスをデプロイします。
5. バックエンド サービスをデプロイする
概要
この Codelab のバックエンド サービスは、次の 4 種類のサービスを表す golang REST API です。
- プロフィール: サンプルの「ゲーム」に登録して認証する機能をプレーヤーに提供します。
- マッチメイキング: プレーヤーのデータを操作してマッチメイキング機能を支援し、作成されたゲームに関する情報を追跡し、ゲームが終了したときにプレーヤーの統計情報を更新します。
- アイテム: プレーヤーがゲームのプレイ中にゲームのアイテムとお金を獲得できるようにします。
- Tradepost: プレーヤーがトレードポストでアイテムを売買できます
これらのサービスについて詳しくは、Cloud Spanner でゲーム開発を始めるの Codelab をご覧ください。ここでの目的上、これらのサービスを GKE Autopilot クラスタで実行する必要があります。
これらのサービスは Spanner データを変更できる必要があります。そのために、各サービスに「databaseUser」というサービス アカウントをなります。
Workload Identity を使用すると、Kubernetes サービス アカウントがサービスの権限をGoogle Cloud サービス アカウントを作成する必要があります。
- サービスの Google Cloud サービス アカウント(
GSA
)リソースを作成する - そのサービス アカウントに databaseUser ロールを割り当てます。
- そのサービス アカウントに workloadIdentityUser ロールを割り当てる。
- GSA を参照する Kubernetes サービス アカウント(
KSA
)を作成します
大まかな図は次のようになります。
サービス アカウントと Kubernetes サービス アカウントは Terraform によって作成されました。Kubernetes サービス アカウントは、kubectl
を使用して確認できます。
# 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
ビルドの仕組みは次のとおりです。
- Terraform により、次のような
$DEMO_HOME/backend_services/cloudbuild.yaml
ファイルが生成されます。
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
ファイルの定義に従います。Service のデプロイ ファイルには、Service を作成するための情報が含まれています。この場合は、ポート 80 で実行されている clusterIP です。
<ph type="x-smartling-placeholder"></ph>"ClusterIP" タイプは、バックエンド サービス Pod が外部 IP を持つことがなくなるため、内部 GKE ネットワークに接続できるエンティティのみがバックエンド サービスにアクセスできます。プレーヤーは、Spanner データにアクセスして変更するため、これらのサービスにはプレーヤーが直接アクセスできるようにすべきではありません。
apiVersion: v1
kind: Service
metadata:
name: profile
spec:
type: ClusterIP
selector:
app: profile
ports:
- port: 80
targetPort: 80
Cloud Deploy は、Kubernetes Service を作成するだけでなく、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"
上部には、サービスに関するメタデータが表示されます。ここで最も重要なのは、この Deployment によって作成されるレプリカの数を定義することです。
replicas: 2 # EDIT: Number of instances of deployment
次に、アプリを実行するサービス アカウントと使用するイメージを確認します。これらは、Terraform から作成された Kubernetes サービス アカウントと、Cloud Build ステップで作成されたイメージと一致します。
spec:
serviceAccountName: profile-app
containers:
- name: profile-service
image: profile
その後、ネットワーキングと環境変数に関する情報を指定します。
spanner_config
は、アプリケーションが Spanner に接続するために必要なプロジェクト、インスタンス、データベースの情報を指定する Kubernetes ConfigMap です。
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_HOST
と SERVICE_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
パイプラインに移動し、デプロイの進行状況をモニタリングします。
Service がデプロイされたら、kubectl
で Pod のstatus:
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 に移動して、Workloads
、Services
、ConfigMaps
を表示することもできます。
ワークロード
サービス
ConfigMap
概要
このステップでは、4 つのバックエンド サービスを GKE Autopilot にデプロイしました。Cloud Build のステップを実行し、Cloud Deploy と Kubernetes の Cloud コンソールから進行状況を確認できました。
また、これらのサービスが Workload Identity を利用して、Spanner データベースに対してデータの読み取りと書き込みを行うための適切な権限を持つサービス アカウントの権限を借用する方法についても学びました。
次のステップ
次のセクションでは、ワークロードをデプロイします。
6. ワークロードをデプロイする
概要
バックエンド サービスがクラスタで実行されるようになったので、ワークロードをデプロイします。
ワークロードには外部からアクセスでき、この Codelab の目的上、バックエンド サービスごとにワークロードが 1 つあります。
これらのワークロードは、これらのサンプル サービスで想定される実際のアクセス パターンを模倣した、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 セクションの一番上には、ワークロードに関するメタデータが表示されます。この例では、レプリカは 1 つだけデプロイされます。
replicas: 1
ただし、コンテナの仕様は異なります。たとえば、Kubernetes サービス アカウントとして default
を使用しています。ワークロードは GKE クラスタで実行されているバックエンド サービス以外の Google Cloud リソースに接続する必要はないため、このアカウントには特別な権限はありません。
もう一つの違いは、これらのワークロードには環境変数が必要ないことです。その結果、デプロイの仕様が短くなります。
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 を使用して、Google のサービス API に対する実際の負荷をシミュレートします。このステップでは、いくつかのワークロードを実行して GKE クラスタと Spanner で負荷を発生させ、Spanner にデータを保存します。
各ワークロードの説明は次のとおりです。
item-generator
ワークロードは、プレーヤーが「プレイ中」の過程で獲得できる game_items のリストを生成する簡単なワークロードです。できます。profile-workload
は、プレーヤーの登録とログインをシミュレートします。matchmaking-workload
は、プレーヤーがゲームに割り当てられるためにキューに入れられる状態をシミュレートします。game-workload
は、プレーヤーがゲームのプレイ中に game_items とお金を獲得する行為をシミュレートします。tradepost-workload
は、プレーヤーが取引ポストでアイテムを売買できる状態をシミュレートします。
この Codelab では、特に item-generator
と profile-workload
の実行について説明します。
アイテム生成ツールを実行する
item-generator
は、item
バックエンド サービス エンドポイントを使用して、game_items
を Spanner に追加します。これらの項目は、game-workload
と tradepost-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
を指定します。次のようなページが表示されます。
users
と spawn
はデフォルトの 1 のままにします。host
, に「http://item
」と入力します。詳細オプションをクリックし、実行時間に「10s
」と入力します。
構成は次のようになります。
「Start swarming」をクリック!
POST /items
エンドポイントで発行されているリクエストの統計情報の表示が開始されます。10 秒後に読み込みが停止します。
Charts
をクリックすると、これらのリクエストのパフォーマンスに関するグラフがいくつか表示されます。
ここで、データが Spanner データベースに入力されているかどうかを確認します。
そのためには、ハンバーガー メニューをクリックして [Spanner] に移動します。このページから、sample-instance
と sample-database
に移動します。[Query
] をクリックします。
game_items
の数を選択します。:
SELECT COUNT(*) FROM game_items;
下部に結果が表示されます。
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
テストは次のようになります。
「Start swarming」をクリック!
以前と同様に、さまざまな profile
REST エンドポイントの統計情報が表示されるようになります。グラフをクリックすると、すべてのパフォーマンスが表示されます。
概要
このステップでは、game_items
を生成し、Cloud コンソールの Spanner クエリ UI を使用して game_items
テーブルに対してクエリを実行しました。
また、プレーヤーがゲームに登録できるようにして、Locust がバックエンド サービスに対して本番環境と同様のワークロードを作成する方法を確認しました。
次のステップ
ワークロードを実行したら、GKE クラスタと Spanner インスタンスの動作を確認します。
8. GKE と Spanner の使用状況を確認する
プロファイル サービスを実行したところで、今度は GKE Autopilot クラスタと Cloud Spanner の動作を確認します。
GKE クラスタを確認する
Kubernetes クラスタに移動します。ワークロードとサービスをデプロイしたため、vCPU とメモリの合計に関する詳細がクラスタに追加されています。クラスタにワークロードがない場合、この情報は利用できませんでした。
次に、sample-game-gke
クラスタをクリックして、[オブザーバビリティ] タブに切り替えます。
ワークロードとバックエンド サービスは default
で実行されるため、default
Kubernetes Namespace の CPU 使用率は kube-system
Namespace を超えているはずです。更新されていない場合は、profile workload
が引き続き実行されていることを確認し、グラフが更新されるまで数分待ちます。
どのワークロードが最もリソースを消費しているかを確認するには、Workloads
ダッシュボードに移動します。
各ワークロードを個別に確認するのではなく、ダッシュボードの [オブザーバビリティ] タブに移動します。profile
と profile-workload
の CPU が増加したことがわかります。
では、Cloud Spanner を確認しましょう。
Cloud Spanner インスタンスを確認する
Cloud Spanner のパフォーマンスを確認するには、Spanner に移動し、sample-instance
インスタンスと sample-game
データベースをクリックします。
左側のメニューに [システム分析情報] タブが表示されます。
Spanner インスタンスの全般的なパフォーマンスの把握に役立つグラフは、CPU utilization
、transaction latency and locking
、query throughput
など多数あります。
システム分析情報に加えて、[オブザーバビリティ] セクションの他のリンクを調べると、クエリ ワークロードに関する詳細情報を取得できます。
- Query Insights は、Spanner のリソースを使用している上位 N 個のクエリを特定するのに役立ちます。
- トランザクションとロックの分析情報は、レイテンシの高いトランザクションの特定に役立ちます。
- Key Visualizer でアクセス パターンを可視化し、データ内のホットスポットを特定できます。
概要
このステップでは、GKE Autopilot と Spanner の基本的なパフォーマンス指標を確認する方法を学習しました。
たとえば、プロファイル ワークロードが実行されている状態で、players テーブルに対してクエリを実行し、テーブルに保存されているデータに関する詳細情報を取得します。
次のステップ
次はクリーンアップです。
9. クリーンアップ
クリーンアップを行う前に、取り上げられていない他のワークロードを自由に確認してください。具体的には matchmaking-workload
、 game-workload
、tradepost-workload
です。
「プレイ」が終わったらプレイグラウンドをきれいにすることができます。これはとても簡単です。
まず、ブラウザで profile-workload
がまだ実行中の場合は、それを実行して停止します。
テストしたワークロードごとに、同じことを行います。
次に、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 コンソールで、Spanner
、Kubernetes Cluster
、Artifact Registry
、Cloud Deploy
、IAM
に移動して、すべてのリソースが削除されたことを確認します。
10. 完了
これで、サンプルの golang アプリケーションを GKE Autopilot にデプロイし、Workload Identity を使用して Cloud Spanner に接続できました。
さらに、このインフラストラクチャは Terraform を使用して繰り返し可能な方法で簡単に設定、削除できました。
この Codelab で操作した Google Cloud サービスの詳細を確認できます。
次のステップ
GKE Autopilot と Cloud Spanner がどのように連携するのかについて基本をご理解いただけたと思います。次は、これらのサービスと連携する独自のアプリケーションを構築してみましょう。