Implantar um banco de dados PostgreSQL altamente disponível no GKE


O PostgreSQL é um banco de dados relacional de objetos de código aberto, conhecido pela confiabilidade e integridade dos dados. Ele está em conformidade com o ACID e é compatível com chaves estrangeiras, junções, visualizações, gatilhos e procedimentos armazenados.

Este documento é destinado a administradores de bancos de dados, arquitetos de nuvem e profissionais de operações interessados em implantar uma topologia de MySQL altamente disponível no Google Kubernetes Engine.

Objetivos

Neste tutorial, você aprenderá a:

  • Use o Terraform para criar um cluster regional do GKE.
  • Implantar um banco de dados PostgreSQL altamente disponível.
  • Configurar o monitoramento do aplicativo PostgreSQL.
  • Fazer upgrades do banco de dados PostgreSQL e do cluster do GKE.
  • Simule a interrupção do cluster e o failover da réplica do PostgreSQL.
  • Fazer backup e restauração do banco de dados PostgreSQL.

Arquitetura

Nesta seção, descrevemos a arquitetura da solução que você criará neste tutorial.

Você provisiona dois clusters do GKE em regiões diferentes: um cluster principal e um cluster de backup. Para este tutorial, o cluster principal está na região us-central1 e o cluster de backup está na região us-west1. Essa arquitetura permite provisionar um banco de dados PostgreSQL altamente disponível e testar a recuperação de desastres, conforme descrito mais adiante neste tutorial.

Para o cluster de origem, use um gráfico do Helm (bitnami/postgresql-ha) para configurar um cluster do PostgreSQL de alta disponibilidade.

O diagrama mostra um exemplo de arquitetura de um cluster PostgreSQL altamente disponível.
Figura 1: exemplo de arquitetura de um cluster PostgreSQL altamente disponível.

Custos

Neste documento, você usará os seguintes componentes faturáveis do Google Cloud:

Para gerar uma estimativa de custo baseada na projeção de uso deste tutorial, use a calculadora de preços. Novos usuários do Google Cloud podem estar qualificados para uma avaliação gratuita.

Ao concluir as tarefas descritas neste documento, é possível evitar o faturamento contínuo excluindo os recursos criados. Saiba mais em Limpeza.

Antes de começar

Configurar o projeto

  1. Sign in to your Google Cloud account. If you're new to Google Cloud, create an account to evaluate how our products perform in real-world scenarios. New customers also get $300 in free credits to run, test, and deploy workloads.
  2. In the Google Cloud console, on the project selector page, click Create project to begin creating a new Google Cloud project.

    Go to project selector

  3. Make sure that billing is enabled for your Google Cloud project.

  4. Enable the Google Kubernetes Engine, Backup for GKE, Artifact Registry, Compute Engine, and IAM APIs.

    Enable the APIs

  5. In the Google Cloud console, on the project selector page, click Create project to begin creating a new Google Cloud project.

    Go to project selector

  6. Make sure that billing is enabled for your Google Cloud project.

  7. Enable the Google Kubernetes Engine, Backup for GKE, Artifact Registry, Compute Engine, and IAM APIs.

    Enable the APIs

Configurar papéis

  1. Grant roles to your user account. Run the following command once for each of the following IAM roles: role/storage.objectViewer, role/logging.logWriter, role/artifactregistry.Admin, roles/container.clusterAdmin, role/container.serviceAgent, roles/serviceusage.serviceUsageAdmin, roles/iam.serviceAccountAdmin

    gcloud projects add-iam-policy-binding PROJECT_ID --member="user:USER_IDENTIFIER" --role=ROLE
    • Replace PROJECT_ID with your project ID.
    • Replace USER_IDENTIFIER with the identifier for your user account. For example, user:myemail@example.com.

    • Replace ROLE with each individual role.

Configure seu ambiente

Neste tutorial, você usará o Cloud Shell para gerenciar recursos hospedados no Google Cloud. O Cloud Shell vem pré-instalado com o software necessário para este tutorial, incluindo o Docker, o kubectl e a CLI gcloud. , Helm e Terraform.

Siga estes passos para configurar o ambiente usando o Cloud Shell:

  1. Inicie uma sessão do Cloud Shell no Console do Google Cloud clicando em Ícone de ativação do Cloud Shell Ativar o Cloud Shell no Console do Google Cloud. Isso inicia uma sessão no painel inferior do Cloud Console.

  2. Defina variáveis de ambiente.

    export PROJECT_ID=PROJECT_ID
    export SOURCE_CLUSTER=cluster-db1
    export REGION=us-central1
    

    Substitua os seguintes valores:

  3. Defina as variáveis de ambiente padrão.

    gcloud config set project PROJECT_ID
    
  4. Clone o repositório do código.

    git clone https://github.com/GoogleCloudPlatform/kubernetes-engine-samples
    
  5. Mude para o diretório de trabalho.

    cd kubernetes-engine-samples/databases/gke-stateful-postgres
    

Criar a infraestrutura do cluster

Nesta seção, você executará um script do Terraform para criar uma nuvem privada virtual (VPC) personalizada, um repositório do Artifact Registry para armazenar imagens do PostgreSQL e dois clusters regionais do GKE. Um cluster será implantado em us-central1, e o segundo para backup será implantado em us-west1.

Para criar o cluster, siga estas etapas:

Piloto automático

No Cloud Shell, execute os seguintes comandos:

terraform -chdir=terraform/gke-autopilot init
terraform -chdir=terraform/gke-autopilot apply -var project_id=$PROJECT_ID

Quando solicitado, digite yes.

Entender a configuração do Terraform

