Подключение Cloud Spanner к автопилоту GKE

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, чтобы выполнить первоначальную миграцию схемы для базы данных Games, развернуть серверные службы, а затем развернуть рабочие нагрузки.

Службы в этой лаборатории кода такие же, как и в лаборатории кода Cloud Spanner «Начало работы с разработкой игр» . Прохождение этой лаборатории кода не является обязательным условием для запуска служб на GKE и подключения к Spanner. Но если вас интересует более подробная информация о специфике тех сервисов, которые работают на Spanner, загляните сюда.

Когда рабочие нагрузки и серверные службы запущены, вы можете начать генерировать нагрузку и наблюдать, как службы работают вместе.

Наконец, вы очистите ресурсы, созданные в этой лабораторной работе.

Что ты построишь

В рамках этой лабораторной работы вы:

  • Предоставление инфраструктуры с использованием Terraform
  • Создайте схему базы данных с помощью процесса миграции схемы в 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

Что вам понадобится

  • Проект Google Cloud, подключенный к платежному аккаунту.
  • Веб-браузер, например Chrome или Firefox .

2. Настройка и требования

Создать проект

Если у вас еще нет учетной записи Google (Gmail или Google Apps), вам необходимо ее создать . Войдите в консоль Google Cloud Platform ( console.cloud.google.com ) и создайте новый проект.

Если у вас уже есть проект, щелкните раскрывающееся меню выбора проекта в левом верхнем углу консоли:

6c9406d9b014760.png

и нажмите кнопку « НОВЫЙ ПРОЕКТ » в появившемся диалоговом окне, чтобы создать новый проект:

949d83c8a4ee17d9.png

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

870a3cbd6541ee86.png

Последующий диалог создания проекта позволяет вам ввести детали вашего нового проекта:

6a92c57d3250a4b3.png

Запомните идентификатор проекта, который является уникальным именем для всех проектов Google Cloud (имя, указанное выше, уже занято и не подойдет вам, извините!). Позже в этой лаборатории он будет называться PROJECT_ID .

Далее, если вы еще этого не сделали, вам необходимо включить выставление счетов в консоли разработчика, чтобы использовать ресурсы Google Cloud и включить Cloud Spanner API .

15d0ef27a8fbab27.png

Выполнение этой кодовой лаборатории не должно стоить вам больше нескольких долларов, но может стоить больше, если вы решите использовать больше ресурсов или оставите их включенными (см. раздел «Очистка» в конце этого документа). Цены на Google Cloud Spanner описаны здесь , а GKE Autopilot — здесь .

Новые пользователи Google Cloud Platform имеют право на бесплатную пробную версию стоимостью 300 долларов США , что делает эту лабораторию кода совершенно бесплатной.

Настройка Cloud Shell

Хотя Google Cloud и Spanner можно управлять удаленно с вашего ноутбука, в этой лаборатории мы будем использовать Google Cloud Shell , среду командной строки, работающую в облаке.

Эта виртуальная машина на базе Debian оснащена всеми необходимыми инструментами разработки. Он предлагает постоянный домашний каталог объемом 5 ГБ и работает в Google Cloud, что значительно повышает производительность сети и аутентификацию. Это означает, что все, что вам понадобится для этой лаборатории кода, — это браузер (да, он работает на Chromebook).

  1. Чтобы активировать Cloud Shell из Cloud Console, просто нажмите «Активировать Cloud Shell». gcLMt5IuEcJJNnMId-Bcz3sxCd0rZn7IzT_r95C8UZeqML68Y1efBG_B0VRp7hc7qiZTLAF-TXD7SsOadxn8uadgHhaLeASnVS3ZHK39eOlKJOgj9SJua_oeGhMxRrbOg3qigddS2A (подготовка и подключение к среде займет всего несколько минут).

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

Снимок экрана 14.06.2017, 22.13.43.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 ? Узнайте, какой идентификатор вы использовали на этапах настройки, или найдите его на панели управления Cloud Console:

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)

Краткое содержание

На этом этапе вы настроили новый проект, активировали облачную оболочку и загрузили код для этой лабораторной работы.

Дальше

Далее вы подготовите инфраструктуру с помощью Terraform.

3. Обеспечение инфраструктуры

Обзор

Когда ваш проект готов, пришло время запустить инфраструктуру. Сюда входят сети VPC, Cloud Spanner, GKE Autopilot, реестр артефактов для хранения образов, которые будут запускаться в GKE, конвейеры Cloud Deploy для серверных служб и рабочих нагрузок и, наконец, учетные записи служб и привилегии IAM для возможности использования этих служб.

