Connessione di Cloud Spanner con GKE Autopilot

1. Introduzione

Cloud Spanner è un servizio di database relazionale completamente gestito, scalabile orizzontalmente e distribuito a livello globale che fornisce transazioni ACID e semantica SQL senza rinunciare a prestazioni e disponibilità elevata.

GKE Autopilot è una modalità operativa di GKE in cui Google gestisce la configurazione del cluster, inclusi nodi, scalabilità, sicurezza e altre impostazioni preconfigurate in base alle best practice. Ad esempio, GKE Autopilot abilita Workload Identity per gestire le autorizzazioni del servizio.

L'obiettivo di questo lab è guidarti attraverso il processo per connettere diversi servizi di backend in esecuzione su GKE Autopilot a un database Cloud Spanner.

3d810aa9ec80a271.png

In questo lab, configurerai innanzitutto un progetto e avvierai Cloud Shell. Quindi eseguirai il deployment dell'infrastruttura utilizzando Terraform.

Al termine, interagirai con Cloud Build e Cloud Deploy per eseguire una migrazione iniziale dello schema per il database dei giochi, eseguire il deployment dei servizi di backend e quindi del deployment dei carichi di lavoro.

I servizi in questo codelab sono gli stessi del codelab Introduzione allo sviluppo di giochi di Cloud Spanner. Seguire questo codelab non è un requisito per eseguire i servizi su GKE e stabilire la connessione a Spanner. Ma se vuoi saperne di più sulle specifiche di questi servizi che funzionano su Spanner, dai un'occhiata.

Con i carichi di lavoro e i servizi di backend in esecuzione, puoi iniziare a generare carico e osservare come i servizi funzionano insieme.

Infine, eseguirai la pulizia delle risorse create in questo lab.

Cosa creerai

Nell'ambito di questo lab imparerai a:

  • Eseguire il provisioning dell'infrastruttura utilizzando Terraform
  • Crea lo schema del database utilizzando un processo di migrazione degli schemi in Cloud Build
  • Esegui il deployment dei quattro servizi di backend Golang che utilizzano Workload Identity per la connessione a Cloud Spanner
  • Esegui il deployment dei quattro servizi dei carichi di lavoro utilizzati per simulare il carico dei servizi di backend.

Cosa imparerai a fare

  • Come eseguire il provisioning di pipeline GKE Autopilot, Cloud Spanner e Cloud Deploy utilizzando Terraform
  • Come Workload Identity consente ai servizi su GKE di impersonare gli account di servizio per accedere alle autorizzazioni IAM per lavorare con Cloud Spanner
  • Come generare un carico di tipo produzione su GKE e Cloud Spanner utilizzando Locust.io

Che cosa ti serve

  • Un progetto Google Cloud collegato a un account di fatturazione.
  • Un browser web, ad esempio Chrome o Firefox.

2. Configurazione e requisiti

Creare un progetto

Se non disponi già di un account Google (Gmail o Google Apps), devi crearne uno. Accedi alla console della piattaforma Google Cloud ( console.cloud.google.com) e crea un nuovo progetto.

Se hai già un progetto, fai clic sul menu a discesa per la selezione del progetto in alto a sinistra nella console:

6c9406d9b014760.png

e fai clic su "NUOVO PROGETTO" nella finestra di dialogo risultante per creare un nuovo progetto:

949d83c8a4ee17d9.png

Se non hai ancora un progetto, dovresti visualizzare una finestra di dialogo come questa per crearne uno:

870a3cbd6541ee86.png

La finestra di dialogo di creazione del progetto successiva ti consente di inserire i dettagli del nuovo progetto:

6a92c57d3250a4b3.png

Ricorda l'ID progetto, che è un nome univoco tra tutti i progetti Google Cloud (il nome precedente è già in uso e non funzionerà per te). Verrà indicato più avanti in questo codelab come PROJECT_ID.

Successivamente, se non l'hai ancora fatto, dovrai abilitare la fatturazione in Developers Console per utilizzare le risorse Google Cloud e abilitare l'API Cloud Spanner.

15d0ef27a8fbab27.png

