Como conectar o Cloud Spanner ao Autopilot do GKE

1. Introdução

O Cloud Spanner é um serviço de banco de dados relacional totalmente gerenciado, escalonável e distribuído globalmente que oferece transações ACID e semântica de SQL sem abrir mão do desempenho e da alta disponibilidade.

O GKE Autopilot é um modo de operação em que o Google gerencia a configuração do cluster, incluindo nós, escalonamento, segurança e outras configurações predefinidas para seguir as práticas recomendadas. Por exemplo, o GKE Autopilot permite que a Identidade da carga de trabalho gerencie permissões de serviço.

O objetivo deste laboratório é orientar você no processo de conexão de vários serviços de back-end em execução no Autopilot do GKE a um banco de dados do Cloud Spanner.

3d810aa9ec80a271.png

Neste laboratório, primeiro você vai configurar um projeto e iniciar o Cloud Shell. Depois você vai implantar a infraestrutura usando o Terraform.

Quando terminar, você vai interagir com o Cloud Build e o Cloud Deploy para realizar uma migração de esquema inicial para o banco de dados de jogos, implantar os serviços de back-end e implantar as cargas de trabalho.

Os serviços deste codelab são os mesmos do codelab Introdução ao desenvolvimento de jogos no Cloud Spanner. Realizar esse codelab não é um requisito para executar os serviços no GKE e se conectar ao Spanner. Mas se você tiver interesse em mais detalhes específicos desses serviços que funcionam no Spanner, confira.

Com as cargas de trabalho e os serviços de back-end em execução, é possível começar a gerar carga e observar como os serviços funcionam juntos.

Por fim, você vai limpar os recursos criados neste laboratório.

O que você vai criar

Como parte deste laboratório, você vai:

  • Provisionar a infraestrutura usando o Terraform
  • Criar o esquema do banco de dados usando um processo de migração de esquema no Cloud Build
  • Implante os quatro serviços de back-end do Golang que usam a Identidade da carga de trabalho para se conectar ao Cloud Spanner
  • Implantar os quatro serviços de carga de trabalho usados para simular a carga dos serviços de back-end.

O que você vai aprender

  • Como provisionar pipelines do Autopilot do GKE, do Cloud Spanner e do Cloud Deploy usando o Terraform
  • Como a Identidade da carga de trabalho permite que os serviços no GKE representem contas de serviço para acessar as permissões do IAM para funcionar com o Cloud Spanner
  • Como gerar uma carga semelhante à de produção no GKE e no Cloud Spanner usando o Locust.io

O que é necessário

  • Um projeto do Google Cloud conectado a uma conta de faturamento.
  • Um navegador, como o Chrome ou o Firefox

2. Configuração e requisitos

Criar um projeto

Se você ainda não tem uma Conta do Google (Gmail ou Google Apps), crie uma. Faça login no console do Google Cloud Platform ( console.cloud.google.com) e crie um novo projeto.

Se você já tiver um projeto, clique no menu suspenso de seleção no canto superior esquerdo do console:

6c9406d9b014760.png

e clique no botão NOVO PROJETO na caixa de diálogo para criar um novo projeto:

949d83c8a4ee17d9.png

Se você ainda não tiver um projeto, uma caixa de diálogo como esta será exibida para criar seu primeiro:

870a3cbd6541ee86.png

A caixa de diálogo de criação de projeto subsequente permite que você insira os detalhes do novo projeto:

6a92c57d3250a4b3.png

Lembre-se do código do projeto, um nome exclusivo em todos os projetos do Google Cloud. O nome acima já foi escolhido e não servirá para você. Faremos referência a ele mais adiante neste codelab como PROJECT_ID.

Em seguida, será preciso ativar o faturamento no Developers Console para usar os recursos do Google Cloud e ativar a API Cloud Spanner, caso ainda não tenha feito isso.

15d0ef27a8fbab27.png

