1. Введение
Cloud Spanner – это полностью управляемый сервис реляционных баз данных с горизонтальным масштабированием и глобальным распределением, который обеспечивает транзакции ACID и семантику SQL без ущерба для производительности и высокой доступности.
GKE Autopilot – это режим работы в GKE, в котором Google управляет конфигурацией кластера, включая узлы, масштабирование, безопасность и другие предварительно настроенные параметры, в соответствии с рекомендациями. Например, GKE Autopilot позволяет Workload Identity управлять разрешениями сервиса.
В этой лабораторной работе вы узнаете, как подключить несколько бэкенд-служб, работающих в GKE Autopilot, к базе данных Cloud Spanner.

На этом практическом занятии вы сначала настроите проект и запустите Cloud Shell. Затем вы развернете инфраструктуру с помощью Terraform.
После этого вы будете взаимодействовать с Cloud Build и Cloud Deploy, чтобы выполнить первоначальный перенос схемы для базы данных Games, развернуть бэкенд-службы, а затем развернуть рабочие нагрузки.
В этой практической работе используются те же сервисы, что и в практической работе Начало разработки игр с помощью Cloud Spanner. Выполнять эту практическую работу необязательно, чтобы запустить сервисы в GKE и подключить их к Spanner. Но если вы хотите узнать больше о специфике этих сервисов, работающих на Spanner, ознакомьтесь с ним.
После запуска рабочих нагрузок и бэкенд-служб вы можете начать генерировать нагрузку и наблюдать за тем, как службы работают вместе.
В конце вы удалите ресурсы, созданные в ходе этой практической работы.
Что вы создадите
В этой практической работе вы:
- Подготовка инфраструктуры с помощью Terraform
- Создайте схему базы данных с помощью процесса Schema Migration в Cloud Build
- Развертывание четырех бэкенд-служб Golang, которые используют Workload Identity для подключения к Cloud Spanner
- Разверните четыре сервиса рабочих нагрузок, которые используются для симуляции нагрузки на серверные службы.
Что вы узнаете
- Как подготовить конвейеры GKE Autopilot, Cloud Spanner и Cloud Deploy с помощью Terraform
- Как Workload Identity позволяет сервисам в GKE выдавать себя за сервисные аккаунты, чтобы получать разрешения IAM для работы с Cloud Spanner
- Как сгенерировать нагрузку, похожую на производственную, в GKE и Cloud Spanner с помощью Locust.io.
Что вам понадобится
2. Настройка и требования
Как создать проект
Если у вас нет аккаунта Google (Gmail или Google Apps), создайте его. Войдите в консоль Google Cloud Platform (console.cloud.google.com) и создайте проект.
Если у вас уже есть проект, нажмите на раскрывающееся меню выбора проекта в левом верхнем углу консоли.

и нажмите кнопку Новый проект в появившемся диалоговом окне.

Если у вас ещё нет проекта, вы увидите диалоговое окно, в котором можно создать первый проект:

В открывшемся диалоговом окне укажите сведения о новом проекте:

Запомните идентификатор проекта. Он должен быть уникальным для всех проектов Google Cloud. Идентификатор, указанный выше, уже занят, поэтому вы не сможете его использовать. В этой практической работе он будет называться PROJECT_ID.
Затем, если вы ещё этого не сделали, вам нужно включить оплату в Developers Console, чтобы использовать ресурсы Google Cloud, и включить Cloud Spanner API.