Это много. Но, к счастью, Terraform может упростить эту настройку. Terraform — это инструмент «Инфраструктура как код», который позволяет нам указать, что нам нужно для этого проекта, в серии файлов «.tf». Это упрощает предоставление инфраструктуры.

Знание Terraform не является обязательным условием для завершения этой лаборатории. Но если вы хотите увидеть, что делают следующие несколько шагов, вы можете взглянуть на то, что все создается в этих файлах, расположенных в каталоге инфраструктуры :

  • vpc.tf
  • backend_gke.tf
  • гаечный ключ.tf
  • артефакт_регистрация.tf
  • трубопроводы.tf
  • iam.tf

Настроить Терраформ

В 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, перейдя в гамбургер-меню и нажав Spanner . Возможно, вам придется нажать «Просмотреть больше продуктов», чтобы найти его в списке.

Это приведет вас к списку экземпляров Spanner. Нажмите на экземпляр, и вы увидите базы данных. Это должно выглядеть примерно так:

10b7fc0c4a86c59.png

ГКЭ Автопилот

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

9cecb1a702e6b7ff.png

Реестр артефактов

Теперь вам нужно увидеть, где будут храниться изображения. Итак, щелкните гамбургер-меню и найдите Artifact Registry=>Repositories . Реестр артефактов находится в разделе меню CI/CD.

Здесь вы увидите реестр Docker с именем spanner-game-images . Здесь пока будет пусто.

3f805eee312841b.png

Облачное развертывание

Cloud Deploy — это место, где были созданы конвейеры, чтобы Cloud Build мог предоставить шаги для создания образов и последующего их развертывания в нашем кластере GKE.

Перейдите в меню-гамбургер и найдите Cloud Deploy , который также находится в разделе меню CI/CD.

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

d2e4a659145ddf5e.png

Я

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

кровать3d1af94974916.png

Всего существует шесть учетных записей служб, созданных Terraform:

  • Учетная запись службы компьютера по умолчанию. В этой лаборатории кода это не используется.
  • Учетная запись cloudbuild-cicd используется для этапов Cloud Build и Cloud Deploy.
  • Четыре учетные записи приложений, которые используются нашими серверными службами для взаимодействия с Cloud Spanner.

Далее вам нужно настроить kubectl для взаимодействия с кластером GKE.

Настроить кубектл

# 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 для серверных служб и рабочих нагрузок, а также репозиторий реестра артефактов для хранения построенных образов.

И, наконец, учетные записи служб были созданы и настроены для работы с Workload Identity, чтобы серверные службы могли использовать Cloud Spanner.

У вас также есть kubectl , настроенный для взаимодействия с кластером GKE в Cloud Shell после развертывания серверных служб и рабочих нагрузок.

Дальше

Прежде чем вы сможете использовать службы, необходимо определить схему базы данных. Вы настроите это дальше.

4. Создайте схему базы данных.

Обзор

Прежде чем вы сможете запустить серверные службы, вам необходимо убедиться, что схема базы данных существует.

Если вы посмотрите на файлы в каталоге $DEMO_HOME/schema/migrations из демонстрационного репозитория, вы увидите серию файлов .sql , определяющих нашу схему. Это имитирует цикл разработки, при котором изменения схемы отслеживаются в самом репозитории и могут быть привязаны к определенным функциям приложений.

В этом примере среды wrench — это инструмент, который будет применять миграцию нашей схемы с помощью 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

И эта учетная запись службы имеет роль 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, чтобы вы могли отслеживать ход сборки и видеть, что она делает.

11b1cf107876d797.png

Краткое содержание

На этом этапе вы использовали Cloud Build для отправки первоначальной миграции схемы, в которой применялись 5 различных операций DDL. Эти операции представляют собой добавление функций, требующих изменения схемы базы данных.

В обычном сценарии разработки вам потребуется обеспечить обратную совместимость изменений схемы с текущим приложением, чтобы избежать сбоев.

Для изменений, которые не имеют обратной совместимости, рекомендуется развертывать изменения в приложении и схеме поэтапно, чтобы избежать сбоев.

Дальше

Когда схема готова, следующим шагом будет развертывание серверных служб!

5. Развертывание серверных служб

Обзор