A execução por meio deste codelab terá um custo baixo, mas poderá ser mais se você decidir usar mais recursos ou se deixá-los em execução. Consulte a seção "limpeza" no final deste documento. Os preços do Google Cloud Spanner estão documentados aqui e do Autopilot do GKE estão documentados aqui.

Novos usuários do Google Cloud Platform estão qualificados para uma avaliação gratuita de US$ 300, o que torna este codelab totalmente gratuito.

Configuração do Cloud Shell

Embora o Google Cloud e o Spanner possam ser operados remotamente do seu laptop, neste codelab usaremos o Google Cloud Shell, um ambiente de linha de comando executado no Cloud.

O Cloud Shell é uma máquina virtual com base em Debian que contém todas as ferramentas de desenvolvimento necessárias. Ela oferece um diretório principal persistente de 5 GB, além de ser executada no Google Cloud. Isso aprimora o desempenho e a autenticação da rede. Isso significa que tudo que você precisa para este codelab é um navegador (sim, funciona em um Chromebook).

  1. Para ativar o Cloud Shell no Console do Cloud, basta clicar em Ativar o Cloud Shell gcLMt5IuEcJJNnMId-Bcz3sxCd0rZn7IzT_r95C8UZeqML68Y1efBG_B0VRp7hc7qiZTLAF-TXD7SsOadxn8uadgHhaLeASnVS3ZHK39eOlKJOgj9SJua_oeGhMxRrbOg3qigddS2A. O provisionamento e a conexão ao ambiente devem levar apenas alguns instantes.

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

Screen Shot 2017-06-14 às 10.13.43 PM.png

Depois de se conectar ao Cloud Shell, você já estará autenticado e o projeto estará configurado com seu PROJECT_ID.

gcloud auth list

Resposta ao comando

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

Resposta ao comando

[core]
project = <PROJECT_ID>

Se, por algum motivo, o projeto não estiver definido, basta emitir o seguinte comando:

gcloud config set project <PROJECT_ID>

Quer encontrar seu PROJECT_ID? Veja qual ID você usou nas etapas de configuração ou procure-o no painel do Console do Cloud:

158fNPfwSxsFqz9YbtJVZes8viTS3d1bV4CVhij3XPxuzVFOtTObnwsphlm6lYGmgdMFwBJtc-FaLrZU7XHAg_ZYoCrgombMRR3h-eolLPcvO351c5iBv506B3ZwghZoiRg6cz23Qw

O Cloud Shell também define algumas variáveis de ambiente por padrão, o que pode ser útil ao executar comandos futuros.

echo $GOOGLE_CLOUD_PROJECT

Resposta ao comando

<PROJECT_ID>

Fazer o download do código

No Cloud Shell, faça o download do código para este laboratório:

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

Resposta ao comando

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

Este codelab é baseado na versão v0.1.3, então confira esta tag:

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

Resposta ao comando

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

Agora defina o diretório de trabalho atual como a variável de ambiente DEMO_HOME. Isso facilita a navegação enquanto você trabalha nas diferentes partes do codelab.

export DEMO_HOME=$(pwd)

Resumo

Nesta etapa, você configurou um novo projeto, ativou o Cloud Shell e fez o download do código para este laboratório.

A seguir

Em seguida, você vai provisionar a infraestrutura usando o Terraform.

3. Provisionar infraestrutura

Visão geral

Com o projeto pronto, é hora de colocar a infraestrutura em execução. Isso inclui redes VPC, Cloud Spanner, GKE Autopilot, Artifact Registry para armazenar as imagens que serão executadas no GKE, os pipelines do Cloud Deploy para serviços e cargas de trabalho de back-end e, por fim, as contas de serviço e os privilégios do IAM para usar esses serviços.

É muita coisa. Felizmente, o Terraform pode simplificar essa configuração. O Terraform é uma ferramenta de "infraestrutura como código" que nos permite especificar o que precisamos para este projeto em uma série de arquivos . Isso simplifica o provisionamento da infraestrutura.