L'esecuzione di questo codelab non dovrebbe costare più di qualche euro, ma potrebbe essere più costoso se decidi di utilizzare più risorse o se le lasci in esecuzione (consulta la sezione relativa alla pulizia alla fine di questo documento). I prezzi di Google Cloud Spanner sono documentati qui, mentre GKE Autopilot è documentato qui.

I nuovi utenti di Google Cloud Platform hanno diritto a una prova senza costi di 300$, che dovrebbe rendere questo codelab completamente senza costi.

Configurazione di Cloud Shell

Mentre Google Cloud e Spanner possono essere gestiti da remoto dal tuo laptop, in questo codelab utilizzeremo Google Cloud Shell, un ambiente a riga di comando in esecuzione nel cloud.

Questa macchina virtuale basata su Debian viene caricata con tutti gli strumenti di sviluppo necessari. Offre una home directory permanente da 5 GB e viene eseguita in Google Cloud, migliorando notevolmente le prestazioni di rete e l'autenticazione. Ciò significa che per questo codelab sarà sufficiente un browser (sì, funziona su Chromebook).

  1. Per attivare Cloud Shell dalla console Cloud, fai clic su Attiva Cloud Shell gcLMt5IuEcJJNnMId-Bcz3sxCd0rZn7IzT_r95C8UZeqML68Y1efBG_B0VRp7hc7qiZTLAF-TXD7SsOadxn8uadgHhaLeASnVS3ZHK39eOlKJOgj9SJua_oeGhMxRrbOg3qigddS2A (il provisioning e la connessione all'ambiente dovrebbero richiedere solo pochi minuti).

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

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

Una volta stabilita la connessione a Cloud Shell, dovresti vedere che hai già eseguito l'autenticazione e che il progetto è già impostato su PROJECT_ID.

gcloud auth list

Output comando

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

Output comando

[core]
project = <PROJECT_ID>

Se, per qualche motivo, il progetto non è impostato, invia semplicemente il seguente comando:

gcloud config set project <PROJECT_ID>

Stai cercando il tuo PROJECT_ID? Controlla l'ID utilizzato nei passaggi di configurazione o cercalo nella dashboard della console Cloud:

158fNPfwSxsFqz9YbtJVZes8viTS3d1bV4CVhij3XPxuzVFOtTObnwsphlm6lYGmgdMFwBJtc-FaLrZU7XHAg_ZYoCrgombMRR3h-eolLPcvO351c5iBv506B3ZwghZoiRg6cz23Qw

Cloud Shell imposta anche alcune variabili di ambiente per impostazione predefinita, cosa che può essere utile quando eseguirai comandi futuri.

echo $GOOGLE_CLOUD_PROJECT

Output comando

<PROJECT_ID>

Scarica il codice

In Cloud Shell puoi scaricare il codice per questo lab:

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

Output comando

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

Questo codelab è basato sulla release v0.1.3, quindi dai un'occhiata al 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

Output comando

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

Ora imposta la directory di lavoro attuale come variabile di ambiente DEMO_HOME. In questo modo sarà più facile navigare mentre lavori tra le diverse parti del codelab.

export DEMO_HOME=$(pwd)

Riepilogo

In questo passaggio hai configurato un nuovo progetto, attivato Cloud Shell e scaricato il codice per il lab.

Successivo

Successivamente, eseguirai il provisioning dell'infrastruttura utilizzando Terraform.

3. Esegui il provisioning dell'infrastruttura

Panoramica

Con il tuo progetto pronto, è il momento di avviare l'infrastruttura. Sono inclusi il networking VPC, Cloud Spanner, GKE Autopilot, Artifact Registry per archiviare le immagini che verranno eseguite su GKE, le pipeline Cloud Deploy per i servizi e i carichi di lavoro di backend e, infine, gli account di servizio e i privilegi IAM per essere in grado di utilizzare questi servizi.

Niente male. Fortunatamente, però, Terraform può semplificare la configurazione. Terraform è una soluzione "Infrastructure as Code" che ci permette di specificare ciò di cui abbiamo bisogno per questo progetto in una serie di file ".tf" . Questo semplifica il provisioning dell'infrastruttura.

Conoscere Terraform non è un requisito per completare questo codelab. Tuttavia, se vuoi sapere cosa fanno i prossimi passaggi, puoi dare un'occhiata a cosa viene creato in questi file che si trovano nella directory infrastructure:

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

Configura Terraform

In Cloud Shell, passerai alla directory infrastructure e inizializzerai Terraform:

cd $DEMO_HOME/infrastructure
terraform init

Output 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.

A questo punto, configura Terraform copiando terraform.tfvars.sample e modificando il valore del progetto. Anche le altre variabili possono essere modificate, ma il progetto è l'unico che deve essere modificato per funzionare con il tuo ambiente.

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

Esegui il provisioning dell'infrastruttura

Ora è il momento di eseguire il provisioning dell'infrastruttura.

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

Output 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.

Verificare che cosa è stato creato

Per verificare cosa è stato creato, vuoi controllare i prodotti nella console Cloud.

Cloud Spanner

Per prima cosa, controlla Cloud Spanner andando al menu a tre linee e facendo clic su Spanner. Potresti dover fare clic su "Visualizza altri prodotti" per trovarlo nell'elenco.

Verrà visualizzato l'elenco delle istanze Spanner. Fai clic sull'istanza per visualizzare i database. Il sito dovrebbe avere il seguente aspetto:

10b7fc0c4a86c59.png

GKE Autopilot

Poi, dai un'occhiata a GKE andando al menu a tre linee e facendo clic su Kubernetes Engine => Clusters. Qui vedrai il cluster sample-games-gke in esecuzione in modalità Autopilot.

9cecb1a702e6b7ff.png

Artifact Registry

Ora vuoi vedere dove vengono archiviate le immagini. Fai clic sul menu a tre linee e trova Artifact Registry=>Repositories. Artifact Registry si trova nella sezione CI/CD del menu.

Qui vedrai un registro Docker denominato spanner-game-images. Per il momento è vuoto.

3f805eee312841b.png

Cloud Deploy

Cloud Deploy è il luogo in cui sono state create le pipeline in modo che Cloud Build possa fornire i passaggi per creare le immagini e per eseguirne il deployment nel nostro cluster GKE.

Vai al menu a tre linee e trova Cloud Deploy, anch'esso disponibile nella sezione CI/CD del menu.

Qui noterai due pipeline: una per i servizi di backend e una per i carichi di lavoro. Entrambi eseguono il deployment delle immagini sullo stesso cluster GKE, ma questo consente di separare i nostri deployment.

d2e4a659145ddf5e.png

IAM

Infine, controlla la pagina IAM nella console Cloud per verificare gli account di servizio creati. Vai al menu a tre linee e trova IAM and Admin=>Service accounts. Il sito dovrebbe avere il seguente aspetto:

bed3d1af94974916.png

Terraform crea in totale sei account di servizio:

  • L'account di servizio predefinito del computer. Non viene usato in questo codelab.
  • L'account cloudbuild-cicd viene utilizzato per i passaggi di Cloud Build e Cloud Deploy.
  • Quattro "app" utilizzati dai nostri servizi di backend per interagire con Cloud Spanner.

Successivamente devi configurare kubectl per interagire con il cluster GKE.

Configura 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

Output 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

Riepilogo

Bene. Hai potuto eseguire il provisioning di un'istanza Cloud Spanner, un cluster GKE Autopilot, il tutto in un VPC per il networking privato.

Inoltre, sono state create due pipeline Cloud Deploy per i servizi di backend e i carichi di lavoro, nonché un repository Artifact Registry per archiviare le immagini create.

Infine, gli account di servizio sono stati creati e configurati in modo da funzionare con Workload Identity in modo che i servizi di backend possano utilizzare Cloud Spanner.

Hai inoltre configurato kubectl per interagire con il cluster GKE in Cloud Shell dopo aver eseguito il deployment dei carichi di lavoro e dei servizi di backend.

Successivo

Prima di poter utilizzare i servizi, è necessario definire lo schema del database. Lo configurerai successivamente.

4. Crea lo schema del database

Panoramica

Prima di poter eseguire i servizi di backend, devi assicurarti che sia attivo lo schema del database.

Se osservi i file nella directory $DEMO_HOME/schema/migrations del repository della demo, vedrai una serie di file .sql che definiscono il nostro schema. Questo imita un ciclo di sviluppo in cui le modifiche allo schema vengono monitorate nel repository stesso e possono essere collegate a determinate funzionalità delle applicazioni.

Per questo ambiente di esempio, chiave inglese è lo strumento che applicherà le nostre migrazioni degli schemi utilizzando Cloud Build.

Cloud Build

Il file $DEMO_HOME/schema/cloudbuild.yaml descrive i passaggi che verranno effettuati:

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

Essenzialmente composta da due passaggi:

  • scarica la chiave inglese nell'area di lavoro di Cloud Build
  • esegui la migrazione della chiave inglese

Le variabili di ambiente del database, dell'istanza e del progetto Spanner sono necessarie affinché la chiave inglese si connetta all'endpoint di scrittura.

Cloud Build è in grado di apportare queste modifiche perché è in esecuzione con l'account di servizio cloudbuild-cicd@${PROJECT_ID}.iam.gserviceaccount.com:

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

Inoltre, a questo account di servizio è stato aggiunto il ruolo spanner.databaseUser, che consente all'account di servizio di aggiornare DDL.

Migrazioni di schemi

Esistono cinque passaggi di migrazione che vengono eseguiti in base ai file presenti nella directory $DEMO_HOME/schema/migrations. Ecco un esempio del file 000001.sql che crea una tabella players e gli indici:

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

Invia la migrazione dello schema

Per inviare la build per eseguire la migrazione dello schema, passa alla directory schema ed esegui questo comando gcloud:

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

Output 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

Nell'output riportato sopra, noterai un link al processo di Cloud Build Created. Se fai clic sul pulsante, si aprirà la build nella console Cloud, in modo da poter monitorare l'avanzamento della build e vedere cosa sta facendo.

11b1cf107876d797.png

Riepilogo

In questo passaggio, hai utilizzato Cloud Build per inviare la migrazione iniziale dello schema con 5 diverse operazioni DDL. Queste operazioni indicano quando sono state aggiunte funzionalità che hanno richiesto modifiche allo schema del database.

In un normale scenario di sviluppo, conviene apportare modifiche allo schema compatibili con le versioni precedenti dell'applicazione per evitare interruzioni.

Per le modifiche non compatibili con le versioni precedenti, ti consigliamo di eseguire il deployment delle modifiche all'applicazione e allo schema in fasi per evitare interruzioni.

Successivo

Una volta impostato lo schema, il passaggio successivo è il deployment dei servizi di backend.

5. Esegui il deployment dei servizi di backend

Panoramica

I servizi di backend per questo codelab sono API REST golang che rappresentano quattro diversi servizi:

  • Profilo: offre ai giocatori la possibilità di registrarsi e autenticarsi al nostro "gioco di esempio".
  • Abbinamento: consente di interagire con i dati dei giocatori per semplificare la ricerca degli abbinamenti, tenere traccia delle informazioni sulle partite create e aggiornare le statistiche dei giocatori quando le partite sono chiuse.
  • Elemento: consente ai giocatori di acquisire oggetti e denaro del gioco durante il gioco.
  • Tradepost::consente ai giocatori di acquistare e vendere articoli su una piattaforma commerciale.

d36e958411d44b5d.png

Scopri di più su questi servizi nel codelab Introduzione allo sviluppo di giochi di Cloud Spanner. Per i nostri scopi, vogliamo che questi servizi siano in esecuzione sul nostro cluster GKE Autopilot.

Questi servizi devono essere in grado di modificare i dati Spanner. Per farlo, ogni servizio ha un account di servizio che gli concede il ruolo "databaseUser" ruolo.

Workload Identity consente a un account di servizio Kubernetes di simulare l'identità dei servizi Google Cloud seguendo i passaggi nel nostro Terraform:

  • Crea la risorsa dell'account di servizio Google Cloud (GSA) del servizio
  • Assegnare il ruolo databaseUser a quell'account di servizio.
  • Assegnare il ruolo workloadIdentityUser a quell'account di servizio
  • Crea un account di servizio Kubernetes (KSA) che fa riferimento a Gboard

Un diagramma approssimativo sarebbe simile al seguente:

a8662d31d66b5910.png

Terraform ha creato gli account di servizio e gli account di servizio Kubernetes per te. Infine, puoi controllare gli account di servizio Kubernetes utilizzando 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

Ecco il funzionamento della build:

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
  • Il comando Cloud Build legge questo file e segue i passaggi elencati. Innanzitutto, crea le immagini del servizio. quindi esegue un comando gcloud deploy create. Legge il file $DEMO_HOME/backend_services/skaffold.yaml, che definisce la posizione di ciascun file di deployment:
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 seguirà le definizioni del file deployment.yaml di ogni servizio. Il file di deployment del servizio contiene le informazioni per la creazione di un servizio, che in questo caso è un clusterIP in esecuzione sulla porta 80.

Il " Il tipo ClusterIP" impedisce ai pod del servizio di backend di avere un IP esterno, in modo che solo le entità che possono connettersi alla rete GKE interna possano accedere ai servizi di backend. Questi servizi non dovrebbero essere accessibili direttamente ai giocatori perché accedono e modificano i dati di Spanner.

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

Oltre a creare un servizio Kubernetes, Cloud Deploy crea anche un deployment Kubernetes. Esaminiamo la sezione relativa al deployment del servizio 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"

La parte superiore fornisce alcuni metadati sul servizio. La parte più importante di questo processo è la definizione del numero di repliche che saranno create da questo deployment.

replicas: 2 # EDIT: Number of instances of deployment

Ora vediamo quale account di servizio deve eseguire l'app e quale immagine utilizzare. Queste corrispondono all'account di servizio Kubernetes creato da Terraform e all'immagine creata durante il passaggio di Cloud Build.

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

Successivamente, specificheremo alcune informazioni sulle variabili di networking e di ambiente.

spanner_config è un ConfigMap Kubernetes che specifica le informazioni su progetto, istanza e database necessarie all'applicazione per la connessione a 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 sono variabili di ambiente aggiuntive necessarie al servizio per sapere dove eseguire l'associazione.

La sezione finale indica a GKE quante risorse consentire per ogni replica in questo deployment. Questo è anche ciò che viene utilizzato da GKE Autopilot per scalare il cluster in base alle esigenze.

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

Con queste informazioni, è il momento di eseguire il deployment dei servizi di backend.

Esegui il deployment dei servizi di backend

Come accennato, il deployment dei servizi di backend utilizza Cloud Build. Proprio come per le migrazioni degli schemi, puoi inviare la richiesta di build utilizzando la riga di comando gcloud:

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

Output 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

A differenza dell'output del passaggio schema migration, l'output di questa build indica che sono state create alcune immagini. Verranno archiviate nel tuo repository Artifact Registry.

L'output del passaggio gcloud build avrà un collegamento alla console Cloud. Dai un'occhiata a questi.

Quando ricevi la notifica di esito positivo da Cloud Build, vai a Cloud Deploy, quindi alla pipeline sample-game-services per monitorare l'avanzamento del deployment.

df5c6124b9693986.png

Una volta eseguito il deployment dei servizi, puoi controllare kubectl per vedere i pod stato:

kubectl get pods

Output 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

Poi controlla i servizi per vedere ClusterIP in azione:

kubectl get services

Output 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

Puoi anche andare alla UI di GKE nella console Cloud per vedere Workloads, Services e ConfigMaps.

Carichi di lavoro

da98979ae49e5a30.png

Servizi

406ca2fe7ad4818b.png

ConfigMap

a0ebd34ee735ee11.png

3b9ef91c77a4e7f0.png

Riepilogo

In questo passaggio hai eseguito il deployment dei quattro servizi di backend in GKE Autopilot. Hai eseguito il passaggio Cloud Build e controllare lo stato di avanzamento in Cloud Deploy e su Kubernetes nella console Cloud.

Hai anche imparato come questi servizi utilizzano Workload Identity per impersonare un account di servizio che dispone delle autorizzazioni appropriate per leggere e scrivere dati nel database Spanner.

Passaggi successivi

Nella sezione successiva, eseguirai il deployment dei carichi di lavoro.

6. Esegui il deployment dei carichi di lavoro

Panoramica

Ora che i servizi di backend sono in esecuzione sul cluster, eseguirai il deployment dei carichi di lavoro.

dd900485e2eeb611.png

I carichi di lavoro sono accessibili dall'esterno e ne esiste uno per ogni servizio di backend ai fini di questo codelab.

Questi carichi di lavoro sono script di generazione del carico basati su Locust che imitano i pattern di accesso reali previsti da questi servizi di esempio.

Sono presenti file per il processo di Cloud Build:

  • $DEMO_HOME/workloads/cloudbuild.yaml (generato da Terraform)
  • $DEMO_HOME/workloads/skaffold.yaml
  • un file deployment.yaml per ogni carico di lavoro

I file deployment.yaml del carico di lavoro hanno un aspetto leggermente diverso dai file di deployment del servizio di backend.

Ecco un esempio tratto dalla 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"

La parte superiore del file definisce il servizio. In questo caso, viene creato un LoadBalancer e il carico di lavoro viene eseguito sulla porta 8089.

LoadBalancer fornisce un IP esterno che può essere utilizzato per la connessione al carico di lavoro.

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

Nella parte superiore della sezione relativa al deployment si trovano i metadati relativi al carico di lavoro. In questo caso, viene eseguito il deployment di una sola replica:

replicas: 1 

Tuttavia, le specifiche del container sono diverse. Per prima cosa, utilizziamo un account di servizio Kubernetes default. Questo account non dispone di privilegi speciali, poiché il carico di lavoro non deve connettersi a nessuna risorsa Google Cloud, ad eccezione dei servizi di backend in esecuzione sul cluster GKE.

L'altra differenza è che non sono necessarie variabili di ambiente per questi carichi di lavoro. Il risultato è una specifica del deployment più breve.

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

Le impostazioni delle risorse sono simili a quelle dei servizi di backend. Ricorda che è così che GKE Autopilot sa quante risorse sono necessarie per soddisfare le richieste di tutti i pod in esecuzione sul cluster.

Procedi con il deployment dei carichi di lavoro.

Esegui il deployment dei carichi di lavoro

Come in precedenza, puoi inviare la richiesta di build utilizzando la riga di comando gcloud:

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

Output 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

Assicurati di controllare i log di Cloud Build e la pipeline di Cloud Deploy nella console Cloud per verificare lo stato. Per i carichi di lavoro, la pipeline di Cloud Deploy è sample-game-workloads:

Al termine del deployment, controlla lo stato con kubectl in Cloud Shell:

kubectl get pods

Output 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

Quindi, controlla i servizi del carico di lavoro per vedere LoadBalancer in azione:

kubectl get services 

Output 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

Riepilogo

A questo punto hai eseguito il deployment dei carichi di lavoro nel cluster GKE. Questi carichi di lavoro non richiedono autorizzazioni IAM aggiuntive e sono accessibili dall'esterno sulla porta 8089 mediante il servizio LoadBalancer.

Passaggi successivi

Con i servizi di backend e i carichi di lavoro in esecuzione, è il momento di "giocare" il gioco!

7. Inizia a giocare

Panoramica

I servizi di backend per il tuo "gioco" di esempio che ora sono in esecuzione e hai anche la possibilità di generare "player" a interagire con questi servizi utilizzando i carichi di lavoro.

Ogni carico di lavoro utilizza Locust per simulare il carico effettivo sulle nostre API di servizio. In questo passaggio, eseguirai diversi carichi di lavoro per generare carico sul cluster GKE e su Spanner, nonché per archiviare i dati su Spanner.

Di seguito è riportata una descrizione di ciascun carico di lavoro:

  • Il carico di lavoro item-generator è un carico di lavoro rapido per generare un elenco di game_items che i giocatori possono acquisire durante il gioco al gioco.
  • Il profile-workload simula i giocatori che si registrano e accedono.
  • L'matchmaking-workload simula i giocatori in coda per essere assegnati ai giochi.
  • L'game-workload simula i giocatori che acquistano game_items e denaro nel corso del gioco.
  • La tradepost-workload simula la possibilità dei giocatori di vendere e acquistare articoli sul trading post.

Questo codelab evidenzia l'esecuzione specifica di item-generator e profile-workload.

Esegui il generatore di articoli

item-generator utilizza l'endpoint del servizio di backend item per aggiungere game_items a Spanner. Questi elementi sono necessari affinché game-workload e tradepost-workload funzionino correttamente.

Il primo passaggio consiste nel ottenere l'IP esterno del servizio item-generator. In Cloud Shell, esegui questo comando:

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

Output comando

{ITEMGENERATOR_EXTERNAL_IP}

Ora apri una nuova scheda del browser e posiziona il puntatore del mouse su http://{ITEMGENERATOR_EXTERNAL_IP}:8089. Dovrebbe essere visualizzata una pagina simile alla seguente:

817307157d66c661.png

Lascerai il valore predefinito 1 per users e spawn. Per host, inserisci http://item. Fai clic sulle opzioni avanzate e inserisci 10s per il tempo di esecuzione.

Ecco come dovrebbe apparire la configurazione:

f3143165c6285c21.png

Fai clic su "Inizia a sciamare".

Le statistiche inizieranno a essere visualizzate per le richieste inviate sull'endpoint POST /items. Dopo 10 secondi il caricamento verrà arrestato.

Fai clic sulla Charts per visualizzare alcuni grafici sul rendimento di queste richieste.

abad0a9f3c165345.png

Ora devi verificare se i dati sono stati inseriti nel database Spanner.

Per farlo, fai clic sul menu a tre linee e vai a "Spanner". Da questa pagina, vai al sample-instance e al sample-database. Quindi, fai clic su "Query".

Vogliamo selezionare il numero di game_items:

SELECT COUNT(*) FROM game_items;

In basso vedrai il risultato.

137ce291a2ff2706.png

Non abbiamo bisogno di molte teste di serie di game_items. Ma ora sono disponibili per l'acquisizione dei giocatori!

Esegui il carico di lavoro del profilo

Con il tuo seed di game_items, il passo successivo è far registrare i giocatori per poter giocare.

profile-workload userà Locust per simulare i giocatori che creano account, accedono, recuperano le informazioni del profilo e si disconnettono. Tutti questi testano gli endpoint del servizio di backend profile in un tipico carico di lavoro di tipo produzione.

Per eseguirlo, ottieni l'IP esterno di profile-workload:

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

Output comando

{PROFILEWORKLOAD_EXTERNAL_IP}

Ora apri una nuova scheda del browser e posiziona il puntatore del mouse su http://{PROFILEWORKLOAD_EXTERNAL_IP}:8089. Dovrebbe essere visualizzata una pagina Locust simile a quella precedente.

In questo caso, utilizzerai http://profile per l'host. Inoltre, non specificherai un runtime nelle opzioni avanzate. Inoltre, specifica un valore per users, in modo da simulare quattro richieste dell'utente alla volta.

Il test profile-workload dovrebbe avere il seguente aspetto:

f6e0f06efb0ad6e.png

Fai clic su "Inizia a sciamare".

Come in precedenza, inizieranno a essere visualizzate le statistiche per i vari endpoint REST di profile. Fai clic sui grafici per visualizzare il rendimento di tutti gli elementi.

4c2146e1cb3de23e.png

Riepilogo

In questo passaggio hai generato game_items e quindi hai eseguito una query sulla tabella game_items utilizzando l'interfaccia utente di query di Spanner nella console Cloud.

Hai anche consentito ai giocatori di registrarsi al tuo gioco e hai visto in che modo Locust è in grado di creare carichi di lavoro simili a quelli di produzione con i tuoi servizi di backend.

Passaggi successivi

Dopo aver eseguito i carichi di lavoro, vorrai verificare come si comportano il cluster GKE e l'istanza Spanner.

8. Rivedi l'utilizzo di GKE e Spanner

Con il servizio di profilo in esecuzione, è il momento di cogliere l'opportunità di vedere come si comportano il tuo cluster GKE Autopilot e Cloud Spanner.

Controlla il cluster GKE

Accedi al cluster Kubernetes. Tieni presente che, dal momento che hai eseguito il deployment dei carichi di lavoro e dei servizi, nel cluster sono stati aggiunti alcuni dettagli sulle vCPU e sulla memoria totali. Queste informazioni non erano disponibili quando non c'erano carichi di lavoro sul cluster.

61d2d766c1f10079.png

Ora, fai clic sul cluster sample-game-gke e passa alla scheda Osservabilità:

fa9acc7e26ea04a.png

Lo spazio dei nomi Kubernetes default dovrebbe aver superato lo spazio dei nomi kube-system per l'utilizzo della CPU, poiché i nostri carichi di lavoro e servizi di backend vengono eseguiti su default. In caso contrario, assicurati che profile workload sia ancora in esecuzione e attendi alcuni minuti per l'aggiornamento dei grafici.

Per vedere quali carichi di lavoro utilizzano il maggior numero di risorse, vai alla dashboard Workloads.

Anziché andare direttamente in ogni carico di lavoro, vai direttamente alla scheda Osservabilità della dashboard. Dovresti vedere che le CPU profile e profile-workload sono aumentate.

f194b618969cfa9e.png

Ora controlla Cloud Spanner.

Controlla l'istanza Cloud Spanner

Per verificare le prestazioni di Cloud Spanner, vai a Spanner e fai clic sull'istanza sample-instance e sul database sample-game.

Da qui, nel menu a sinistra vedrai una scheda Approfondimenti sul sistema:

216212182a57dfd1.png

Qui sono presenti molti grafici per aiutarti a comprendere le prestazioni generali della tua istanza Spanner, tra cui CPU utilization, transaction latency and locking e query throughput.

Oltre ad Insight sul sistema, puoi ottenere informazioni più dettagliate sul carico di lavoro delle query cercando gli altri link nella sezione Osservabilità:

  • Query Insights consente di identificare le query principali che utilizzano risorse su Spanner.
  • Gli approfondimenti su Transaction e Lock aiutano a identificare le transazioni con latenze elevate.
  • Key Visualizer aiuta a visualizzare i pattern di accesso e a rintracciare gli hotspot nei dati.

Riepilogo

In questo passaggio hai imparato a controllare alcune metriche delle prestazioni di base sia per GKE Autopilot che per Spanner.

Ad esempio, con il carico di lavoro del profilo in esecuzione, esegui una query sulla tabella dei player per ottenere ulteriori informazioni sui dati che vengono archiviati al suo interno.

Passaggi successivi

È il momento di pulire.

9. esegui la pulizia

Prima di eseguire la pulizia, esplora liberamente gli altri carichi di lavoro non coperti. Nello specifico, matchmaking-workload, game-workload e tradepost-workload.

Quando hai finito di "giocare" al gioco, puoi ripulire il tuo parco giochi. Per fortuna è abbastanza facile.

Innanzitutto, se il tuo profile-workload è ancora in esecuzione nel browser, controllalo e interrompilo:

13ae755a11f3228.png

Ripeti l'operazione per ogni carico di lavoro che potresti aver testato.

Quindi, in Cloud Shell, vai alla cartella dell'infrastruttura. Dovrai destroy usare Terraform:

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

Output 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.

Nella console Cloud, vai a Spanner, Kubernetes Cluster, Artifact Registry, Cloud Deploy e IAM per verificare che tutte le risorse siano state rimosse.

10. Complimenti!

Complimenti, hai eseguito correttamente il deployment delle applicazioni golang di esempio su GKE Autopilot e le hai connesse a Cloud Spanner utilizzando Workload Identity.

Inoltre, questa infrastruttura è stata facilmente configurata e rimossa in modo ripetibile utilizzando Terraform.

Puoi scoprire di più sui servizi Google Cloud con cui hai interagito in questo codelab:

Passaggi successivi

Ora che hai una conoscenza di base di come GKE Autopilot e Cloud Spanner possono funzionare insieme, perché non fare il passo successivo e iniziare a creare la tua applicazione per funzionare con questi servizi?