Серверными службами для этой лаборатории кода являются API-интерфейсы REST golang, которые представляют четыре разных сервиса:

  • Профиль: предоставьте игрокам возможность зарегистрироваться и пройти аутентификацию в нашем образце «игры».
  • Организация матчей: взаимодействуйте с данными игроков, чтобы помочь с функцией подбора игроков, отслеживайте информацию о созданных играх и обновляйте статистику игроков, когда игры закрыты.
  • Предмет: позволяет игрокам приобретать игровые предметы и деньги в ходе игры.
  • Торговый пост: позволяет игрокам покупать и продавать предметы на торговом посту.

d36e958411d44b5d.png

Подробнее об этих сервисах можно узнать в лаборатории кода Cloud Spanner «Начало работы с разработкой игр» . Для наших целей мы хотим, чтобы эти службы работали в нашем кластере GKE Autopilot.

Эти службы должны иметь возможность изменять данные Spanner. Для этого у каждой службы создается учетная запись службы, которая предоставляет ей роль databaseUser.

Workload Identity позволяет учетной записи службы Kubernetes выдавать себя за учетную запись облачной службы Google, выполнив следующие шаги в нашем Terraform:

  • Создайте ресурс учетной записи облачной службы Google ( GSA ).
  • Назначьте роль DatabaseUser этой учетной записи службы.
  • Назначьте роль workloadIdentityUser этой учетной записи службы.
  • Создайте учетную запись службы Kubernetes ( KSA ), которая ссылается на GSA.

Грубая схема будет выглядеть так:

а8662d31d66b5910.png

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

Принцип работы сборки следующий:

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 каждой службы. Файл развертывания службы содержит информацию для создания службы, которая в данном случае представляет собой кластерный IP-адрес, работающий на порту 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, и образом, созданным на этапе сборки в облаке.

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

После этого мы указываем некоторую информацию о сетевых переменных и переменных среды.

spanner_config — это карта конфигурации Kubernetes, которая определяет информацию о проекте, экземпляре и базе данных, необходимую приложению для подключения к 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 , выходные данные этой сборки показывают, что были созданы некоторые образы. Они будут храниться в вашем репозитории реестра артефактов.

В результатах этапа gcloud build будет ссылка на Cloud Console. Взгляните на них.

Получив уведомление об успехе от Cloud Build, перейдите к Cloud Deploy, а затем к конвейеру sample-game-services , чтобы отслеживать ход развертывания.

df5c6124b9693986.png

После развертывания сервисов вы можете проверить 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 .

Рабочие нагрузки

da98979ae49e5a30.png

Услуги

406ca2fe7ad4818b.png

Карты конфигурации

a0ebd34ee735ee11.png

3b9ef91c77a4e7f0.png

Краткое содержание

На этом этапе вы развернули четыре серверные службы в GKE Autopilot. Вы смогли выполнить этап Cloud Build и проверить ход выполнения Cloud Deploy и Kubernetes в Cloud Console.

Вы также узнали, как эти службы используют Workload Identity для олицетворения учетной записи службы, имеющей необходимые разрешения на чтение и запись данных в базу данных 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

В верхней части раздела развертывания находятся метаданные о рабочей нагрузке. В этом случае развертывается только одна реплика:

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 . У вас должна получиться вот такая страница:

817307157d66c661.png

Вы оставите users и spawn по умолчанию 1. Для host введите http://item . Нажмите на дополнительные параметры и введите 10s для времени работы.

Вот как должна выглядеть конфигурация:

f3143165c6285c21.png

Нажмите «Начать роение»!

Начнет отображаться статистика для запросов, отправленных на конечную точку POST /items . Через 10 секунд нагрузка прекратится.

Нажмите на Charts , и вы увидите несколько графиков производительности этих запросов.

abad0a9f3c165345.png

Теперь вы хотите проверить, введены ли данные в базу данных Spanner.

Для этого нажмите гамбургер-меню и выберите «Гаечный ключ». На этой странице перейдите к sample-instance и sample-database . Затем нажмите « Query ».

Мы хотим выбрать количество game_items :

ВЫБЕРИТЕ СЧЕТ (*) ИЗ game_items;

Внизу вы получите свой результат.

137ce291a2ff2706.png

Нам не нужно много посеянных 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 для хоста. И вы не укажете время выполнения в дополнительных параметрах. Также укажите 4 users , что будет имитировать 4 пользовательских запроса одновременно.

Тест profile-workload должен выглядеть так:

f6e0f06efb0ad6e.png

Нажмите «Начать роение»!

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

4c2146e1cb3de23e.png