Ter familiaridade com o Terraform não é um requisito para concluir este codelab. Mas se você quiser saber o que as próximas etapas estão fazendo, confira o que tudo é criado nestes arquivos localizados no diretório infrastructure:

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

Configurar o Terraform

No Cloud Shell, mude para o diretório infrastructure e inicialize o Terraform:

cd $DEMO_HOME/infrastructure
terraform init

Resposta ao comando

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.

Em seguida, configure o Terraform copiando o terraform.tfvars.sample e modificando o valor do projeto. As outras variáveis também podem ser alteradas, mas o projeto é a única que precisa ser alterada para funcionar com seu ambiente.

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

Provisionar a infraestrutura

Agora é hora de provisionar a infraestrutura.

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

Resposta ao comando

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.

Verificar o que foi criado

Para confirmar o que foi criado, confira os produtos no console do Cloud.

Cloud Spanner

Primeiro, verifique o Cloud Spanner navegando até o menu de navegação e clicando em Spanner. Talvez você precise clicar em "Ver mais produtos" para encontrá-lo na lista.

Isso vai levar você à lista de instâncias do Spanner. Clique na instância para acessar os bancos de dados. O código será semelhante a este:

10b7fc0c4a86c59.png

Autopilot do GKE

Em seguida, acesse o GKE navegando até o menu de navegação e clicando em Kubernetes Engine => Clusters. Aqui você vai conferir o cluster sample-games-gke em execução no modo Autopilot.

9cecb1a702e6b7ff.png

Artifact Registry

Agora você vai querer ver onde as imagens serão armazenadas. Clique no menu de navegação e encontre Artifact Registry=>Repositories. O Artifact Registry está na seção de CI/CD do menu.

Aqui, você verá um registro do Docker chamado spanner-game-images. Ele ficará vazio por enquanto.

3f805eee312841b.png

Cloud Deploy

O Cloud Deploy é onde os pipelines foram criados para que o Cloud Build possa fornecer etapas para criar as imagens e implantá-las no cluster do GKE.

Navegue até o menu de navegação e encontre Cloud Deploy, que também está na seção CI/CD do menu.

Você vai notar dois pipelines: um para serviços de back-end e outro para cargas de trabalho. Ambas implantam as imagens no mesmo cluster do GKE, mas isso permite separar as implantações.

d2e4a659145ddf5e.png

IAM

Por fim, confira a página do IAM no console do Cloud para verificar as contas de serviço que foram criadas. Navegue até o menu de navegação e encontre IAM and Admin=>Service accounts. O código será semelhante a este:

bed3d1af94974916.png

Há seis contas de serviço no total criadas pelo Terraform:

  • a conta padrão de serviço do computador. Isso não é usado neste codelab.
  • A conta cloudbuild-cicd é usada nas etapas de Cloud Build e Cloud Deploy.
  • Quatro "app" contas que são usadas pelos nossos serviços de back-end para interagir com o Cloud Spanner.

Em seguida, configure o kubectl para interagir com o cluster do GKE.

Configurar o 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

Resposta ao comando

#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

Resumo

Ótimo! Você provisionaru uma instância do Cloud Spanner e um cluster do Autopilot do GKE, tudo em uma VPC para rede particular.

Além disso, dois pipelines do Cloud Deploy foram criados para os serviços de back-end e as cargas de trabalho, além de um repositório do Artifact Registry para armazenar as imagens criadas.

Por fim, as contas de serviço foram criadas e configuradas para funcionar com a Identidade da carga de trabalho. Assim, os serviços de back-end podem usar o Cloud Spanner.

Você também configurou o kubectl para interagir com o cluster do GKE no Cloud Shell depois de implantar os serviços de back-end e as cargas de trabalho.

A seguir

Antes de usar os serviços, o esquema do banco de dados precisa ser definido. Você vai configurar isso a seguir.