Os arquivos de configuração do Terraform criam os seguintes recursos para implantar a infraestrutura:

  • Crie um repositório do Artifact Registry para armazenar as imagens do Docker.
    resource "google_artifact_registry_repository" "main" {
      location      = "us"
      repository_id = "main"
      format        = "DOCKER"
      project       = var.project_id
    }
  • Crie a rede VPC e a sub-rede da interface de rede da VM.
    module "gcp-network" {
      source  = "terraform-google-modules/network/google"
      version = "< 8.0.0"
    
      project_id   = var.project_id
      network_name = "vpc-gke-postgresql"
    
      subnets = [
        {
          subnet_name           = "snet-gke-postgresql-us-central1"
          subnet_ip             = "10.0.0.0/17"
          subnet_region         = "us-central1"
          subnet_private_access = true
        },
        {
          subnet_name           = "snet-gke-postgresql-us-west1"
          subnet_ip             = "10.0.128.0/17"
          subnet_region         = "us-west1"
          subnet_private_access = true
        },
      ]
    
      secondary_ranges = {
        ("snet-gke-postgresql-us-central1") = [
          {
            range_name    = "ip-range-pods-db1"
            ip_cidr_range = "192.168.0.0/18"
          },
          {
            range_name    = "ip-range-svc-db1"
            ip_cidr_range = "192.168.64.0/18"
          },
        ],
        ("snet-gke-postgresql-us-west1") = [
          {
            range_name    = "ip-range-pods-db2"
            ip_cidr_range = "192.168.128.0/18"
          },
          {
            range_name    = "ip-range-svc-db2"
            ip_cidr_range = "192.168.192.0/18"
          },
        ]
      }
    }
    
    output "network_name" {
      value = module.gcp-network.network_name
    }
    
    output "primary_subnet_name" {
      value = module.gcp-network.subnets_names[0]
    }
    
    output "secondary_subnet_name" {
      value = module.gcp-network.subnets_names[1]
    }
  • Criar um cluster principal do GKE.

    O Terraform cria um cluster particular na região us-central1 e ativa o Backup para GKE para recuperação de desastres e o Managed Service para Prometheus para monitoramento de clusters.

    O serviço gerenciado para o Prometheus é compatível apenas com clusters do Autopilot que executam o GKE versão 1.25 ou posterior.

    module "gke-db1-autopilot" {
      source                          = "../modules/beta-autopilot-private-cluster"
      project_id                      = var.project_id
      name                            = "cluster-db1"
      kubernetes_version              = "1.25" # Will be ignored if use "REGULAR" release_channel
      region                          = "us-central1"
      regional                        = true
      zones                           = ["us-central1-a", "us-central1-b", "us-central1-c"]
      network                         = module.network.network_name
      subnetwork                      = module.network.primary_subnet_name
      ip_range_pods                   = "ip-range-pods-db1"
      ip_range_services               = "ip-range-svc-db1"
      horizontal_pod_autoscaling      = true
      release_channel                 = "RAPID" # Default version is 1.22 in REGULAR. GMP on Autopilot requires V1.25 via var.kubernetes_version
      enable_vertical_pod_autoscaling = true
      enable_private_endpoint         = false
      enable_private_nodes            = true
      master_ipv4_cidr_block          = "172.16.0.0/28"
      create_service_account          = false
    }

  • Crie um cluster de backup na região us-west1 para recuperação de desastres.

    module "gke-db2-autopilot" {
      source                          = "../modules/beta-autopilot-private-cluster"
      project_id                      = var.project_id
      name                            = "cluster-db2"
      kubernetes_version              = "1.25" # Will be ignored if use "REGULAR" release_channel
      region                          = "us-west1"
      regional                        = true
      zones                           = ["us-west1-a", "us-west1-b", "us-west1-c"]
      network                         = module.network.network_name
      subnetwork                      = module.network.secondary_subnet_name
      ip_range_pods                   = "ip-range-pods-db2"
      ip_range_services               = "ip-range-svc-db2"
      horizontal_pod_autoscaling      = true
      release_channel                 = "RAPID" # Default version is 1.22 in REGULAR. GMP on Autopilot requires V1.25 via var.kubernetes_version
      enable_vertical_pod_autoscaling = true
      enable_private_endpoint         = false
      enable_private_nodes            = true
      master_ipv4_cidr_block          = "172.16.0.16/28"
      create_service_account          = false
    }

Padrão

No Cloud Shell, execute os seguintes comandos:

terraform -chdir=terraform/gke-standard init
terraform -chdir=terraform/gke-standard apply -var project_id=$PROJECT_ID

Quando solicitado, digite yes.

Entender a configuração do Terraform