Краткое содержание

На этом этапе вы создали несколько game_items , а затем запросили таблицу game_items с помощью пользовательского интерфейса Spanner Query в Cloud Console.

Вы также разрешили игрокам подписаться на вашу игру и увидели, как Locust может создавать рабочие нагрузки, подобные производственным, для ваших серверных служб.

Следующие шаги

После запуска рабочих нагрузок вам нужно будет проверить, как ведут себя кластер GKE и экземпляр Spanner.

8. Проверьте использование GKE и гаечного ключа.

Когда служба профилей запущена, пришло время воспользоваться возможностью посмотреть, как ведут себя ваш кластер GKE Autopilot и Cloud Spanner.

Проверьте кластер GKE

Перейдите в кластер Kubernetes. Обратите внимание: поскольку вы развернули рабочие нагрузки и службы, в кластер теперь добавлены некоторые сведения об общем количестве виртуальных ЦП и памяти. Эта информация была недоступна, когда в кластере не было рабочих нагрузок.

61d2d766c1f10079.png

Теперь щелкните кластер sample-game-gke и переключитесь на вкладку наблюдаемости:

fa9acc7e26ea04a.png

Пространство имен kubernetes default должно было превосходить пространство имен kube-system по загрузке ЦП, поскольку наши рабочие нагрузки и серверные службы выполняются по default . Если этого не произошло, убедитесь, что profile workload все еще выполняется, и подождите несколько минут, пока диаграммы обновятся.

Чтобы узнать, какие рабочие нагрузки потребляют больше всего ресурсов, перейдите на панель Workloads .

Вместо того, чтобы рассматривать каждую рабочую нагрузку по отдельности, перейдите прямо на вкладку «Наблюдаемость» панели мониторинга. Вы должны увидеть, что profile и profile-workload ЦП увеличились.

f194b618969cfa9e.png

А теперь проверь Cloud Spanner.

Проверьте экземпляр Cloud Spanner

Чтобы проверить производительность Cloud Spanner, перейдите к Spanner и щелкните sample-instance и базу данных sample-game .

Оттуда вы увидите вкладку System Insights в левом меню:

216212182a57dfd1.png

Здесь представлено множество диаграмм, которые помогут вам понять общую производительность вашего экземпляра Spanner, включая CPU utilization , transaction latency and locking , а также query throughput .

Помимо System Insights, вы можете получить более подробную информацию о рабочей нагрузке запросов, просмотрев другие ссылки в разделе «Наблюдаемость»:

  • Аналитика запросов помогает определить TopN запросов, использующих ресурсы Spanner.
  • Анализ транзакций и блокировок помогает выявлять транзакции с высокими задержками.
  • Key Visualizer помогает визуализировать шаблоны доступа и отслеживать «горячие точки» в данных.

Краткое содержание

На этом этапе вы узнали, как проверить некоторые основные показатели производительности для GKE Autopilot и Spanner.

Например, во время рабочей нагрузки вашего профиля запросите таблицу игроков , чтобы получить дополнительную информацию о хранящихся там данных.

Следующие шаги

Далее пришло время навести порядок!

9. Уборка

Прежде чем приступить к очистке, изучите другие рабочие нагрузки, которые не были рассмотрены. В частности, matchmaking-workload , game-workload и tradepost-workload .

Когда вы закончите «играть» в игру, вы можете навести порядок на игровой площадке. К счастью, это довольно легко.

Во-первых, если profile-workload все еще выполняется в браузере, остановите ее:

13ae755a11f3228.png

Сделайте то же самое для каждой рабочей нагрузки, которую вы, возможно, тестировали.

Затем в Cloud Shell перейдите в папку инфраструктуры. Вы 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 Console перейдите к Spanner , Kubernetes Cluster , Artifact Registry , Cloud Deploy и IAM , чтобы убедиться, что все ресурсы удалены.

10. Поздравляем!

Поздравляем, вы успешно развернули примеры приложений golang на GKE Autopilot и подключили их к Cloud Spanner с помощью Workload Identity!

В качестве бонуса эту инфраструктуру можно было легко настроить и удалить с помощью Terraform.

Вы можете узнать больше о сервисах Google Cloud, с которыми вы взаимодействовали, в этой лаборатории кода:

Что дальше?

Теперь, когда у вас есть базовое представление о том, как GKE Autopilot и Cloud Spanner могут работать вместе, почему бы не сделать следующий шаг и не начать создавать собственное приложение для работы с этими сервисами?