4. Criar o esquema do banco de dados

Visão geral

Antes de executar os serviços de back-end, você precisa verificar se o esquema do banco de dados está em vigor.

Nos arquivos do diretório $DEMO_HOME/schema/migrations do repositório de demonstração, você vai encontrar uma série de arquivos .sql que definem o esquema. Isso imita um ciclo de desenvolvimento em que as alterações de esquema são rastreadas no próprio repositório e podem ser vinculadas a determinados recursos dos aplicativos.

Neste ambiente de exemplo, a chave é a ferramenta que aplica nossas migrações de esquema usando o Cloud Build.

Cloud Build

O arquivo $DEMO_HOME/schema/cloudbuild.yaml descreve as etapas que serão realizadas:

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

Basicamente, há duas etapas:

  • fazer o download da chave inglesa para o espaço de trabalho do Cloud Build
  • executar a migração da chave inglesa

As variáveis de ambiente do banco de dados, da instância e do projeto do Spanner são necessárias para a chave se conectar ao endpoint de gravação.

O Cloud Build pode fazer essas alterações porque está sendo executado como a conta de serviço cloudbuild-cicd@${PROJECT_ID}.iam.gserviceaccount.com:

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

E essa conta de serviço tem o papel spanner.databaseUser adicionado pelo Terraform, que permite que a conta de serviço atualize DDL.

Migrações de esquema

Há cinco etapas de migração que são realizadas com base nos arquivos do diretório $DEMO_HOME/schema/migrations. Confira um exemplo do arquivo 000001.sql que cria uma tabela players e os índices:

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);

Enviar a migração do esquema

Para enviar o build para a migração do esquema, alterne para o diretório schema e execute o seguinte comando gcloud:

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

Resposta ao comando

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

Na saída acima, você verá um link para o processo de build do Cloud Created. Se clicar nele, você será direcionado ao build no console do Cloud para monitorar o progresso e conferir o que está acontecendo.

11b1cf107876d797.png

Resumo

Nesta etapa, você usou o Cloud Build para enviar a migração de esquema inicial que aplicou cinco operações DDL diferentes. Essas operações representam quando foram adicionados recursos que precisavam de alterações no esquema do banco de dados.

Em um cenário de desenvolvimento normal, é recomendado fazer alterações de esquema compatíveis com o aplicativo atual para evitar interrupções.

Para alterações que não são compatíveis com versões anteriores, implante as alterações no aplicativo e no esquema em etapas para garantir que não haja interrupções.

A seguir

Com o esquema implementado, a próxima etapa é implantar os serviços de back-end.

5. Implantar os serviços de back-end

Visão geral

Os serviços de back-end deste codelab são APIs REST do golang que representam quatro serviços diferentes:

  • Perfil:permite que os jogadores se inscrevam e autentiquem no nosso "jogo" de exemplo.
  • Criação de combinações:interaja com os dados dos jogadores para ajudar com uma função de combinação, acompanhar informações sobre jogos criados e atualizar as estatísticas quando os jogos são encerrados.
  • Item:permite que os usuários adquiram itens e dinheiro ao longo do jogo.
  • Tradepost::permita que os jogadores comprem e vendam itens em uma loja

d36e958411d44b5d.png

Saiba mais sobre esses serviços no codelab Introdução ao desenvolvimento de jogos com o Cloud Spanner. Para nossos objetivos, queremos que esses serviços sejam executados no nosso cluster do Autopilot do GKE.

Esses serviços precisam ser capazes de modificar os dados do Spanner. Para isso, cada serviço tem uma conta criada que concede a ele o papel "databaseUser" de rede.

A Identidade da carga de trabalho permite que uma conta de serviço do Kubernetes personifique conta de serviço do Google Cloud seguindo as etapas abaixo no Terraform:

  • Criar o recurso da conta de serviço do Google Cloud (GSA) do serviço
  • Atribua o papel databaseUser a essa conta de serviço.
  • Atribua o papel workloadIdentityUser a essa conta de serviço.
  • Crie uma conta de serviço do Kubernetes (KSA) que faça referência ao GSA