Os arquivos de configuração do Terraform criam os seguintes recursos para implantar a infraestrutura:

  • Crie um repositório do Artifact Registry para armazenar as imagens do Docker.
    resource "google_artifact_registry_repository" "main" {
      location      = "us"
      repository_id = "main"
      format        = "DOCKER"
      project       = var.project_id
    }
    resource "google_artifact_registry_repository_iam_binding" "binding" {
      provider   = google-beta
      project    = google_artifact_registry_repository.main.project
      location   = google_artifact_registry_repository.main.location
      repository = google_artifact_registry_repository.main.name
      role       = "roles/artifactregistry.reader"
      members = [
        "serviceAccount:${module.gke-db1.service_account}",
      ]
    }
  • Crie a rede VPC e a sub-rede da interface de rede da VM.
    module "gcp-network" {
      source  = "terraform-google-modules/network/google"
      version = "< 8.0.0"
    
      project_id   = var.project_id
      network_name = "vpc-gke-postgresql"
    
      subnets = [
        {
          subnet_name           = "snet-gke-postgresql-us-central1"
          subnet_ip             = "10.0.0.0/17"
          subnet_region         = "us-central1"
          subnet_private_access = true
        },
        {
          subnet_name           = "snet-gke-postgresql-us-west1"
          subnet_ip             = "10.0.128.0/17"
          subnet_region         = "us-west1"
          subnet_private_access = true
        },
      ]
    
      secondary_ranges = {
        ("snet-gke-postgresql-us-central1") = [
          {
            range_name    = "ip-range-pods-db1"
            ip_cidr_range = "192.168.0.0/18"
          },
          {
            range_name    = "ip-range-svc-db1"
            ip_cidr_range = "192.168.64.0/18"
          },
        ],
        ("snet-gke-postgresql-us-west1") = [
          {
            range_name    = "ip-range-pods-db2"
            ip_cidr_range = "192.168.128.0/18"
          },
          {
            range_name    = "ip-range-svc-db2"
            ip_cidr_range = "192.168.192.0/18"
          },
        ]
      }
    }
    
    output "network_name" {
      value = module.gcp-network.network_name
    }
    
    output "primary_subnet_name" {
      value = module.gcp-network.subnets_names[0]
    }
    
    output "secondary_subnet_name" {
      value = module.gcp-network.subnets_names[1]
    }
  • Criar um cluster principal do GKE.

    O Terraform cria um cluster particular na região us-central1 e ativa o Backup para GKE para recuperação de desastres e o Managed Service para Prometheus para monitoramento de clusters.

    module "gke-db1" {
      source                   = "../modules/beta-private-cluster"
      project_id               = var.project_id
      name                     = "cluster-db1"
      regional                 = true
      region                   = "us-central1"
      network                  = module.network.network_name
      subnetwork               = module.network.primary_subnet_name
      ip_range_pods            = "ip-range-pods-db1"
      ip_range_services        = "ip-range-svc-db1"
      create_service_account   = true
      enable_private_endpoint  = false
      enable_private_nodes     = true
      master_ipv4_cidr_block   = "172.16.0.0/28"
      network_policy           = true
      cluster_autoscaling = {
        "autoscaling_profile": "OPTIMIZE_UTILIZATION",
        "enabled" : true,
        "gpu_resources" : [],
        "min_cpu_cores" : 36,
        "min_memory_gb" : 144,
        "max_cpu_cores" : 48,
        "max_memory_gb" : 192,
      }
      monitoring_enable_managed_prometheus = true
      gke_backup_agent_config = true
    
      node_pools = [
        {
          name            = "pool-sys"
          autoscaling     = true
          min_count       = 1
          max_count       = 3
          max_surge       = 1
          max_unavailable = 0
          machine_type    = "e2-standard-4"
          node_locations  = "us-central1-a,us-central1-b,us-central1-c"
          auto_repair     = true
        },
        {
          name            = "pool-db"
          autoscaling     = true
          max_surge       = 1
          max_unavailable = 0
          machine_type    = "e2-standard-8"
          node_locations  = "us-central1-a,us-central1-b,us-central1-c"
          auto_repair     = true
        },
      ]
      node_pools_labels = {
        all = {}
        pool-db = {
          "app.stateful/component" = "postgresql"
        }
        pool-sys = {
          "app.stateful/component" = "postgresql-pgpool"
        }
      }
      node_pools_taints = {
        all = []
        pool-db = [
          {
            key    = "app.stateful/component"
            value  = "postgresql"
            effect = "NO_SCHEDULE"
          },
        ],
        pool-sys = [
          {
            key    = "app.stateful/component"
            value  = "postgresql-pgpool"
            effect = "NO_SCHEDULE"
          },
        ],
      }
      gce_pd_csi_driver = true
    }

  • Crie um cluster de backup na região us-west1 para recuperação de desastres.

    module "gke-db2" {
      source                   = "../modules/beta-private-cluster"
      project_id               = var.project_id
      name                     = "cluster-db2"
      regional                 = true
      region                   = "us-west1"
      network                  = module.network.network_name
      subnetwork               = module.network.secondary_subnet_name
      ip_range_pods            = "ip-range-pods-db2"
      ip_range_services        = "ip-range-svc-db2"
      create_service_account   = false
      service_account          = module.gke-db1.service_account
      enable_private_endpoint  = false
      enable_private_nodes     = true
      master_ipv4_cidr_block   = "172.16.0.16/28"
      network_policy           = true
      cluster_autoscaling = {
        "autoscaling_profile": "OPTIMIZE_UTILIZATION",
        "enabled" : true,
        "gpu_resources" : [],
        "min_cpu_cores" : 10,
        "min_memory_gb" : 144,
        "max_cpu_cores" : 48,
        "max_memory_gb" : 192,
      }
      monitoring_enable_managed_prometheus = true
      gke_backup_agent_config = true
      node_pools = [
        {
          name            = "pool-sys"
          autoscaling     = true
          min_count       = 1
          max_count       = 3
          max_surge       = 1
          max_unavailable = 0
          machine_type    = "e2-standard-4"
          node_locations  = "us-west1-a,us-west1-b,us-west1-c"
          auto_repair     = true
        },
        {
          name            = "pool-db"
          autoscaling     = true
          max_surge       = 1
          max_unavailable = 0
          machine_type    = "e2-standard-8"
          node_locations  = "us-west1-a,us-west1-b,us-west1-c"
          auto_repair     = true
        },
      ]
      node_pools_labels = {
        all = {}
        pool-db = {
          "app.stateful/component" = "postgresql"
        }
        pool-sys = {
          "app.stateful/component" = "postgresql-pgpool"
        }
      }
      node_pools_taints = {
        all = []
        pool-db = [
          {
            key    = "app.stateful/component"
            value  = "postgresql"
            effect = "NO_SCHEDULE"
          },
        ],
        pool-sys = [
          {
            key    = "app.stateful/component"
            value  = "postgresql-pgpool"
            effect = "NO_SCHEDULE"
          },
        ],
      }
      gce_pd_csi_driver = true
    }

Implantar o PostgreSQL no cluster

Nesta seção, você vai implantar uma instância de banco de dados PostgreSQL para ser executada no GKE usando um gráfico do Helm.

Instale o PostgreSQL