Выполнение этой практической работы не должно стоить вам больше нескольких долларов, но может быть больше, если вы решите использовать больше ресурсов или оставите их работать (см. раздел "Очистка" в конце этого документа). Цены на Google Cloud Spanner приведены здесь, а на GKE Autopilot – здесь.
Новые пользователи Google Cloud Platform могут получить 300 долларов США на бесплатный пробный период, что позволит выполнить эту практическую работу бесплатно.
Настройка Cloud Shell
Хотя Google Cloud и Spanner можно управлять удаленно с ноутбука, в этой практической работе мы будем использовать Google Cloud Shell – среду командной строки, работающую в облаке.
На этой виртуальной машине на базе Debian установлены все необходимые инструменты разработки. Она предлагает постоянный домашний каталог объемом 5 ГБ и работает в Google Cloud, что значительно повышает производительность сети и аутентификацию. Это значит, что для выполнения практической работы вам понадобится только браузер (да, это работает на Chromebook).
- Чтобы активировать Cloud Shell в Cloud Console, нажмите "Активировать 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? Проверьте, какой идентификатор вы использовали при настройке, или найдите его на панели управления Cloud Console:

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. Инициализация инфраструктуры
Обзор
Когда проект готов, можно запускать инфраструктуру. Это включает в себя сеть VPC, 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, скопировав terraform.tfvars.sample и изменив значение проекта. Другие переменные также можно изменить, но для работы с вашей средой необходимо изменить только проект.
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 Console.
Cloud Spanner
Сначала проверьте Cloud Spanner. Для этого откройте меню в виде трех полосок и нажмите Spanner. Возможно, вам потребуется нажать "Показать больше товаров", чтобы найти его в списке.
Откроется список экземпляров Spanner. Нажмите на экземпляр, чтобы увидеть базы данных. Он выглядит примерно так:

GKE Autopilot
Теперь перейдите в GKE. Для этого откройте меню в виде трех полосок и нажмите Kubernetes Engine => Clusters. Вы увидите кластер sample-games-gke, работающий в режиме Autopilot.

Artifact Registry
Теперь вы хотите посмотреть, где будут храниться изображения. Нажмите на меню в виде трех полосок и выберите Artifact Registry=>Repositories. Artifact Registry находится в разделе CI/CD меню.
Вы увидите реестр Docker с названием spanner-game-images. Пока оно будет пустым.

Cloud Deploy
В Cloud Deploy создаются конвейеры, чтобы Cloud Build мог предоставить шаги для создания образов и их развертывания в кластере GKE.
Откройте меню в виде трех полосок и найдите Cloud Deploy в разделе CI/CD.
Здесь вы увидите два конвейера: один для бэкенд-служб, а другой для рабочих нагрузок. Оба развертывают образы в одном кластере GKE, но это позволяет разделить развертывания.

IAM
Наконец, проверьте созданные сервисные аккаунты на странице IAM в Cloud Console. Откройте меню в виде трех горизонтальных полосок и найдите IAM and Admin=>Service accounts. Он выглядит примерно так:

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 в VPC для частной сети.
Кроме того, для бэкенд-служб и рабочих нагрузок были созданы два конвейера Cloud Deploy, а также хранилище Artifact Registry для хранения созданных образов.
И наконец, были созданы и настроены сервисные аккаунты для работы с Workload Identity, чтобы бэкенд-службы могли использовать Cloud Spanner.
Вы также настроили kubectl для взаимодействия с кластером GKE в Cloud Shell после развертывания бэкенд-служб и рабочих нагрузок.
Далее
Чтобы использовать сервисы, необходимо определить схему базы данных. Вы настроите это на следующем этапе.
4. Создайте схему базы данных
Обзор
Прежде чем запускать серверные службы, необходимо убедиться, что схема базы данных на месте.
Если вы посмотрите на файлы в каталоге $DEMO_HOME/schema/migrations из демонстрационного репозитория, то увидите серию файлов .sql, которые определяют нашу схему. Это имитирует цикл разработки, в котором изменения схемы отслеживаются в самом репозитории и могут быть привязаны к определенным функциям приложений.
В этой тестовой среде wrench – это инструмент, который будет применять перенос схемы с помощью 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
Для этого нужно выполнить два действия:
- скачать wrench в рабочую область Cloud Build;
- запустить перенос Wrench
Для подключения Wrench к конечной точке записи необходимы переменные среды проекта, экземпляра и базы данных Spanner.
Cloud Build может вносить эти изменения, поскольку он работает как сервисный аккаунт cloudbuild-cicd@${PROJECT_ID}.iam.gserviceaccount.com:
serviceAccount: projects/${PROJECT_ID}/serviceAccounts/cloudbuild-cicd@${PROJECT_ID}.iam.gserviceaccount.com
А у этого сервисного аккаунта есть роль spanner.databaseUser, добавленная Terraform, которая позволяет сервисному аккаунту обновлять DDL.
Перенос схем
Перенос выполняется в пять этапов на основе файлов в каталоге $DEMO_HOME/schema/migrations. Ниже приведен пример файла 000001.sql, который создает таблицу players и индексы.
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 Console, где сможете отслеживать ход выполнения и видеть, что происходит.