Um diagrama aproximado seria semelhante a este:

a8662d31d66b5910.png

O Terraform criou as contas de serviço e as contas de serviço do Kubernetes para você. E é possível verificar as contas de serviço do Kubernetes usando 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

O build funciona da seguinte maneira:

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
  • O comando do Cloud Build lê esse arquivo e segue as etapas listadas. Primeiro, ele cria as imagens de serviço. Em seguida, ele executa um comando gcloud deploy create. Isso lê o arquivo $DEMO_HOME/backend_services/skaffold.yaml, que define onde cada arquivo de implantação está localizado:
apiVersion: skaffold/v2beta29
kind: Config
deploy:
 kubectl:
   manifests:
     - spanner_config.yaml
     - profile/deployment.yaml
     - matchmaking/deployment.yaml
     - item/deployment.yaml
     - tradepost/deployment.yaml
  • O Cloud Deploy seguirá as definições do arquivo deployment.yaml de cada serviço. O arquivo de implantação do serviço contém as informações para criar um serviço, que neste caso é um clusterIP em execução na porta 80.

O evento " O tipo ClusterIP" impede que os pods de serviço de back-end tenham um IP externo. Assim, apenas entidades que podem se conectar à rede interna do GKE podem acessar os serviços de back-end. Esses serviços não podem ser diretamente acessíveis aos jogadores porque eles acessam e modificam os dados do Spanner.

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

Além de criar um serviço do Kubernetes, o Cloud Deploy também cria uma implantação do Kubernetes. Vamos examinar a seção de implantação do serviço 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"

A parte de cima contém alguns metadados sobre o serviço. O mais importante aqui é definir quantas réplicas serão criadas por esta implantação.

replicas: 2 # EDIT: Number of instances of deployment

Em seguida, vamos conferir qual conta de serviço executa o app e qual imagem ele precisa usar. Elas correspondem à conta de serviço do Kubernetes criada no Terraform e à imagem criada durante a etapa do Cloud Build.

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

Depois, especificamos algumas informações sobre a rede e as variáveis de ambiente.

O spanner_config é um ConfigMap do Kubernetes que especifica as informações do projeto, da instância e do banco de dados necessárias para que o aplicativo se conecte ao 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 e SERVICE_PORT são variáveis de ambiente extras necessárias para que o serviço saiba onde se vincular.

A seção final informa ao GKE quantos recursos são permitidos para cada réplica na implantação. O GKE Autopilot também usa isso para escalonar o cluster conforme necessário.

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

Com essas informações, é hora de implantar os serviços de back-end.

Implantar os serviços de back-end

Como mencionado, a implantação dos serviços de back-end usa o Cloud Build. Assim como nas migrações de esquema, é possível enviar a solicitação de build usando a linha de comando gcloud:

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

Resposta ao comando

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

Ao contrário da saída da etapa schema migration, a saída desse build indica que algumas imagens foram criadas. Eles serão armazenados no repositório do Artifact Registry.

A saída da etapa gcloud build terá um link para o console do Cloud. Dá uma olhada nisso.

Quando você tiver a notificação de êxito do Cloud Build, acesse o Cloud Deploy e, em seguida, o pipeline sample-game-services para monitorar o progresso da implantação.

df5c6124b9693986.png

Depois que os serviços forem implantados, verifique o kubectl para verificar Status:

kubectl get pods

Resposta ao comando

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

Em seguida, verifique os serviços para ver o ClusterIP em ação:

kubectl get services

Resposta ao comando

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

Também é possível navegar até a interface do GKE no Console do Cloud para ver Workloads, Services e ConfigMaps.

Cargas de trabalho

da98979ae49e5a30.png