Para instalar o PostgreSQL no cluster, siga estas etapas.

  1. Configurar o acesso ao Docker

    gcloud auth configure-docker us-docker.pkg.dev
    
  2. Preencher o Artifact Registry com as imagens obrigatórias do Docker do PostgreSQL.

    ./scripts/gcr.sh bitnami/postgresql-repmgr 15.1.0-debian-11-r0
    ./scripts/gcr.sh bitnami/postgres-exporter 0.11.1-debian-11-r27
    ./scripts/gcr.sh bitnami/pgpool 4.3.3-debian-11-r28
    

    O script envia as seguintes imagens do Bitnami para o Artifact Registry para o Helm instalar:

  3. Verifique se as imagens corretas estão armazenadas no repositório.

    gcloud artifacts docker images list us-docker.pkg.dev/$PROJECT_ID/main \
        --format="flattened(package)"
    

    O resultado será assim:

    ---
    image: us-docker.pkg.dev/[PROJECT_ID]/main/bitnami/pgpool
    ---
    image: us-docker.pkg.dev/[PROJECT_ID]/main/bitnami/postgres-exporter
    ---
    image: us-docker.pkg.dev/h[PROJECT_ID]/main/bitnami/postgresql-repmgr
    
  4. Configure o acesso da linha de comando kubectl ao cluster principal.

    gcloud container clusters get-credentials $SOURCE_CLUSTER \
    --region=$REGION --project=$PROJECT_ID
    
  5. Crie um namespace

    export NAMESPACE=postgresql
    kubectl create namespace $NAMESPACE
    
  6. Se você estiver implantando em um cluster do Autopilot, configure o provisionamento de nós em três zonas. Pule esta etapa se estiver implantando em um cluster padrão.

    Por padrão, o Autopilot provisiona recursos em duas zonas. A implantação definida em prepareforha.yaml garante que o Autopilot provisione nós em três zonas do cluster, definindo estes valores:

    • replicas:3
    • podAntiAffinity com requiredDuringSchedulingIgnoredDuringExecution e topologyKey: "topology.kubernetes.io/zone"
    kubectl -n $NAMESPACE apply -f scripts/prepareforha.yaml
    
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: prepare-three-zone-ha
      labels:
        app: prepare-three-zone-ha
        app.kubernetes.io/name: postgresql-ha
    spec:
      replicas: 3
      selector:
        matchLabels:
          app: prepare-three-zone-ha
          app.kubernetes.io/name: postgresql-ha
      template:
        metadata:
          labels:
            app: prepare-three-zone-ha
            app.kubernetes.io/name: postgresql-ha
        spec:
          affinity:
            podAntiAffinity:
              requiredDuringSchedulingIgnoredDuringExecution:
              - labelSelector:
                  matchExpressions:
                  - key: app
                    operator: In
                    values:
                    - prepare-three-zone-ha
                topologyKey: "topology.kubernetes.io/zone"
            nodeAffinity:
              preferredDuringSchedulingIgnoredDuringExecution:
              - preference:
                  matchExpressions:
                  - key: cloud.google.com/compute-class
                    operator: In
                    values:
                    - "Scale-Out"
                weight: 1
          nodeSelector:
            app.stateful/component: postgresql
          tolerations:
          - effect: NoSchedule
            key: app.stateful/component
            operator: Equal
            value: postgresql
          containers:
          - name: prepare-three-zone-ha
            image: busybox:latest
            command:
                - "/bin/sh"
                - "-c"
                - "while true; do sleep 3600; done"
            resources:
              limits:
                cpu: "500m"
                ephemeral-storage: "10Mi"
                memory: "0.5Gi"
              requests:
                cpu: "500m"
                ephemeral-storage: "10Mi"
                memory: "0.5Gi"
    
  7. Atualizar a dependência do Helm.

    cd helm/postgresql-bootstrap
    helm dependency update
    
  8. Inspecione e verifique os gráficos que o Helm instalará.

    helm -n postgresql template postgresql . \
      --set global.imageRegistry="us-docker.pkg.dev/$PROJECT_ID/main"
    
  9. Instale o gráfico do Helm.

    helm -n postgresql upgrade --install postgresql . \
        --set global.imageRegistry="us-docker.pkg.dev/$PROJECT_ID/main"
    

    O resultado será assim:

    NAMESPACE: postgresql
    STATUS: deployed
    REVISION: 1
    TEST SUITE: None
    
  10. Verifique se as réplicas estão em execução:

    kubectl get all -n $NAMESPACE
    

    O resultado será assim:

    NAME                                                          READY   STATUS    RESTARTS   AGE
    pod/postgresql-postgresql-bootstrap-pgpool-75664444cb-dkl24   1/1     Running   0          8m39s
    pod/postgresql-postgresql-ha-pgpool-6d86bf9b58-ff2bg          1/1     Running   0          8m39s
    pod/postgresql-postgresql-ha-postgresql-0                     2/2     Running   0          8m39s
    pod/postgresql-postgresql-ha-postgresql-1                     2/2     Running   0          8m39s
    pod/postgresql-postgresql-ha-postgresql-2                     2/2     Running   0          8m38s
    
    NAME                                                   TYPE        CLUSTER-IP        EXTERNAL-IP   PORT(S)    AGE
    service/postgresql-postgresql-ha-pgpool                ClusterIP   192.168.99.236    <none>        5432/TCP   8m39s
    service/postgresql-postgresql-ha-postgresql            ClusterIP   192.168.90.20     <none>        5432/TCP   8m39s
    service/postgresql-postgresql-ha-postgresql-headless   ClusterIP   None              <none>        5432/TCP   8m39s
    service/postgresql-postgresql-ha-postgresql-metrics    ClusterIP   192.168.127.198   <none>        9187/TCP   8m39s
    
    NAME                                                     READY   UP-TO-DATE   AVAILABLE   AGE
    deployment.apps/postgresql-postgresql-bootstrap-pgpool   1/1     1            1           8m39s
    deployment.apps/postgresql-postgresql-ha-pgpool          1/1     1            1           8m39s
    
    NAME                                                                DESIRED   CURRENT   READY   AGE
    replicaset.apps/postgresql-postgresql-bootstrap-pgpool-75664444cb   1         1         1       8m39s
    replicaset.apps/postgresql-postgresql-ha-pgpool-6d86bf9b58          1         1         1       8m39s
    
    NAME                                                   READY   AGE
    statefulset.apps/postgresql-postgresql-ha-postgresql   3/3     8m39s
    

Criar um conjunto de dados de teste

Nesta seção, você vai criar um banco de dados e uma tabela com valores de amostra. O banco de dados serve como um conjunto de dados de teste para o processo de failover que você testará posteriormente neste tutorial.

  1. Conectar-se à instância do PostgreSQL.

    cd ../../
    ./scripts/launch-client.sh
    

    O resultado será assim:

    Launching Pod pg-client in the namespace postgresql ...
    pod/pg-client created
    waiting for the Pod to be ready
    Copying script files to the target Pod pg-client ...
    Pod: pg-client is healthy
    
  2. Inicie uma sessão de shell.

    kubectl exec -it pg-client -n postgresql -- /bin/bash
    
  3. Crie um banco de dados e uma tabela e, em seguida, insira algumas linhas de teste:

    psql -h $HOST_PGPOOL -U postgres -a -q -f /tmp/scripts/generate-db.sql
    
  4. Verifique o número de linhas de cada tabela.

    psql -h $HOST_PGPOOL -U postgres -a -q -f /tmp/scripts/count-rows.sql
    

    O resultado será assim:

    select COUNT(*) from tb01;
     count
    --------
     300000
    (1 row)
    
    select COUNT(*) from tb02;
     count
    --------
     300000
    (1 row)
    
  5. Gerar dados de teste

    export DB=postgres
    pgbench -i -h $HOST_PGPOOL -U postgres $DB -s 50
    

    O resultado será assim:

    dropping old tables...
    creating tables...
    generating data (client-side)...
    5000000 of 5000000 tuples (100%) done (elapsed 29.85 s, remaining 0.00 s)
    vacuuming...
    creating primary keys...
    done in 36.86 s (drop tables 0.00 s, create tables 0.01 s, client-side generate 31.10 s, vacuum 1.88 s, primary keys 3.86 s).
    
  6. Saia do pod cliente do postgres.

    exit
    

