Implementa una base de datos de PostgreSQL con alta disponibilidad en GKE

PostgreSQL es una base de datos relacional de objetos de código abierto conocida por la confiabilidad y la integridad de los datos. Cumple con los criterios ACID y admite claves externas, uniones, vistas, activadores y procedimientos almacenados.

Este documento está dirigido a los administradores de bases de datos, los arquitectos de la nube y los profesionales de operaciones interesados en implementar una topología de PostgreSQL con alta disponibilidad en Google Kubernetes Engine (GKE).

Objetivos

En este instructivo aprenderás realizar las siguientes tareas:

  • Usar Terraform para crear un clúster de GKE regional.
  • Implementar una base de datos de PostgreSQL con alta disponibilidad.
  • Configurar la supervisión de la aplicación de PostgreSQL.
  • Realizar actualizaciones de la base de datos de PostgreSQL y del clúster de GKE.
  • Simular la interrupción del clúster y la conmutación por error de la réplica de PostgreSQL.
  • Realiza una copia de seguridad y restablecimiento de la base de datos de PostgreSQL.

Arquitectura

En esta sección, se describe la arquitectura de la solución que compilarás en este instructivo.

Aprovisionarás dos clústeres de GKE en diferentes regiones: un clúster principal y un clúster de copia de seguridad. En este instructivo, el clúster principal está en la región us-central1, y el clúster de copia de seguridad está en la región us-west1. Esta arquitectura te permite aprovisionar una base de datos de PostgreSQL con alta disponibilidad y probar la recuperación ante desastres, como se describe más adelante en este instructivo.

Para el clúster de origen, usarás un gráfico de Helm (bitnami/postgresql-ha) a fin de configurar un clúster de PostgreSQL de alta disponibilidad.

En el diagrama, se muestra un ejemplo de arquitectura de un clúster de PostgreSQL con alta disponibilidad.
Figura 1: Arquitectura de ejemplo de un clúster de PostgreSQL con alta disponibilidad.

Costos

En este documento, usarás los siguientes componentes facturables de Google Cloud:

Para obtener una estimación de costos en función del uso previsto, usa la calculadora de precios.

Es posible que los usuarios de Google Cloud nuevos cumplan con los requisitos para acceder a una prueba gratuita.

Cuando completes las tareas que se describen en este documento, podrás borrar los recursos que creaste para evitar que se te siga facturando. Para obtener más información, consulta Realiza una limpieza.

Antes de comenzar