Сводка
На этом шаге вы использовали Cloud Build для отправки начальной миграции схемы, которая применила 5 различных операций DDL. Эти операции представляют собой добавление функций, для которых требовалось изменить схему базы данных.
В обычном сценарии разработки вы бы хотели сделать изменения схемы обратно совместимыми с текущим приложением, чтобы избежать сбоев.
Если изменения несовместимы с предыдущими версиями, развертывайте их в приложении и схеме поэтапно, чтобы избежать сбоев.
Далее
После создания схемы следующим шагом будет развертывание серверных служб!
5. Развертывание бэкенд-служб
Обзор
В этой практической работе используются четыре бэкенд-службы REST API на языке Go:
- Профиль. Позволяет игрокам регистрироваться и проходить аутентификацию в нашей примерной игре.
- Подбор игроков. Взаимодействие с данными игроков для подбора соперников, отслеживание информации о созданных играх и обновление статистики игроков после завершения игр.
- Предметы. Игроки могут получать предметы и деньги в процессе игры.
- Торговый пост. Позвольте игрокам покупать и продавать предметы на торговом посту.

Узнать больше об этих сервисах можно в практической работе Начало разработки игр с помощью Cloud Spanner. В нашем случае мы хотим, чтобы эти сервисы работали в кластере GKE Autopilot.
У этих сервисов должна быть возможность изменять данные Spanner. Для этого у каждого сервиса есть сервисный аккаунт, который предоставляет им роль databaseUser.
Workload Identity позволяет сервисному аккаунту Kubernetes выдавать себя за сервисный аккаунт Google Cloud, выполнив следующие действия в Terraform:
- Создайте ресурс сервисного аккаунта Google Cloud (
GSA). - Назначьте этому сервисному аккаунту роль databaseUser.
- Назначьте этому сервисному аккаунту роль workloadIdentityUser.
- Создайте сервисный аккаунт Kubernetes (
KSA), который ссылается на сервисный аккаунт Google.
Примерная схема выглядит так:

Terraform создал для вас сервисные аккаунты и сервисные аккаунты Kubernetes. Проверить сервисные аккаунты 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каждого сервиса. Файл развертывания сервиса содержит информацию для создания сервиса, в данном случае это clusterIP, работающий на порту 80.
Тип ClusterIP не позволяет подам бэкенд-службы иметь внешний 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. Рассмотрим раздел развертывания службы 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
Далее мы видим, какой сервисный аккаунт должен запускать приложение и какой образ он должен использовать. Они соответствуют сервисному аккаунту Kubernetes, созданному из Terraform, и образу, созданному на этапе 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_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 Console. Посмотрите на них.
Получив уведомление об успешном завершении от Cloud Build, перейдите в Cloud Deploy, а затем в конвейер sample-game-services, чтобы отслеживать ход развертывания.

После развертывания сервисов вы можете проверить статус подов в kubectl:
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
Вы также можете перейти в интерфейс GKE в Cloud Console, чтобы посмотреть Workloads, Services и ConfigMaps.
Рабочие нагрузки

Сервисы

Объекты ConfigMap


Сводка
На этом шаге вы развернули четыре бэкенд-службы в GKE Autopilot. Вы смогли запустить шаг Cloud Build и проверить ход выполнения в Cloud Deploy и Kubernetes в Cloud Console.
Вы также узнали, как эти сервисы используют Workload Identity, чтобы выдать себя за сервисный аккаунт, у которого есть нужные разрешения на чтение и запись данных в базе данных Spanner.
Дальнейшие действия
В следующем разделе вы развернете рабочие нагрузки.
6. Развертывание рабочих нагрузок
Обзор
Теперь, когда в кластере запущены бэкенд-службы, вы развернете рабочие нагрузки.