Monitorar o PostgreSQL

Nesta seção, você verá métricas e configurará alertas para sua instância do PostgreSQL. Você vai usar o Google Cloud Managed Service para Prometheus para monitorar e criar alertas.

Ver métricas

Sua implantação do PostgreSQL inclui um contêiner de arquivo secundário postgresql-exporter. Este contêiner expõe um endpoint /metrics. O Google Cloud Managed Service para Prometheus está configurado para monitorar os pods do PostgreSQL nesse endpoint. É possível visualizar essas métricas por meio dos painéis do console do Google Cloud.

O console do Google Cloud oferece algumas maneiras de criar e salvar a configuração do painel:

  • Criação e exportação: é possível criar painéis diretamente no console do Google Cloud e, em seguida, exportá-los e armazená-los em um repositório de código. Para fazer isso, na barra de ferramentas do painel, abra o editor JSON e faça o download do arquivo JSON do painel.
  • Armazenamento e importação: é possível importar um painel de um arquivo JSON clicando em +Criar painel e fazendo upload do conteúdo JSON do painel usando o editor JSON menu.

Para visualizar os dados do aplicativo do PostgreSQL e do cluster do GKE, siga estas etapas:

  1. Crie os seguintes painéis.

    cd monitoring
    gcloud monitoring dashboards create \
            --config-from-file=dashboard/postgresql-overview.json \
            --project=$PROJECT_ID
    gcloud monitoring dashboards create \
            --config-from-file dashboard/gke-postgresql.json \
            --project $PROJECT_ID
    
  2. No console do Google Cloud, navegue até o painel do Cloud Monitoring. Acessar o painel do Cloud Monitoring

  3. Selecione Personalizar na lista de painel. Os seguintes painéis aparecem:

    • Visão geral do PostgreSQL: exibe métricas do aplicativo PostgreSQL, incluindo tempo de atividade do banco de dados, tamanho do banco de dados e latência da transação.
    • Cluster PostgreSQL do GKE: exibe métricas do cluster do GKE em que o PostgreSQL está sendo executado, incluindo o uso da CPU, o uso da memória e a utilização do volume.
  4. Clique em cada link para examinar os painéis gerados.

Configurar alertas

O alerta proporciona reconhecimento oportuno de problemas nos seus aplicativos para que você possa resolvê-los rapidamente. É possível criar uma política de alertas para especificar as circunstâncias em que você quer receber alertas e notificações. Você também pode criar canais de notificação para selecionar para onde os alertas serão enviados.

Nesta seção, você usará o Terraform para configurar os seguintes alertas de exemplo:

  • db_max_transaction: monitora o atraso máximo das transações em segundos; um alerta será acionado se o valor for maior que 10.
  • db_node_up: monitora o status dos pods do banco de dados. Zero significa que um pod está inativo e aciona um alerta.

Para configurar alertas, siga estas etapas:

  1. Configure alertas com o Terraform.

    EMAIL=YOUR_EMAIL
    cd alerting/terraform
    terraform init
    terraform plan -var project_id=$PROJECT_ID -var email_address=$EMAIL
    terraform apply -var project_id=$PROJECT_ID -var email_address=$EMAIL
    

    Substitua os seguintes valores:

    • YOUR_EMAIL: seu endereço de e-mail.

    O resultado será assim:

    Apply complete! Resources: 3 added, 0 changed, 0 destroyed.
    
  2. Conecte-se ao pod cliente.

    cd ../../../
    kubectl exec -it --namespace postgresql pg-client -- /bin/bash
    
  3. Gere um teste de carga para o alerta db_max_transaction.

    pgbench -i -h $HOST_PGPOOL -U postgres -s 200 postgres
    

    O resultado será assim:

    dropping old tables...
    creating tables...
    generating data (client-side)...
    20000000 of 20000000 tuples (100%) done (elapsed 163.22 s, remaining 0.00 s)
    vacuuming...
    creating primary keys...
    done in 191.30 s (drop tables 0.14 s, create tables 0.01 s, client-side generate 165.62 s, vacuum 4.52 s, primary keys 21.00 s).
    

    O alerta é acionado e envia um e-mail para YOUR_EMAIL com uma linha de assunto que começa com "[ALERT] Intervalo máximo de transação".

  4. No Console do Google Cloud, acesse a página "Política de alertas".

    Acessar a política de alertas

  5. Selecione db_max_transaction entre as políticas listadas. No gráfico, você verá um pico do teste de carga que excede a retenção de 10 para a métrica pg_stat_activity_max_tx_duration/gauge do Prometheus.

  6. Saia do pod cliente do postgres.

    exit
    

Gerenciar upgrades do PostgreSQL e GKE

As atualizações de versão para o PostgreSQL e o Kubernetes são lançadas regularmente. Siga as práticas recomendadas operacionais para atualizar o ambiente de software regularmente. Por padrão, o GKE gerencia os upgrades de clusters e pools de nodes para você.

Fazer upgrade do PostgreSQL

Nesta seção, mostramos como realizar um upgrade de versão para o PostgreSQL. Neste tutorial, você usará uma estratégia de atualização gradual para fazer upgrade dos pods para que, em nenhum momento, todos os pods fiquem inativos.

Para fazer upgrade da versão, siga estas etapas:

  1. Envie uma versão atualizada da imagem postgresql-repmgr para o Artifact Registry. Defina a nova versão (por exemplo, postgresql-repmgr 15.1.0-debian-11-r1).

    NEW_IMAGE=us-docker.pkg.dev/$PROJECT_ID/main/bitnami/postgresql-repmgr:15.1.0-debian-11-r1
    ./scripts/gcr.sh bitnami/postgresql-repmgr 15.1.0-debian-11-r1
    
  2. Acione uma atualização gradual usando kubectl.

    kubectl set image statefulset -n postgresql postgresql-postgresql-ha-postgresql postgresql=$NEW_IMAGE
    kubectl rollout restart statefulsets -n postgresql postgresql-postgresql-ha-postgresql
    kubectl rollout status statefulset -n postgresql postgresql-postgresql-ha-postgresql
    

    Você verá o StatefulSet concluir uma atualização gradual, começando com a réplica ordinal mais alta.

    O resultado será assim:

    Waiting for 1 pods to be ready...
    waiting for statefulset rolling update to complete 1 pods at revision postgresql-postgresql-ha-postgresql-5c566ccf49...
    Waiting for 1 pods to be ready...
    Waiting for 1 pods to be ready...
    waiting for statefulset rolling update to complete 2 pods at revision postgresql-postgresql-ha-postgresql-5c566ccf49...
    Waiting for 1 pods to be ready...
    Waiting for 1 pods to be ready...
    statefulset rolling update complete 3 pods at revision postgresql-postgresql-ha-postgresql-5c566ccf49...
    