Serviços

406ca2fe7ad4818b.png

ConfigMaps

a0ebd34ee735ee11.png

3b9ef91c77a4e7f0.png

Resumo

Nesta etapa, você implantou os quatro serviços de back-end no Autopilot do GKE. Você conseguiu executar a etapa do Cloud Build e verificar o progresso no Cloud Deploy e no Kubernetes no console do Cloud.

Você também aprendeu como esses serviços usam a Identidade da carga de trabalho para representar uma conta de serviço com as permissões certas para ler e gravar dados no banco de dados do Spanner.

Próximas etapas

Na próxima seção, você vai implantar as cargas de trabalho.

6. Implantar as cargas de trabalho

Visão geral

Agora que os serviços de back-end estão em execução no cluster, você implantará as cargas de trabalho.

dd900485e2eeb611.png

As cargas de trabalho podem ser acessadas externamente, e há uma para cada serviço de back-end neste codelab.

Essas cargas de trabalho são scripts de geração de carga baseados no Locust que imitam os padrões de acesso reais esperados por esses serviços de amostra.

Há arquivos para o processo do Cloud Build:

  • $DEMO_HOME/workloads/cloudbuild.yaml (gerado pelo Terraform)
  • $DEMO_HOME/workloads/skaffold.yaml
  • um arquivo deployment.yaml para cada carga de trabalho

Os arquivos deployment.yaml da carga de trabalho são um pouco diferentes dos arquivos de implantação do serviço de back-end.

Veja um exemplo do 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"

A parte superior do arquivo define o serviço. Nesse caso, um LoadBalancer é criado e a carga de trabalho é executada na porta 8089.

O LoadBalancer fornecerá um IP externo que pode ser usado para se conectar à carga de trabalho.

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

A parte de cima da seção de implantação são os metadados sobre a carga de trabalho. Neste caso, apenas uma réplica está sendo implantada:

replicas: 1 

No entanto, a especificação do contêiner é diferente. Por um lado, estamos usando uma conta de serviço default do Kubernetes. Essa conta não tem privilégios especiais, já que a carga de trabalho não precisa se conectar a nenhum recurso do Google Cloud, exceto aos serviços de back-end em execução no cluster do GKE.

A outra diferença é que não são necessárias variáveis de ambiente para essas cargas de trabalho. O resultado é uma especificação de implantação mais curta.

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

As configurações de recursos são semelhantes às dos serviços de back-end. É assim que o Autopilot do GKE sabe quantos recursos são necessários para atender às solicitações de todos os pods em execução no cluster.

Implante as cargas de trabalho.

Implantar as cargas de trabalho

Assim como antes, você pode enviar a solicitação de build usando a linha de comando gcloud:

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

Resposta ao comando

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

Verifique os registros do Cloud Build e o pipeline do Cloud Deploy no console do Cloud para verificar o status. Para as cargas de trabalho, o pipeline do Cloud Deploy é sample-game-workloads:

Quando a implantação for concluída, verifique o status com kubectl no Cloud Shell:

kubectl get pods

Resposta ao comando

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

Em seguida, verifique os serviços de carga de trabalho para ver o LoadBalancer em ação:

kubectl get services 

Resposta ao comando

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

Resumo

Você implantou as cargas de trabalho no cluster do GKE. Essas cargas de trabalho não exigem outras permissões do IAM e podem ser acessadas externamente na porta 8089 com o serviço LoadBalancer.

Próximas etapas

Com serviços de back-end e cargas de trabalho em execução, é hora de jogar o jogo!

7. Começar a jogar

Visão geral

Os serviços de back-end para o "jogo" de amostra estão em execução e você também pode gerar "jogadores" que interagem com esses serviços usando as cargas de trabalho.

Cada carga de trabalho usa o Locust para simular uma carga real com base nas nossas APIs de serviço. Nesta etapa, você vai executar várias cargas de trabalho para gerar carga no cluster do GKE e no Spanner, além de armazenar dados nele.