Рабочие нагрузки доступны извне. В рамках этой практической работы для каждой бэкенд-службы предусмотрена одна рабочая нагрузка.
Эти рабочие нагрузки представляют собой скрипты генерации нагрузки на основе 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
В верхней части раздела развертывания находятся метаданные о рабочей нагрузке. В этом случае развертывается только одна реплика:
replicas: 1
Однако спецификация контейнера отличается. Во-первых, мы используем сервисный аккаунт Kubernetes default. У этого аккаунта нет особых привилегий, поскольку рабочей нагрузке не нужно подключаться к ресурсам Google Cloud, кроме бэкенд-служб, работающих в кластере GKE.
Ещё одно отличие заключается в том, что для этих рабочих нагрузок не требуются переменные среды. В результате спецификация развертывания становится короче.
spec:
serviceAccountName: default
containers:
- name: matchmaking-workload
image: matchmaking-workload
ports:
- containerPort: 8089
Настройки ресурсов аналогичны настройкам бэкенд-служб. Помните, что именно так GKE Autopilot узнает, сколько ресурсов необходимо для удовлетворения запросов всех подов, работающих в кластере.
Разверните рабочие нагрузки.
Развертывание рабочих нагрузок
Как и раньше, вы можете отправить запрос на сборку с помощью командной строки 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 Build и конвейер Cloud Deploy в Cloud Console, чтобы узнать статус. Для рабочих нагрузок конвейер Cloud Deploy – sample-game-workloads:
После завершения развертывания проверьте статус с помощью kubectl в Cloud Shell:
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, и они доступны извне через порт 8089 с помощью сервиса LoadBalancer.
Дальнейшие действия
Когда серверные службы и рабочие нагрузки запущены, можно "играть" в игру.
7. Начните играть.
Обзор
Теперь у вас есть работающие бэкенд-службы для примера игры и возможность генерировать игроков, взаимодействующих с этими службами, с помощью рабочих нагрузок.
Для каждой рабочей нагрузки используется Locust, чтобы симулировать фактическую нагрузку на API сервиса. На этом шаге вы запустите несколько рабочих нагрузок, чтобы создать нагрузку на кластер GKE и Spanner, а также сохранить данные в Spanner.
Ниже приведено описание каждой рабочей нагрузки.
- Рабочая нагрузка
item-generatorпозволяет быстро создать список игровых предметов (game_items), которые игроки могут получить в процессе игры. profile-workloadимитирует регистрацию и вход игроков.matchmaking-workloadимитирует очередь игроков, ожидающих назначения в игры.game-workloadимитирует получение игроками предметов и денег в процессе игры.tradepost-workloadимитирует покупку и продажу предметов на торговом посту.
В этой практической работе мы рассмотрим запуск item-generator и profile-workload.
Запустите генератор объектов.
item-generator использует конечную точку бэкенд-службы item, чтобы добавить game_items в Spanner. Эти элементы необходимы для правильной работы game-workload и tradepost-workload.
Сначала нужно получить внешний IP-адрес сервиса item-generator. В 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 в поле "Продолжительность".
Вот как должна выглядеть конфигурация:

Нажмите "Начать роение".
Для запросов, отправляемых в конечную точку 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 в типичной рабочей нагрузке, похожей на производственную.
Чтобы запустить его, получите внешний IP-адрес profile-workload:
# 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. Это позволит симулировать четыре пользовательских запроса одновременно.
Тест profile-workload должен выглядеть следующим образом:

Нажмите "Начать роение".
Как и раньше, вы увидите статистику по различным конечным точкам REST API profile. Нажмите на диаграммы, чтобы посмотреть, насколько хорошо все работает.