Planejar upgrades do GKE em clusters padrão

Esta seção é aplicável se você estiver executando clusters padrão. É possível tomar medidas proativas e definir configurações para reduzir os riscos e facilitar um upgrade mais tranquilo do cluster quando estiver executando serviços com estado, incluindo:

  • Siga as práticas recomendadas do GKE para fazer upgrade de clusters. Escolha uma estratégia de upgrade apropriada para garantir que os upgrades aconteçam durante o período da janela de manutenção:

    • Escolha upgrades súbitos se a otimização de custos for importante e se as cargas de trabalho podem tolerar um encerramento otimizado em menos de 60 minutos.
    • Escolha upgrades azul-verde se as cargas de trabalho forem menos tolerantes a interrupções e um aumento temporário do custo devido ao maior uso de recursos for aceitável.

    Para saber mais, consulte Fazer upgrade de um cluster que executa uma carga de trabalho com estado.

  • Use o serviço do recomendador para verificar insights de descontinuação e recomendações para evitar interrupções do serviço.

  • Use as janelas de manutenção para garantir que os upgrades aconteçam quando você quiser. Antes da janela de manutenção, verifique se os backups do banco de dados foram concluídos.

  • Antes de permitir o tráfego para os nodes do MySQL atualizados, use as Sondagens de prontidão e atividades para verificar se estão prontas para tráfego.

  • Crie sondagens que avaliem se a replicação está sincronizada antes de aceitar o tráfego. Isso pode ser feito com scripts personalizados, dependendo da complexidade e da escala do seu banco de dados.

Verificar a disponibilidade do banco de dados durante os upgrades de cluster padrão

Esta seção é aplicável se você estiver executando clusters padrão. Para verificar a disponibilidade do PostgreSQL durante os upgrades, o processo geral é gerar tráfego no banco de dados do PostgreSQL durante o processo de upgrade. Em seguida, use pgbench para verificar se o banco de dados pode lidar com um nível de tráfego de referência durante um upgrade, em comparação com quando o banco de dados está totalmente disponível.

  1. Conectar-se à instância do PostgreSQL.

    ./scripts/launch-client.sh
    

    O resultado será assim:

    Launching Pod pg-client in the namespace postgresql ...
    pod/pg-client created
    waiting for the Pod to be ready
    Copying script files to the target Pod pg-client ...
    Pod: pg-client is healthy
    
  2. No Cloud Shell, foque no pod cliente.

    kubectl exec -it -n postgresql pg-client -- /bin/bash
    
  3. Inicialize pgbench .

    pgbench -i -h $HOST_PGPOOL -U postgres postgres
    
  4. Use o comando a seguir para receber resultados de referência e confirmar se o aplicativo PostgreSQL permanece altamente disponível durante o período para um upgrade. Para ter um resultado básico, teste com várias conexões por vários jobs (linhas de execução) por 30 segundos.

    pgbench -h $HOST_PGPOOL -U postgres postgres -c10 -j4 -T 30 -R 200
    

    A saída será assim:

    pgbench (14.5)
    starting vacuum...end.
    transaction type: <builtin: TPC-B (sort of)>
    scaling factor: 1
    query mode: simple
    number of clients: 10
    number of threads: 4
    duration: 30 s
    number of transactions actually processed: 5980
    latency average = 7.613 ms
    latency stddev = 2.898 ms
    rate limit schedule lag: avg 0.256 (max 36.613) ms
    initial connection time = 397.804 ms
    tps = 201.955497 (without initial connection time)
    
  5. Para garantir a disponibilidade durante os upgrades, é possível gerar carga no banco de dados e garantir que o aplicativo PostgreSQL forneça uma taxa de resposta consistente durante o upgrade. Para executar esse teste, gere um tráfego no banco de dados usando o comando pgbench. O comando a seguir executará pgbench por uma hora, segmentando 200 TPS (transações por segundo) e listando a taxa de solicitação a cada dois segundos.

    pgbench -h $HOST_PGPOOL -U postgres postgres --client=10 --jobs=4 --rate=200 --time=3600 --progress=2 --select-only
    

    Em que:

    • --client: número de clientes simulados, ou seja, o número de sessões simultâneas do banco de dados.
    • --jobs: número de linhas de execução de worker no pgbench. Usar mais de uma linha de execução pode ser útil em máquinas com várias CPUs. Os clientes são distribuídos da maneira mais uniforme possível entre as linhas de execução disponíveis. O padrão é 1.
    • --rate: a taxa é dada em transações por segundo
    • --progress: mostra o relatório de progresso a cada segundos.

    O resultado será assim:

    pgbench (14.5)
    starting vacuum...end.
    progress: 5.0 s, 354.8 tps, lat 25.222 ms stddev 15.038
    progress: 10.0 s, 393.8 tps, lat 25.396 ms stddev 16.459
    progress: 15.0 s, 412.8 tps, lat 24.216 ms stddev 14.548
    progress: 20.0 s, 405.0 tps, lat 24.656 ms stddev 14.066
    
  6. No console do Google Cloud, volte para o painel Visão geral do PostgreSQL no Cloud Monitoring. Observe o pico nos gráficos Conexão por banco de dados e Conexão por pod.

  7. Saia do pod cliente.

    exit
    
  8. Exclua o pod cliente.

    kubectl delete pod -n postgresql pg-client
    

Simular uma interrupção do serviço PostgreSQL

Nesta seção, você simulará uma interrupção de serviço em uma das réplicas do PostgreSQL ao interromper o serviço do gerenciador de replicação. Isso impedirá que o pod exiba tráfego para as réplicas de peering e as sondagens de atividade dele falhem.

  1. Abra uma nova sessão do Cloud Shell e configure o acesso da linha de comando kubectl ao cluster principal.

    gcloud container clusters get-credentials $SOURCE_CLUSTER \
    --region=$REGION --project=$PROJECT_ID
    
  2. Veja os eventos do PostgreSQL emitidos no Kubernetes.

    kubectl get events -n postgresql --field-selector=involvedObject.name=postgresql-postgresql-ha-postgresql-0 --watch
    
  3. Na sessão anterior do Cloud Shell, simule uma falha de serviço interrompendo o PostgreSQL repmgr.

    1. Anexe a sessão ao contêiner do banco de dados.

      kubectl exec -it -n $NAMESPACE postgresql-postgresql-ha-postgresql-0 -c postgresql -- /bin/bash
      
    2. Interrompa o serviço usando repmgr e remova o checkpoint e o argumento dry-run.

      export ENTRY='/opt/bitnami/scripts/postgresql-repmgr/entrypoint.sh'
      export RCONF='/opt/bitnami/repmgr/conf/repmgr.conf'
      $ENTRY repmgr -f $RCONF node service --action=stop --checkpoint
      