Configura tu proyecto

  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.

    Roles required to create a project

    To create a project, you need the Project Creator role (roles/resourcemanager.projectCreator), which contains the resourcemanager.projects.create permission. Learn how to grant roles.

    Go to project selector

  3. Verify 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.

    Roles required to enable APIs

    To enable APIs, you need the Service Usage Admin IAM role (roles/serviceusage.serviceUsageAdmin), which contains the serviceusage.services.enable permission. Learn how to grant roles.

    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.

    Roles required to create a project

    To create a project, you need the Project Creator role (roles/resourcemanager.projectCreator), which contains the resourcemanager.projects.create permission. Learn how to grant roles.

    Go to project selector

  6. Verify 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.

    Roles required to enable APIs

    To enable APIs, you need the Service Usage Admin IAM role (roles/serviceusage.serviceUsageAdmin), which contains the serviceusage.services.enable permission. Learn how to grant roles.

    Enable the APIs

  8. Configura funciones

    1. Make sure that you have the following role or roles on the project: roles/storage.objectViewer, roles/logging.logWriter, roles/artifactregistry.Admin, roles/container.clusterAdmin, roles/container.serviceAgent, roles/serviceusage.serviceUsageAdmin, roles/iam.serviceAccountAdmin

      Check for the roles

      1. In the Google Cloud console, go to the IAM page.

        Go to IAM
      2. Select the project.
      3. In the Principal column, find all rows that identify you or a group that you're included in. To learn which groups you're included in, contact your administrator.

      4. For all rows that specify or include you, check the Role column to see whether the list of roles includes the required roles.

      Grant the roles

      1. In the Google Cloud console, go to the IAM page.

        Ir a IAM
      2. Selecciona el proyecto.
      3. Haz clic en Otorgar acceso.
      4. En el campo Principales nuevas, ingresa tu identificador de usuario. Esta suele ser la dirección de correo electrónico de una Cuenta de Google.

      5. Haz clic en Seleccionar un rol y, luego, busca el rol.
      6. Para otorgar roles adicionales, haz clic en Agregar otro rol y agrega uno más.
      7. Haz clic en Guardar.

      Configura tu entorno

      En este instructivo, usarás Cloud Shell para administrar recursos alojados enGoogle Cloud. Cloud Shell viene preinstalado con el software que necesitarás para este instructivo, incluido Docker, kubectl, la CLI de gcloud, Helm y Terraform.

      Sigue estos pasos para configurar tu entorno con Cloud Shell:

      1. Para iniciar una sesión de Cloud Shell desde la Google Cloud consola, haz clic en Ícono de activación de Cloud Shell Activar Cloud Shell en la Google Cloud consola. Esto inicia una sesión en el panel inferior de la consola de Google Cloud .

      2. Configurar variables de entorno

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

        Reemplaza los siguientes valores:

      3. Configura las variables de entorno predeterminadas.

        gcloud config set project PROJECT_ID
        
      4. Clona el repositorio de código.

        git clone https://github.com/GoogleCloudPlatform/kubernetes-engine-samples
        
      5. Cambia al directorio de trabajo.

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

      Crea la infraestructura del clúster

      En esta sección, ejecutarás una secuencia de comandos de Terraform para crear una nube privada virtual (VPC) personalizada, un repositorio de Artifact Registry a fin de almacenar imágenes de PostgreSQL y dos clústeres regionales de GKE. Se implementará un clúster en us-central1 y el segundo clúster para copias de seguridad en us-west1.

      Sigue estos pasos para crear el clúster:

      Autopilot

      En Cloud Shell, ejecute los siguientes comandos:

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

      Cuando se te solicite, escribe yes.

      Comprende la configuración de Terraform

      Los archivos de configuración de Terraform crean los siguientes recursos para implementar la infraestructura:

      • Crea un repositorio de Artifact Registry para almacenar las imágenes de Docker.
        resource "google_artifact_registry_repository" "main" {
          location      = "us"
          repository_id = "main"
          format        = "DOCKER"
          project       = var.project_id
        }
      • Crea la red de VPC y la subred para la interfaz de red de la 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]
        }
      • Crea un clúster principal de GKE.

        Terraform crea un clúster privado en la región us-central1 y habilita la Copia de seguridad para GKE para la recuperación ante desastres y el servicio administrado para Prometheus a fin de supervisar los clústeres.

        El servicio administrado para Prometheus solo es compatible con los clústeres de Autopilot que ejecutan GKE versión 1.25 o 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
        }

      • Crea un clúster de copia de seguridad en la región us-west1 para la recuperación ante 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
        }

      Estándar

      En Cloud Shell, ejecute los siguientes comandos:

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

      Cuando se te solicite, escribe yes.

      Comprende la configuración de Terraform

      Los archivos de configuración de Terraform crean los siguientes recursos para implementar la infraestructura:

      • Crea un repositorio de Artifact Registry para almacenar las imágenes de 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}",
          ]
        }
      • Crea la red de VPC y la subred para la interfaz de red de la 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]
        }
      • Crea un clúster principal de GKE.

        Terraform crea un clúster privado en la región us-central1 y habilita la Copia de seguridad para GKE para la recuperación ante desastres y el servicio administrado para Prometheus a fin de supervisar los clústeres.

        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
        }

      • Crea un clúster de copia de seguridad en la región us-west1 para la recuperación ante 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
        }

      Implementa PostgreSQL en tu clúster

      En esta sección, implementarás una instancia de base de datos de PostgreSQL para que se ejecute en GKE mediante un gráfico de Helm.

      Instala PostgreSQL

      Para instalar PostgreSQL en tu clúster, sigue estos pasos.

      1. Configura el acceso a Docker.

        gcloud auth configure-docker us-docker.pkg.dev
        
      2. Propaga Artifact Registry con las imágenes de Docker de PostgreSQL necesarias.

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

        La secuencia de comandos envía las siguientes imágenes de Bitnami a Artifact Registry para que Helm las instale:

        • postgresql-repmgr: Esta solución de clúster de PostgreSQL incluye el administrador de replicación de PostgreSQL (repmgr), una herramienta de código abierto que se usa para administrar la replicación y la conmutación por error en los clústeres de PostgreSQL.
        • postgres-exporter: El exportador de PostgreSQL recopila métricas de PostgreSQL para el consumo de Prometheus.
        • pgpool: Pgpool-II es el proxy de PostgreSQL. Proporciona agrupación de conexiones y balanceo de cargas.
      3. Verifica que las imágenes correctas estén almacenadas en el repositorio.

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

        El resultado es similar a este:

        ---
        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. Configura el acceso mediante la línea de comandos de kubectl al clúster principal.

        gcloud container clusters get-credentials $SOURCE_CLUSTER \
        --location=$REGION --project=$PROJECT_ID
        
      5. Crea un espacio de nombres.

        export NAMESPACE=postgresql
        kubectl create namespace $NAMESPACE
        
      6. Si implementas en un clúster de Autopilot, configura el aprovisionamiento de nodos en tres zonas. Puedes omitir este paso si implementas en un clúster de Standard.

        De forma predeterminada, Autopilot aprovisiona recursos en solo dos zonas. La implementación definida en prepareforha.yaml garantiza que Autopilot aprovisione nodos en tres zonas de tu clúster mediante la configuración de estos valores:

        • replicas:3
        • podAntiAffinity con requiredDuringSchedulingIgnoredDuringExecution y 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. Actualiza la dependencia de Helm.

        cd helm/postgresql-bootstrap
        helm dependency update
        
      8. Inspecciona y verifica los gráficos que Helm instalará.

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

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

        El resultado es similar a este:

        NAMESPACE: postgresql
        STATUS: deployed
        REVISION: 1
        TEST SUITE: None
        
      10. Verifica que las réplicas estén en ejecución.

        kubectl get all -n $NAMESPACE
        

        El resultado es similar a este:

        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
        

      Crea un conjunto de datos de prueba

      En esta sección, crearás una base de datos y una tabla con valores de muestra. La base de datos sirve como un conjunto de datos de prueba para el proceso de conmutación por error que probarás más adelante en este instructivo.

      1. Conectarte a tu instancia de PostgreSQL

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

        El resultado es similar a este:

        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. Inicia una sesión de shell.

        kubectl exec -it pg-client -n postgresql -- /bin/bash
        
      3. Crea una base de datos y una tabla y, luego, inserta algunas filas de prueba.

        psql -h $HOST_PGPOOL -U postgres -a -q -f /tmp/scripts/generate-db.sql
        
      4. Verifica la cantidad de filas de cada tabla.

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

        El resultado es similar a este:

        select COUNT(*) from tb01;
         count
        --------
         300000
        (1 row)
        
        select COUNT(*) from tb02;
         count
        --------
         300000
        (1 row)
        
      5. Genera datos a partir de las pruebas.

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

        El resultado es similar a este:

        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. Sal del Pod del cliente de Postgres.

        exit
        

      Supervisa PostgreSQL

      En esta sección, verás métricas y configurarás alertas para tu instancia de PostgreSQL. Usarás Google Cloud Managed Service para Prometheus a fin de realizar la supervisión y las alertas.

      Ver métricas

      La implementación de PostgreSQL incluye un contenedor de sidecar postgresql-exporter. Este contenedor expone un extremo /metrics. Google Cloud Managed Service para Prometheus está configurado a fin de supervisar los Pods de PostgreSQL en este extremo. Puedes ver estas métricas a través de los paneles de la consola Google Cloud .

      La consola de Google Cloud proporciona algunas formas de crear y guardar la configuración del panel:

      • Creación y exportación: Puedes crear paneles directamente en la consola de Google Cloud y, luego, exportarlos y almacenarlos en un repositorio de código. Para hacerlo, en la barra de herramientas del panel, abre el editor de JSON y descarga el archivo JSON del panel.
      • Importar y almacenar: Puedes importar un panel desde un archivo JSON si haces clic en + Crear panel y subes el contenido JSON del panel mediante el menú Editor de JSON).

      Para visualizar datos desde tu aplicación de PostgreSQL y tu clúster de GKE, sigue estos pasos:

      1. Crea los siguientes paneles.

        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. En la consola de Google Cloud , navega al panel de Cloud Monitoring. Ir al panel de Cloud Monitoring

      3. Selecciona Personalizado en la lista de paneles. Aparecerán los siguientes paneles:

        • Descripción general de PostgreSQL: Muestra las métricas de la aplicación de PostgreSQL, incluidos el tiempo de actividad de la base de datos, el tamaño de la base de datos y la latencia de la transacción.
        • Clúster de PostgreSQL de GKE: Muestra las métricas del clúster de GKE en el que se ejecuta PostgreSQL, incluido el uso de CPU, el uso de memoria y el uso de volumen.
      4. Haz clic en cada vínculo para examinar los paneles generados.

      Configura alertas

      Las alertas te permiten tener un conocimiento oportuno de los problemas en tus aplicaciones para que puedas resolverlos rápidamente. Puedes crear una política de alertas para especificar las circunstancias en las que deseas recibir la alerta y cómo quieres recibir las notificaciones. También puedes crear canales de notificaciones que te permitan seleccionar a dónde se envían las alertas.

      En esta sección, usarás Terraform para configurar las siguientes alertas de ejemplo:

      • db_max_transaction: Supervisa el retraso máximo de las transacciones en segundos. Se activará una alerta si el valor es superior a 10.
      • db_node_up: Supervisa el estado de los Pods de la base de datos. 0 significa que un Pod está inactivo y activa una alerta.

      Para configurar alertas, sigue estos pasos:

      1. Configura alertas con 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
        

        Reemplaza los siguientes valores:

        • YOUR_EMAIL: el dirección de correo electrónico

        El resultado es similar a este:

        Apply complete! Resources: 3 added, 0 changed, 0 destroyed.
        
      2. Conéctate al Pod cliente.

        cd ../../../
        kubectl exec -it --namespace postgresql pg-client -- /bin/bash
        
      3. Genera una prueba de carga para probar la alerta db_max_transaction.

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

        El resultado es similar a este:

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

        La alerta se activa y envía un correo electrónico a YOUR_EMAIL con un asunto que comienza con “[ALERTA] latencia máxima de transacción”.

      4. En la consola de Google Cloud , navega a la página Política de alertas.

        Ir a Política de alertas

      5. Selecciona db_max_transaction en las políticas de la lista. En el gráfico, deberías ver un aumento de la prueba de carga que supera el umbral de retención de 10 para la métrica de Prometheus pg_stat_activity_max_tx_duration/gauge.

      6. Sal del Pod del cliente de Postgres.

        exit
        

      Administra actualizaciones de PostgreSQL y GKE

      Las actualizaciones de versiones para PostgreSQL y Kubernetes se lanzan con regularidad. Sigue las prácticas recomendadas operativas para actualizar el entorno de software con regularidad. De forma predeterminada, GKE administra las actualizaciones del clúster y del grupo de nodos por ti.

      Actualiza PostgreSQL

      En esta sección, se muestra cómo realizar una actualización de versión para PostgreSQL. En este instructivo, usarás una estrategia de actualización progresiva para actualizar los Pods, de modo que en ningún momento todos los Pods estén inactivos.

      Para realizar una actualización de versión, sigue estos pasos:

      1. Envía una versión actualizada de la imagen postgresql-repmgr a Artifact Registry. Define la versión nueva (por ejemplo, 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. Activa una actualización progresiva mediante 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
        

        Verás que StatefulSet completa una actualización progresiva, comenzando con la réplica ordinal más alta y hasta la más baja.

        El resultado es similar a este:

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

      Planifica las actualizaciones de GKE en los clústeres de Standard

      Esta sección es aplicable si ejecutas clústeres de Standard. Puedes tomar medidas proactivas y establecer parámetros de configuración para mitigar el riesgo y facilitar una actualización del clúster sin problemas cuando ejecutas servicios con estado, incluidos los siguientes:

      Verifica la disponibilidad de la base de datos durante las actualizaciones del clúster de Standard

      Esta sección es aplicable si ejecutas clústeres de Standard. Para verificar la disponibilidad de PostgreSQL durante las actualizaciones, el proceso general es generar tráfico en la base de datos de PostgreSQL durante el proceso de actualización. Luego, usa pgbench para verificar que la base de datos pueda controlar un nivel de tráfico de referencia durante una actualización, en comparación con cuando la base de datos está completamente disponible.

      1. Conectarte a tu instancia de PostgreSQL

        ./scripts/launch-client.sh
        

        El resultado es similar a este:

        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. En Cloud Shell, abre una conexión de shell al Pod del cliente.

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

        pgbench -i -h $HOST_PGPOOL -U postgres postgres
        
      4. Usa el siguiente comando para obtener resultados de referencia a fin de confirmar que tu aplicación de PostgreSQL permanezca con alta disponibilidad durante el período de una actualización. Para obtener un resultado del modelo de referencia, prueba con conexiones múltiples a través de varios trabajos (subprocesos) durante 30 segundos.

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

        El resultado es similar al siguiente:

        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 garantizar la disponibilidad durante las actualizaciones, puedes generar cierta carga en tu base de datos y asegurarte de que la aplicación de PostgreSQL proporcione una tasa de respuesta coherente durante la actualización. Para realizar esta prueba, genera tráfico en la base de datos con el comando pgbench. El siguiente comando ejecutará pgbench durante una hora, se orientará a 200 TPS (transacciones por segundo) y mostrará el porcentaje de solicitudes cada 2 segundos.

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

        Donde:

        • --client: cantidad de clientes simulados, es decir, cantidad de sesiones simultáneas de la base de datos.
        • --jobs: Cantidad de subprocesos de trabajo dentro de pgbench. El uso de más de un subproceso puede ser útil en las máquinas con varias CPU. Los clientes se distribuyen de la manera más uniforme posible entre los subprocesos disponibles. El valor predeterminado es 1.
        • --rate: la tarifa se proporciona en transacciones por segundo
        • --progress: muestra el informe de progreso cada cierta cantidad de segundos.

        El resultado es similar a lo siguiente:

        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. En la consola de Google Cloud , vuelve al panel Descripción general de PostgreSQL en Cloud Monitoring. Observa el aumento en los gráficos de Conexión por base de datos y Conexión por Pod.

      7. Sal del Pod del cliente.

        exit
        
      8. Borra el Pod del cliente.

        kubectl delete pod -n postgresql pg-client
        

      Simula una interrupción del servicio de PostgreSQL

      En esta sección, simularás una interrupción del servicio en una de las réplicas de PostgreSQL mediante la detención del servicio del administrador de replicación. Esto evitará que el Pod entregue tráfico a las réplicas de intercambio de tráfico y que sus sondeos de estado en funcionamiento fallen.

      1. Abre una sesión de Cloud Shell nueva y configura el acceso de la línea de comandos de kubectl al clúster principal.

        gcloud container clusters get-credentials $SOURCE_CLUSTER \
        --location=$REGION --project=$PROJECT_ID
        
      2. Ve los eventos de PostgreSQL emitidos en Kubernetes.

        kubectl get events -n postgresql --field-selector=involvedObject.name=postgresql-postgresql-ha-postgresql-0 --watch
        
      3. En la sesión anterior de Cloud Shell, detén repmgr de PostgreSQL para simular una falla del servicio.

        1. Adjunta tu sesión al contenedor de la base de datos.

          kubectl exec -it -n $NAMESPACE postgresql-postgresql-ha-postgresql-0 -c postgresql -- /bin/bash
          
        2. Detén el servicio con repmgr y quita el punto de control y el 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
          

      El sondeo de actividad configurado para el contenedor de PostgreSQL comenzará a fallar en cinco segundos. Esto se repite cada diez segundos, hasta que se alcanza el umbral de falla de seis fallas. Una vez que se alcanza el valor failureThreshold, el contenedor se reinicia. Puedes configurar estos parámetros para disminuir la tolerancia del sondeo de funcionamiento a fin de ajustar los requisitos del SLO de tu implementación.

      Desde la transmisión de eventos, verás que los sondeos de funcionamiento y de preparación del Pod fallan, y un mensaje que indica que el contenedor debe reiniciarse. El resultado es similar a lo siguiente:

      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
      

      Prepárate para la recuperación ante desastres

      Para asegurarte de que las cargas de trabajo de producción permanezcan disponibles en caso de un evento que interrumpa el servicio, debes preparar un plan de recuperación ante desastres (DR). Para obtener más información sobre la planificación de DR, consulta la Guía de planificación de recuperación ante desastres.

      La recuperación ante desastres para Kubernetes se puede implementar en dos fases:

      • La copia de seguridad implica la creación de una instantánea de un momento determinado del estado o los datos antes de que se produzca un evento que interrumpa el servicio.
      • La recuperación implica restablecer el estado o los datos de una copia de seguridad después de que ocurra un desastre.

      Para crear una copia de seguridad de tus cargas de trabajo en clústeres de GKE y restablecerlas, puedes usar Copia de seguridad para GKE. Puedes habilitar este servicio en clústeres nuevos y existentes. Esto implementa un agente de copia de seguridad para GKE que se ejecuta en tus clústeres; el agente es responsable de capturar los datos de copia de seguridad del volumen y la configuración, y organizar la recuperación.

      Las copias de seguridad y los restablecimientos se pueden aplicar a un clúster completo, a un espacio de nombres o a una aplicación (definido por selectores como matchLabels).

      Ejemplo de situación de copia de seguridad y restablecimiento de PostgreSQL

      En el ejemplo de esta sección, se muestra cómo realizar una operación de copia de seguridad y restablecimiento en el alcance de la aplicación con el recurso personalizado ProtectedApplication.

      En el siguiente diagrama, se muestran los recursos del componente en ProtectedApplication, es decir, un StatefulSet que representa la aplicación postgresql-ha y una implementación de pgpool, que usa la misma etiqueta (app.kubernetes.io/name: postgresql-ha).

      En el diagrama, se muestra un ejemplo de solución de copia de seguridad y recuperación para un clúster de PostgreSQL con alta disponibilidad.
      Figura 2: ejemplo de solución de copia de seguridad y recuperación para un clúster de PostgreSQL con alta disponibilidad.

      A fin de prepararte para crear una copia de seguridad de tu carga de trabajo de PostgreSQL y restablecerla, sigue estos pasos:

      1. Configura las variables de entorno. En este ejemplo, usarás una ProtectedApplication para restablecer la carga de trabajo de PostgreSQL y sus volúmenes desde el clúster de GKE de origen (us-central1) y, luego, restablecerlos a otro clúster de GKE en una región 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. Verifica que Copia de seguridad para GKE esté habilitado en tus clústeres. Ya debería estar habilitado como parte de la configuración de Terraform que realizaste antes.

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

        Si Copia de seguridad para GKE está habilitado, se muestra enabled=True en el resultado del comando.

      Configura un plan de copia de seguridad y realiza un restablecimiento

      La copia de seguridad para GKE te permite crear un plan de copia de seguridad como un trabajo cron. Un plan de copia de seguridad contiene una configuración de copia de seguridad que incluye el clúster de origen, la selección de las cargas de trabajo de las que se creará una copia de seguridad y la región en la que se almacenan los artefactos de copia de seguridad producidos en este plan.

      Para realizar una copia de seguridad y restablecimiento, sigue estos pasos:

      1. Verifica el estado de ProtectedApplication en cluster-db1.

        kubectl get ProtectedApplication -A
        

        El resultado es similar al siguiente:

        NAMESPACE    NAME            READY TO BACKUP
        postgresql   postgresql-ha   true
        
      2. Crea un plan de copia de seguridad para 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. Crea una copia de seguridad de forma manual.

        gcloud beta container backup-restore backups create $BACKUP_NAME \
        --project=$PROJECT_ID \
        --location=$DR_REGION \
        --backup-plan=$BACKUP_PLAN_NAME \
        --wait-for-completion
        
      4. Configura un plan de restablecimiento.

        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. Restablece las copias de seguridad.

        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
        

      Verifica que el clúster esté restablecido

      Para verificar que el clúster restablecido tenga todos los Pods, los PersistentVolumes y los recursos StorageClass esperados, sigue estos pasos:

      1. Configura el acceso de la línea de comandos de kubectl al clúster de copia de seguridad cluster-db2.

        gcloud container clusters get-credentials $TARGET_CLUSTER --location $DR_REGION --project $PROJECT_ID
        
      2. Verifica que el StatefulSet esté listo con 3/3 Pods.

        kubectl get all -n $NAMESPACE
        

        El resultado es similar a este:

        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. Verifica que todos los Pods en el espacio de nombres postgres estén en ejecución.

        kubectl get pods -n $NAMESPACE
        

        El resultado es similar a este:

        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. Verifica los PersistentVolumes y la StorageClass. Durante el proceso de restablecimiento, Copia de seguridad para GKE crea una clase de proxy en la carga de trabajo de destino para reemplazar la StorageClass aprovisionada en la carga de trabajo de origen (gce-pd-gkebackup-dn en el resultado de ejemplo).

        kubectl get pvc -n $NAMESPACE
        

        El resultado es similar a este:

        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
        

      Valida que se restablezcan los datos esperados

      Para validar que los datos esperados se restablezcan, sigue estos pasos:

      1. Conectarte a tu instancia de PostgreSQL

        ./scripts/launch-client.sh
        kubectl exec -it pg-client -n postgresql -- /bin/bash
        
      2. Verifica la cantidad de filas de cada tabla.

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

        Deberías ver un resultado similar a los datos que escribiste antes en Crea un conjunto de datos de prueba. El resultado es similar a este:

        300000
        (1 row)
        
      3. Sal del Pod del cliente.

        exit
        

      Realiza una limpieza

      Para evitar que se apliquen cargos a tu cuenta de Google Cloud por los recursos usados en este instructivo, borra el proyecto que contiene los recursos o conserva el proyecto y borra los recursos individuales.

      Borra el proyecto

      La manera más fácil de evitar la facturación es borrar el proyecto que creaste para el instructivo.

    2. In the Google Cloud console, go to the Manage resources page.

      Go to Manage resources

    3. In the project list, select the project that you want to delete, and then click Delete.
    4. In the dialog, type the project ID, and then click Shut down to delete the project.
    5. ¿Qué sigue?