Veja a seguir uma descrição de cada carga de trabalho:

  • A carga de trabalho item-generator é rápida para gerar uma lista de game_items que os jogadores podem adquirir ao "jogar" o jogo.
  • O profile-workload simula a inscrição e o login dos jogadores.
  • O matchmaking-workload simula os jogadores na fila para serem atribuídos a jogos.
  • O game-workload simula a aquisição de itens de jogo e dinheiro pelos jogadores.
  • O tradepost-workload simula a venda e compra de itens dos jogadores na postagem de negociação.

Este codelab destacará a execução específica de item-generator e profile-workload.

Executar o gerador de itens

O item-generator usa o endpoint do serviço de back-end item para adicionar game_items ao Spanner. Esses itens são necessários para que game-workload e tradepost-workload funcionem corretamente.

A primeira etapa é conseguir o IP externo do serviço item-generator. No Cloud Shell, execute o seguinte:

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

Resposta ao comando

{ITEMGENERATOR_EXTERNAL_IP}

Agora, abra uma nova guia do navegador e aponte-a para http://{ITEMGENERATOR_EXTERNAL_IP}:8089. Você verá uma página como esta:

817307157d66c661.png

Deixe users e spawn com o padrão 1. Para host, insira http://item. Clique nas opções avançadas e insira 10s para o tempo de execução.

A configuração vai ficar assim:

f3143165c6285c21.png

Clique em "Start swarming"!

Estatísticas serão exibidas para solicitações emitidas no endpoint POST /items. Após 10 segundos, o carregamento é interrompido.

Clique no Charts para ver alguns gráficos sobre o desempenho dessas solicitações.

abad0a9f3c165345.png

Agora você quer verificar se os dados são inseridos no banco de dados do Spanner.

Para fazer isso, clique no menu de navegação e acesse "Spanner". Nessa página, navegue até o sample-instance e o sample-database. Depois, clique em "Query".

Queremos selecionar o número de game_items:

SELECT COUNT(*) FROM game_items;

Você receberá seu resultado na parte inferior.

137ce291a2ff2706.png

Não precisamos de muitas sugestões de game_items. Mas agora eles estão disponíveis para os jogadores adquirirem!

Executar a carga de trabalho do perfil

Com seu número de origem do game_items, a próxima etapa é inscrever os jogadores para poder jogar.

O profile-workload vai usar o Locust para simular os jogadores criando contas, fazendo login, recuperando informações de perfil e saindo. Todos eles testam os endpoints do serviço de back-end profile em uma carga de trabalho típica semelhante à de produção.

Para executar, consulte o IP externo profile-workload:

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

Resposta ao comando

{PROFILEWORKLOAD_EXTERNAL_IP}

Agora, abra uma nova guia do navegador e aponte-a para http://{PROFILEWORKLOAD_EXTERNAL_IP}:8089. Será exibida uma página do Locust parecida com a anterior.

Neste caso, você vai usar http://profile para o host. Além disso, você não especificará um ambiente de execução nas opções avançadas. Além disso, especifique o users como 4, o que vai simular quatro solicitações do usuário por vez.

O teste profile-workload ficará assim:

f6e0f06efb0ad6e.png

Clique em "Start swarming"!

Assim como antes, as estatísticas dos vários endpoints REST profile vão começar a aparecer. Clique nos gráficos para visualizar o desempenho de tudo.

4c2146e1cb3de23e.png

Resumo

Nesta etapa, você gerou game_items e consultou a tabela game_items usando a interface de consulta do Spanner no Console do Cloud.

Você também permitiu que os jogadores se inscrevessem no jogo e viu como o Locust cria cargas de trabalho semelhantes às de produção nos serviços de back-end.

Próximas etapas

Depois de executar as cargas de trabalho, verifique como o cluster do GKE e a instância do Spanner estão se comportando.