A sondagem de atividade configurada para o contêiner do PostgreSQL começará a falhar em até cinco segundos. Isso se repete a cada 10 segundos e atinge o limite de seis falhas. Quando o valor failureThreshold é alcançado, o contêiner é reiniciado. É possível configurar esses parâmetros para diminuir a tolerância da sondagem de atividade para ajustar os requisitos de SLO de sua implantação.

No stream de eventos, você verá as sondagens de atividade e prontidão do pod e uma mensagem informando que o contêiner precisa ser reiniciado. O resultado será assim:

0s          Normal    Killing                pod/postgresql-postgresql-ha-postgresql-0   Container postgresql failed liveness probe, will be restarted
0s          Warning   Unhealthy              pod/postgresql-postgresql-ha-postgresql-0   Readiness probe failed: psql: error: connection to server at "127.0.0.1", port 5432 failed: Connection refused...
0s          Normal    Pulled                 pod/postgresql-postgresql-ha-postgresql-0   Container image "us-docker.pkg.dev/psch-gke-dev/main/bitnami/postgresql-repmgr:14.5.0-debian-11-r10" already present on machine
0s          Normal    Created                pod/postgresql-postgresql-ha-postgresql-0   Created container postgresql
0s          Normal    Started                pod/postgresql-postgresql-ha-postgresql-0   Started container postgresql

Prepare-se para a recuperação de desastres

Para garantir que suas cargas de trabalho de produção permaneçam disponíveis no caso de um evento de interrupção de serviço, prepare um plano de recuperação de desastres (DR). Para saber mais sobre o planejamento de DR, consulte o Guia de planejamento de recuperação de desastres.

A recuperação de desastres para o Kubernetes pode ser implementada em duas fases:

  • O backup envolve a criação de um snapshot pontual do seu estado ou dos seus dados antes de ocorrer um evento de interrupção de serviço.
  • A recuperação envolve a restauração do seu estado ou dados de uma cópia de backup após a ocorrência de um desastre.

Para fazer backup e restaurar suas cargas de trabalho em clusters do GKE, use o Backup para o GKE. É possível ativar esse serviço em clusters novos e atuais. Isso implanta um agente de Backup para GKE executado nos clusters. o agente é responsável por capturar dados de backup de configuração e volume e orquestrar a recuperação.

Os backups e restaurações podem ter como escopo um cluster inteiro, um namespace ou um aplicativo (definido por seletores como matchLabels).

Exemplo de cenário de backup e restauração do PostgreSQL

O exemplo nesta seção mostra como executar uma operação de backup e restauração no escopo do aplicativo, usando o recurso personalizado ProtectedApplication.

O diagrama a seguir mostra os recursos do componente no ManagedApplication, ou seja, um StatefulSet que representa o aplicativo postgresql-ha e uma implantação de pgpool que usa o mesmo rótulo (app.kubernetes.io/name: postgresql-ha).

O diagrama mostra um exemplo de solução de backup e recuperação de um cluster PostgreSQL altamente disponível.
Figura 2: exemplo de solução de backup e recuperação para um cluster PostgreSQL altamente disponível.

Para se preparar para fazer backup e restaurar sua carga de trabalho do PostgreSQL, siga estas etapas:

  1. Configurar as variáveis de ambiente Neste exemplo, você usará um ProtectedApplication para restaurar a carga de trabalho do PostgreSQL e os respectivos volumes do cluster de origem do GKE (us-central1) e, em seguida, restaurar para outro cluster do GKE em uma região diferente (us-west1).

    export SOURCE_CLUSTER=cluster-db1
    export TARGET_CLUSTER=cluster-db2
    export REGION=us-central1
    export DR_REGION=us-west1
    export NAME_PREFIX=g-db-protected-app
    export BACKUP_PLAN_NAME=$NAME_PREFIX-bkp-plan-01
    export BACKUP_NAME=bkp-$BACKUP_PLAN_NAME
    export RESTORE_PLAN_NAME=$NAME_PREFIX-rest-plan-01
    export RESTORE_NAME=rest-$RESTORE_PLAN_NAME
    
  2. Verifique se o backup para o GKE está ativado no cluster Ele já deve estar ativado como parte da configuração do Terraform que você executou anteriormente.

    gcloud container clusters describe $SOURCE_CLUSTER \
        --project=$PROJECT_ID  \
        --region=$REGION \
        --format='value(addonsConfig.gkeBackupAgentConfig)'
    

    Se o Backup para GKE estiver ativado, a saída do comando vai mostrar enabled=True.

Configurar um plano de backup e fazer uma restauração

O Backup para GKE permite criar um plano de backup como um cron job. Um plano de backup contém uma configuração de backup, incluindo o cluster de origem, a seleção de quais cargas de trabalho fazer backup e a região em que os artefatos de backup produzidos nesse plano são armazenados.