Сводка
На этом шаге вы сгенерировали game_items данные в таблице game_items, а затем запросили их с помощью интерфейса Spanner Query в Cloud Console.
Вы также разрешили игрокам регистрироваться в игре и увидели, как Locust может создавать рабочие нагрузки, подобные производственным, для ваших серверных служб.
Дальнейшие действия
После запуска рабочих нагрузок вы захотите проверить, как ведут себя кластер GKE и экземпляр Spanner.
8. Проверьте использование GKE и Spanner
Теперь, когда сервис профилей запущен, вы можете посмотреть, как работают кластер GKE Autopilot и Cloud Spanner.
Проверьте кластер GKE
Перейдите к кластеру Kubernetes. Обратите внимание, что после развертывания рабочих нагрузок и сервисов в кластере появились сведения об общем количестве виртуальных процессоров и объеме памяти. Эта информация была недоступна, когда в кластере не было рабочих нагрузок.

Теперь нажмите на кластер sample-game-gke и перейдите на вкладку Observability (Наблюдаемость).

Пространство имен Kubernetes default должно было превзойти пространство имен kube-system по загрузке ЦП, поскольку наши рабочие нагрузки и бэкенд-службы выполняются в default. Если этого не произошло, убедитесь, что profile workload все ещё работает, и подождите несколько минут, пока диаграммы не обновятся.
Чтобы узнать, какие рабочие нагрузки потребляют больше всего ресурсов, перейдите на панель управления Workloads.
Вместо того чтобы проверять каждую рабочую нагрузку по отдельности, перейдите на вкладку Observability (Наблюдаемость) на панели управления. Вы должны увидеть, что загрузка ЦП profile и profile-workload увеличилась.

Теперь проверьте Cloud Spanner.
Проверьте экземпляр Cloud Spanner
Чтобы проверить производительность Cloud Spanner, перейдите в Spanner и нажмите на экземпляр sample-instance и базу данных sample-game.
В меню слева вы увидите вкладку Статистика системы.

Здесь есть много диаграмм, которые помогут вам понять общую производительность вашего экземпляра Spanner, включая CPU utilization, transaction latency and locking и query throughput.
Помимо System Insights, вы можете получить более подробную информацию о рабочей нагрузке запросов, перейдя по другим ссылкам в разделе Observability:
- Статистика запросов помогает определить, какие запросы используют больше всего ресурсов Spanner.
- Статистика Транзакции и блокировки помогает выявлять транзакции с высокой задержкой.
- Key Visualizer помогает визуализировать шаблоны доступа и отслеживать горячие точки в данных.
Сводка
На этом шаге вы узнали, как проверить некоторые базовые показатели эффективности для GKE Autopilot и Spanner.
Например, пока выполняется рабочая нагрузка профиля, запросите таблицу players, чтобы получить больше информации о хранящихся в ней данных.
Дальнейшие действия
Теперь пора навести порядок.
9. Очистка
Прежде чем удалять ресурсы, вы можете изучить другие рабочие нагрузки, которые не рассматривались в этом руководстве. В частности, matchmaking-workload, game-workload и tradepost-workload.
Когда вы закончите "играть", вы можете очистить игровую площадку. К счастью, это довольно просто.
Если profile-workload все ещё работает в браузере, остановите его:

Повторите эти действия для всех рабочих нагрузок, которые вы тестировали.
Затем в Cloud Shell перейдите в папку infrastructure. Вы destroy инфраструктуру с помощью Terraform:
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 Console перейдите в разделы Spanner, Kubernetes Cluster, Artifact Registry, Cloud Deploy и IAM, чтобы убедиться, что все ресурсы удалены.
10. Поздравляем!
Поздравляем! Вы успешно развернули примеры приложений на Golang в GKE Autopilot и подключили их к Cloud Spanner с помощью Workload Identity.
Кроме того, эту инфраструктуру можно было легко настраивать и удалять с помощью Terraform.
Вы можете узнать больше о сервисах Google Cloud, с которыми вы взаимодействовали в этой практической работе:
Что дальше?
Теперь, когда вы знаете, как GKE Autopilot и Cloud Spanner могут работать вместе, почему бы не сделать следующий шаг и не начать создавать собственное приложение для работы с этими сервисами?