8. Analisar o uso do GKE e do Spanner

Com o serviço de perfil em execução, é hora de aproveitar a oportunidade para conferir como o cluster do Autopilot do GKE e o Cloud Spanner estão se comportando.

Verificar o cluster do GKE

Navegue até o cluster do Kubernetes. Observe que, como você implantou as cargas de trabalho e os serviços, o cluster agora tem alguns detalhes sobre o total de vCPUs e a memória. Essas informações não estavam disponíveis quando não havia cargas de trabalho no cluster.

61d2d766c1f10079.png

Agora, clique no cluster sample-game-gke e alterne para a guia de observabilidade:

fa9acc7e26ea04a.png

O namespace do Kubernetes default deveria ter ultrapassado o namespace kube-system para utilização de CPU, já que nossas cargas de trabalho e serviços de back-end são executados em default. Caso contrário, verifique se o profile workload ainda está em execução e aguarde alguns minutos para que os gráficos sejam atualizados.

Para ver quais cargas de trabalho estão usando mais recursos, acesse o painel Workloads.

Em vez de analisar cada carga de trabalho individualmente, vá direto para a guia "Observabilidade" do painel. A CPU de profile e profile-workload aumentou.

f194b618969cfa9e.png

Agora, verifique o Cloud Spanner.

Verificação na instância do Cloud Spanner

Para verificar o desempenho do Cloud Spanner, navegue até o Spanner e clique na instância sample-instance e no banco de dados sample-game.

Você verá uma guia Insights do sistema no menu à esquerda:

216212182a57dfd1.png

Há muitos gráficos para ajudar você a entender o desempenho geral da sua instância do Spanner, incluindo CPU utilization, transaction latency and locking e query throughput.

Além dos Insights do sistema, você pode conferir informações mais detalhadas sobre a carga de trabalho de consultas nos outros links da seção "Observabilidade":

  • Os insights de consulta ajudam a identificar as principais consultas que utilizam recursos no Spanner.
  • Os insights de transação e bloqueio ajudam a identificar transações com altas latências.
  • O Key Visualizer ajuda a visualizar padrões de acesso e a rastrear pontos de acesso nos dados.

Resumo

Nesta etapa, você aprendeu a verificar algumas métricas básicas de desempenho do Autopilot do GKE e do Spanner.

Por exemplo, com a carga de trabalho do seu perfil em execução, consulte a tabela players para mais informações sobre os dados que estão sendo armazenados.

Próximas etapas

A seguir, é hora de fazer a limpeza!

9. Limpar

Antes da limpeza, fique à vontade para conhecer as outras cargas de trabalho que não foram abordadas. Especificamente, matchmaking-workload, game-workload e tradepost-workload.

Quando terminar de "tocar", pode limpar o playground. Felizmente, isso é muito fácil.

Primeiro, se o profile-workload ainda estiver em execução no navegador, interrompa-o:

13ae755a11f3228.png

Faça o mesmo para cada carga de trabalho que você possa ter testado.

Em seguida, no Cloud Shell, navegue até a pasta de infraestrutura. Você vai destroy a infraestrutura usando o Terraform:

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

Resposta ao comando

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.

No console do Cloud, acesse Spanner, Kubernetes Cluster, Artifact Registry, Cloud Deploy e IAM para confirmar que todos os recursos foram removidos.

10. Parabéns!

Parabéns, você implantou aplicativos de amostra golang no GKE Autopilot e os conectou ao Cloud Spanner usando a Identidade da carga de trabalho.

Como bônus, essa infraestrutura foi facilmente configurada e removida de maneira repetível usando o Terraform.

Leia mais sobre os serviços do Google Cloud com que você interagiu neste codelab:

A seguir

Agora que você tem um entendimento básico de como o Autopilot do GKE e o Cloud Spanner podem funcionar juntos, que tal começar a criar seu próprio aplicativo para trabalhar com esses serviços?