Para fazer um backup e uma restauração, siga estas etapas:

  1. Verifique o status de ProtectedApplication em cluster-db1.

    kubectl get ProtectedApplication -A
    

    A saída será assim:

    NAMESPACE    NAME            READY TO BACKUP
    postgresql   postgresql-ha   true
    
  2. Crie um plano de backup para o ProtectedApplication.

    export NAMESPACE=postgresql
    export PROTECTED_APP=$(kubectl get ProtectedApplication -n $NAMESPACE | grep -v 'NAME' | awk '{ print $1 }')
    
    gcloud beta container backup-restore backup-plans create $BACKUP_PLAN_NAME \
    --project=$PROJECT_ID \
    --location=$DR_REGION \
    --cluster=projects/$PROJECT_ID/locations/$REGION/clusters/$SOURCE_CLUSTER \
    --selected-applications=$NAMESPACE/$PROTECTED_APP \
    --include-secrets \
    --include-volume-data \
    --cron-schedule="0 3 * * *" \
    --backup-retain-days=7 \
    --backup-delete-lock-days=0
    
  3. Crie um backup manualmente.

    gcloud beta container backup-restore backups create $BACKUP_NAME \
    --project=$PROJECT_ID \
    --location=$DR_REGION \
    --backup-plan=$BACKUP_PLAN_NAME \
    --wait-for-completion
    
  4. Configure um plano de restauração.

    gcloud beta container backup-restore restore-plans create $RESTORE_PLAN_NAME \
      --project=$PROJECT_ID \
      --location=$DR_REGION \
      --backup-plan=projects/$PROJECT_ID/locations/$DR_REGION/backupPlans/$BACKUP_PLAN_NAME \
      --cluster=projects/$PROJECT_ID/locations/$DR_REGION/clusters/$TARGET_CLUSTER \
      --cluster-resource-conflict-policy=use-existing-version \
      --namespaced-resource-restore-mode=delete-and-restore \
      --volume-data-restore-policy=restore-volume-data-from-backup \
      --selected-applications=$NAMESPACE/$PROTECTED_APP \
      --cluster-resource-scope-selected-group-kinds="storage.k8s.io/StorageClass","scheduling.k8s.io/PriorityClass"
    
  5. Faça a restauração do backup.

    gcloud beta container backup-restore restores create $RESTORE_NAME \
      --project=$PROJECT_ID \
      --location=$DR_REGION \
      --restore-plan=$RESTORE_PLAN_NAME \
      --backup=projects/$PROJECT_ID/locations/$DR_REGION/backupPlans/$BACKUP_PLAN_NAME/backups/$BACKUP_NAME \
      --wait-for-completion
    

Verifique se o cluster foi restaurado

Para verificar se o cluster restaurado tem todos os recursos esperados de pods, PersistentVolume e StorageClass, siga estas etapas:

  1. Configure o acesso da linha de comando kubectl ao cluster de backup cluster-db2.

    gcloud container clusters get-credentials $TARGET_CLUSTER --region $DR_REGION --project $PROJECT_ID
    
  2. Verifique se o StatefulSet está pronto com 3/3 pods.

    kubectl get all -n $NAMESPACE
    

    O resultado será assim:

    NAME                                                   READY   STATUS    RESTARTS        AGE
    pod/postgresql-postgresql-ha-pgpool-778798b5bd-k2q4b   1/1     Running   0               4m49s
    pod/postgresql-postgresql-ha-postgresql-0              2/2     Running   2 (4m13s ago)   4m49s
    pod/postgresql-postgresql-ha-postgresql-1              2/2     Running   0               4m49s
    pod/postgresql-postgresql-ha-postgresql-2              2/2     Running   0               4m49s
    
    NAME                                                   TYPE        CLUSTER-IP        EXTERNAL-IP   PORT(S)    AGE
    service/postgresql-postgresql-ha-pgpool                ClusterIP   192.168.241.46    <none>        5432/TCP   4m49s
    service/postgresql-postgresql-ha-postgresql            ClusterIP   192.168.220.20    <none>        5432/TCP   4m49s
    service/postgresql-postgresql-ha-postgresql-headless   ClusterIP   None              <none>        5432/TCP   4m49s
    service/postgresql-postgresql-ha-postgresql-metrics    ClusterIP   192.168.226.235   <none>        9187/TCP   4m49s
    
    NAME                                              READY   UP-TO-DATE   AVAILABLE   AGE
    deployment.apps/postgresql-postgresql-ha-pgpool   1/1     1            1           4m49s
    
    NAME                                                         DESIRED   CURRENT   READY   AGE
    replicaset.apps/postgresql-postgresql-ha-pgpool-778798b5bd   1         1         1       4m49s
    
    NAME                                                   READY   AGE
    statefulset.apps/postgresql-postgresql-ha-postgresql   3/3     4m49s
    
  3. Verifique se todos os pods no namespace postgres estão em execução.

    kubectl get pods -n $NAMESPACE
    

    O resultado será assim:

    postgresql-postgresql-ha-pgpool-569d7b8dfc-2f9zx   1/1     Running   0          7m56s
    postgresql-postgresql-ha-postgresql-0              2/2     Running   0          7m56s
    postgresql-postgresql-ha-postgresql-1              2/2     Running   0          7m56s
    postgresql-postgresql-ha-postgresql-2              2/2     Running   0          7m56s
    
  4. Verificar os PersistentVolumes e o StorageClass. Durante o processo de restauração, o Backup para GKE cria uma classe de proxy na carga de trabalho de destino para substituir o StorageClass provisionado na carga de trabalho de origem (gce-pd-gkebackup-dn no exemplo de saída).

    kubectl get pvc -n $NAMESPACE
    

    O resultado será assim:

    NAME                                         STATUS   VOLUME                 CAPACITY   ACCESS MODES   STORAGECLASS          AGE
    data-postgresql-postgresql-ha-postgresql-0   Bound    pvc-be91c361e9303f96   8Gi        RWO            gce-pd-gkebackup-dn   10m
    data-postgresql-postgresql-ha-postgresql-1   Bound    pvc-6523044f8ce927d3   8Gi        RWO            gce-pd-gkebackup-dn   10m
    data-postgresql-postgresql-ha-postgresql-2   Bound    pvc-c9e71a99ccb99a4c   8Gi        RWO            gce-pd-gkebackup-dn   10m
    

Validar a restauração dos dados esperados

Para validar se os dados esperados foram restaurados, siga estas etapas:

  1. Conectar-se à instância do PostgreSQL.

    ./scripts/launch-client.sh
    kubectl exec -it pg-client -n postgresql -- /bin/bash
    
  2. Verifique o número de linhas de cada tabela.

    psql -h $HOST_PGPOOL -U postgres -a -q -f /tmp/scripts/count-rows.sql
    select COUNT(*) from tb01;
    

    Você verá um resultado semelhante aos dados gravados anteriormente em Criar um conjunto de dados de teste. O resultado será assim:

    300000
    (1 row)
    
  3. Saia do pod cliente.

    exit
    

Limpar

Para evitar cobranças na sua conta do Google Cloud pelos recursos usados no tutorial, exclua o projeto que os contém ou mantenha o projeto e exclua os recursos individuais.

Excluir o projeto

A maneira mais fácil de evitar o faturamento é excluir o projeto criado para o tutorial.

Delete a Google Cloud project:

gcloud projects delete PROJECT_ID

A seguir