Hochverfügbare PostgreSQL-Datenbank in GKE bereitstellen


PostgreSQL ist eine objektrelationale Open-Source-Datenbank, die für Zuverlässigkeit und Datenintegrität bekannt ist. Es ist ACID-kompatibel und unterstützt Fremdschlüssel, Joins, Ansichten, Trigger und gespeicherte Prozeduren.

Dieses Dokument richtet sich an Datenbankadministratoren, Cloud-Architekten und Betriebsexperten, die an der Bereitstellung einer hochverfügbaren PostgreSQL-Topologie in Google Kubernetes Engine (GKE) interessiert sind.

Lernziele

In dieser Anleitung erhalten Sie Informationen zu folgenden Themen:

  • Verwenden Sie Terraform, um einen regionalen GKE-Cluster zu erstellen.
  • Stellen Sie hochverfügbare PostgreSQL-Datenbank bereit.
  • Richten Sie das Monitoring für die PostgreSQL-Anwendung ein.
  • Führen Sie PostgreSQL-Datenbank- und GKE-Clusterupgrades durch.
  • Simulieren Sie Clusterunterbrechung und PostgreSQL-Replikat-Failover.
  • Führen Sie die Sicherung und Wiederherstellung der PostgreSQL-Datenbank durch.

Architektur

In diesem Abschnitt wird die Architektur der Lösung beschrieben, die Sie in dieser Anleitung erstellen.

Sie stellen zwei GKE-Cluster in verschiedenen Regionen bereit: einen primären Cluster und einen Sicherungscluster. In dieser Anleitung befindet sich der primäre Cluster in der Region us-central1 und der Sicherungscluster in der Region us-west1. Mit dieser Architektur können Sie eine hochverfügbare PostgreSQL-Datenbank bereitstellen und wie weiter unten in dieser Anleitung beschrieben zur Notfallwiederherstellung testen.

Für den Quellcluster verwenden Sie ein Helm-Diagramm (bitnami/postgresql-ha), um einen PostgreSQL-Cluster mit Hochverfügbarkeit einzurichten.

Das Diagramm zeigt eine Beispielarchitektur eines hochverfügbaren PostgreSQL-Clusters.
Abbildung 1: Beispielarchitektur eines hochverfügbaren PostgreSQL-Clusters.

Kosten

In diesem Dokument verwenden Sie die folgenden kostenpflichtigen Komponenten von Google Cloud:

Mit dem Preisrechner können Sie eine Kostenschätzung für Ihre voraussichtliche Nutzung vornehmen. Neuen Google Cloud-Nutzern steht möglicherweise eine kostenlose Testversion zur Verfügung.

Nach Abschluss der in diesem Dokument beschriebenen Aufgaben können Sie weitere Kosten vermeiden, indem Sie die erstellten Ressourcen löschen. Weitere Informationen finden Sie unter Bereinigen.

Hinweis

Projekt einrichten

  1. Melden Sie sich bei Ihrem Google Cloud-Konto an. Wenn Sie mit Google Cloud noch nicht vertraut sind, erstellen Sie ein Konto, um die Leistungsfähigkeit unserer Produkte in der Praxis sehen und bewerten zu können. Neukunden erhalten außerdem ein Guthaben von 300 $, um Arbeitslasten auszuführen, zu testen und bereitzustellen.
  2. Klicken Sie in der Google Cloud Console auf der Projektauswahlseite auf Projekt erstellen, um mit der Erstellung eines neuen Google Cloud-Projekts zu starten.

    Zur Projektauswahl

  3. Die Abrechnung für das Google Cloud-Projekt muss aktiviert sein.

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

    Aktivieren Sie die APIs

  5. Klicken Sie in der Google Cloud Console auf der Projektauswahlseite auf Projekt erstellen, um mit der Erstellung eines neuen Google Cloud-Projekts zu starten.

    Zur Projektauswahl

  6. Die Abrechnung für das Google Cloud-Projekt muss aktiviert sein.

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

    Aktivieren Sie die APIs

Rollen einrichten

  1. Gewähren Sie Ihrem Google-Konto Rollen. Führen Sie den folgenden Befehl für jede der folgenden IAM-Rollen einmal aus: 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:EMAIL_ADDRESS" --role=ROLE
    • Ersetzen Sie PROJECT_ID durch Ihre Projekt-ID.
    • Ersetzen Sie EMAIL_ADDRESS durch Ihre E-Mail-Adresse.
    • Ersetzen Sie ROLE durch jede einzelne Rolle.

Umgebung einrichten

In dieser Anleitung verwenden Sie Cloud Shell zum Verwalten von Ressourcen, die in Google Cloud gehostet werden. Die Software, die Sie für diese Anleitung benötigen, ist in Cloud Shell vorinstalliert, einschließlich Docker, kubectl und der gcloud CLI, Helm und Terraform.

So richten Sie Ihre Umgebung mit Cloud Shell ein:

  1. Starten Sie eine Cloud Shell-Sitzung über die Google Cloud Console. Klicken Sie dazu in der Google Cloud Console auf Symbol für die Cloud Shell-Aktivierung Cloud Shell aktivieren. Dadurch wird im unteren Bereich der Google Cloud Console eine Sitzung gestartet.

  2. Umgebungsvariablen festlegen

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

    Ersetzen Sie die folgenden Werte:

  3. Legen Sie die Standardumgebungsvariablen fest.

    gcloud config set project PROJECT_ID
    
  4. Klonen Sie das Code-Repository.

    git clone https://github.com/GoogleCloudPlatform/kubernetes-engine-samples
    
  5. Wechseln Sie in das Arbeitsverzeichnis.

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

Clusterinfrastruktur erstellen

In diesem Abschnitt führen Sie ein Terraform-Skript aus, um eine benutzerdefinierte Virtual Private Cloud (VPC), ein Artifact Registry-Repository zum Speichern von PostgreSQL-Images und zwei regionale GKE-Cluster zu erstellen. Ein Cluster wird in us-central1 und der zweite Cluster für die Sicherung in us-west1 bereitgestellt.

So erstellen Sie den Cluster:

Autopilot

Führen Sie in Cloud Shell die folgenden Befehle aus:

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

Geben Sie bei Aufforderung yes ein.

Informationen zur Terraform-Konfiguration

Die Terraform-Konfigurationsdateien erstellen die folgenden Ressourcen, um Ihre Infrastruktur bereitzustellen:

  • Erstellen Sie ein Artifact Registry-Repository zum Speichern der Docker-Images.
    resource "google_artifact_registry_repository" "main" {
      location      = "us"
      repository_id = "main"
      format        = "DOCKER"
      project       = var.project_id
    }
  • Erstellen Sie das VPC-Netzwerk und das Subnetz für die Netzwerkschnittstelle der 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]
    }
  • Erstellen Sie einen primären GKE-Cluster.

    Terraform erstellt einen privaten Cluster in der Region us-central1 und aktiviert Backup for GKE für die Notfallwiederherstellung und Managed Service for Prometheus für das Clustermonitoring.

    Managed Service for Prometheus wird nur auf Autopilot-Clustern mit GKE-Version 1.25 oder höher unterstützt.

    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
    }

  • Erstellen Sie einen Sicherungscluster in der Region us-west1 für die Notfallwiederherstellung.

    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
    }

Standard

Führen Sie in Cloud Shell die folgenden Befehle aus:

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

Geben Sie bei Aufforderung yes ein.

Informationen zur Terraform-Konfiguration

Die Terraform-Konfigurationsdateien erstellen die folgenden Ressourcen, um Ihre Infrastruktur bereitzustellen:

  • Erstellen Sie ein Artifact Registry-Repository zum Speichern der Docker-Images.
    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}",
      ]
    }
  • Erstellen Sie das VPC-Netzwerk und das Subnetz für die Netzwerkschnittstelle der 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]
    }
  • Erstellen Sie einen primären GKE-Cluster.

    Terraform erstellt einen privaten Cluster in der Region us-central1 und aktiviert Backup for GKE für die Notfallwiederherstellung und Managed Service for Prometheus für das Clustermonitoring.

    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
    }

  • Erstellen Sie einen Sicherungscluster in der Region us-west1 für die Notfallwiederherstellung.

    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
    }

PostgreSQL im Cluster bereitstellen

In diesem Abschnitt stellen Sie eine PostgreSQL-Datenbankinstanz mithilfe eines Helm-Diagramms in GKE bereit.

PostgreSQL installieren

So installieren Sie PostgreSQL auf Ihrem Cluster:

  1. Konfigurieren Sie den Docker-Zugriff.

    gcloud auth configure-docker us-docker.pkg.dev
    
  2. Füllen Sie Artifact Registry mit den erforderlichen PostgreSQL-Docker-Images aus.

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

    Das Skript überträgt die folgenden Bitnami-Images an Artifact Registry, damit Helm installiert werden kann:

  3. Prüfen Sie, ob im Repository die richtigen Images gespeichert sind.

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

    Die Ausgabe sieht in etwa so aus:

    ---
    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. Konfigurieren Sie den Zugriff auf die kubectl-Befehlszeile für den primären Cluster.

    gcloud container clusters get-credentials $SOURCE_CLUSTER \
    --region=$REGION --project=$PROJECT_ID
    
  5. Namespace erstellen

    export NAMESPACE=postgresql
    kubectl create namespace $NAMESPACE
    
  6. Wenn Sie in einem Autopilot-Cluster bereitstellen, konfigurieren Sie die Knotenbereitstellung in drei Zonen. Sie können diesen Schritt überspringen, wenn Sie die Bereitstellung in einem Standardcluster vornehmen.

    Standardmäßig stellt Autopilot Ressourcen in nur zwei Zonen bereit. Durch die in prepareforha.yaml definierte Bereitstellung wird sichergestellt, dass Autopilot Knoten in drei Zonen Ihres Clusters bereitstellt. Dazu werden diese Werte festgelegt:

    • replicas:3
    • podAntiAffinity mit requiredDuringSchedulingIgnoredDuringExecution und 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. Aktualisieren Sie die Helm-Abhängigkeit.

    cd helm/postgresql-bootstrap
    helm dependency update
    
  8. Prüfen und prüfen Sie die Diagramme, die Helm installiert.

    helm -n postgresql template postgresql . \
      --set global.imageRegistry="us-docker.pkg.dev/$PROJECT_ID/main"
    
  9. Installieren Sie das Helm-Diagramm.

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

    Die Ausgabe sieht in etwa so aus:

    NAMESPACE: postgresql
    STATUS: deployed
    REVISION: 1
    TEST SUITE: None
    
  10. Prüfen Sie, ob die Replikate ausgeführt werden.

    kubectl get all -n $NAMESPACE
    

    Die Ausgabe sieht in etwa so aus:

    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
    

Test-Dataset erstellen

In diesem Abschnitt erstellen Sie eine Datenbank und eine Tabelle mit Beispielwerten. Die Datenbank dient als Test-Dataset für den Failover-Prozess, den Sie später in dieser Anleitung testen.

  1. eine Verbindung zur PostgreSQL-Instanz herstellen

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

    Die Ausgabe sieht in etwa so aus:

    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. Starten Sie eine Shell-Sitzung.

    kubectl exec -it pg-client -n postgresql -- /bin/bash
    
  3. Erstellen Sie eine Datenbank und eine Tabelle und fügen Sie einige Testzeilen ein.

    psql -h $HOST_PGPOOL -U postgres -a -q -f /tmp/scripts/generate-db.sql
    
  4. Prüfen Sie die Anzahl der Zeilen für jede Tabelle.

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

    Die Ausgabe sieht in etwa so aus:

    select COUNT(*) from tb01;
     count
    --------
     300000
    (1 row)
    
    select COUNT(*) from tb02;
     count
    --------
     300000
    (1 row)
    
  5. Erzeugen Sie Testdaten.

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

    Die Ausgabe sieht in etwa so aus:

    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. Beenden Sie den Postgres-Client-Pod.

    exit
    

PostgreSQL überwachen

In diesem Abschnitt sehen Sie Messwerte und richten Benachrichtigungen für Ihre PostgreSQL-Instanz ein. Sie verwenden Google Cloud Managed Service for Prometheus, um Monitoring und Benachrichtigungen durchzuführen.

Messwerte aufrufen

Ihre PostgreSQL-Bereitstellung enthält einen postgresql-exporter-Sidecar-Container. Dieser Container stellt einen /metrics-Endpunkt bereit. Google Cloud Managed Service for Prometheus ist so konfiguriert, dass die PostgreSQL-Pods an diesem Endpunkt überwacht werden. Sie können diese Messwerte über die Dashboards der Google Cloud Console aufrufen.

Die Google Cloud Console bietet verschiedene Möglichkeiten zum Erstellen und Speichern der Dashboard-Konfiguration:

  • Erstellung und Export: Sie können Dashboards direkt in der Google Cloud Console erstellen und dann in einem Code-Repository exportieren und speichern. Öffnen Sie dazu in der Dashboard-Symbolleiste den JSON-Editor und laden Sie die JSON-Datei des Dashboards herunter.
  • Speichern und Importieren: Zum Importieren eines Dashboards aus einer JSON-Datei klicken Sie auf +Dashboard erstellen und das Hochladen der JSON-Inhalte des Dashboards mithilfe des JSON-Editor-Menüs).

So visualisieren Sie Daten aus Ihrer PostgreSQL-Anwendung und Ihrem GKE-Cluster:

  1. Erstellen Sie die folgenden Dashboards.

    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. Rufen Sie in der Google Cloud Console das Cloud Monitoring-Dashboard auf. Zum Cloud Monitoring-Dashboard

  3. Wählen Sie in der Dashboardliste die Option Benutzerdefiniert aus. Die folgenden Dashboards werden angezeigt:

    • PostgreSQL-Übersicht: Zeigt Messwerte aus der PostgreSQL-Anwendung an, einschließlich Datenbankverfügbarkeit, Datenbankgröße und Transaktionslatenz.
    • GKE-PostgreSQL-Cluster: Zeigt einschließlich der CPU-, Arbeitsspeicher- und Volume-Auslastung Messwerte aus dem GKE-Cluster an, auf denen PostgreSQL ausgeführt wird.
  4. Klicken Sie auf die einzelnen Links, um die generierten Dashboards zu untersuchen.

Warnungen einrichten

Durch Benachrichtigungen werden Sie rechtzeitig über Probleme in Ihren Anwendungen informiert und können sie dann umgehend beheben. Sie können eine Benachrichtigungsrichtlinie erstellen, um anzugeben, unter welchen Umständen und wie Sie benachrichtigt werden möchten. Sie können auch Benachrichtigungskanäle erstellen, um auszuwählen, wohin Benachrichtigungen gesendet werden sollen.

In diesem Abschnitt verwenden Sie Terraform, um die folgenden Beispielbenachrichtigungen zu konfigurieren:

  • db_max_transaction: Überwacht die maximale Verzögerung von Transaktionen in Sekunden. Eine Benachrichtigung wird ausgelöst, wenn der Wert größer als 10 ist.
  • db_node_up: Überwacht den Status von Datenbank-Pods. 0 bedeutet, dass ein Pod ausgefallen ist und eine Benachrichtigung ausgelöst wird.

So richten Sie Benachrichtigungen ein:

  1. Konfigurieren Sie Benachrichtigungen mit 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
    

    Ersetzen Sie die folgenden Werte:

    • YOUR_EMAIL: Ihre E-Mail-Adresse.

    Die Ausgabe sieht in etwa so aus:

    Apply complete! Resources: 3 added, 0 changed, 0 destroyed.
    
  2. Stellen Sie eine Verbindung zum Client-Pod her.

    cd ../../../
    kubectl exec -it --namespace postgresql pg-client -- /bin/bash
    
  3. Generieren Sie einen Lasttest, um die Benachrichtigung db_max_transaction zu testen.

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

    Die Ausgabe sieht in etwa so aus:

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

    Die Benachrichtigung wird ausgelöst und sendet eine E-Mail an YOUR_EMAIL mit einem Betreff, der mit "[WARNUNG] Maximale Verzögerung der Transaktion" beginnt.

  4. Rufen Sie in der Google Cloud Console die Seite „Benachrichtigungsrichtlinie“ auf.

    Zur Benachrichtigungsrichtlinie

  5. Wählen Sie db_max_transaction aus den aufgeführten Richtlinien aus. Im Diagramm sollte ein Anstieg des Lasttests angezeigt werden, der den Schwellenwert von 10 für den Prometheus-Messwert pg_stat_activity_max_tx_duration/gauge überschreitet.

  6. Beenden Sie den Postgres-Client-Pod.

    exit
    

PostgreSQL- und GKE-Upgrades verwalten

Versionsupdates für PostgreSQL und Kubernetes werden regelmäßig veröffentlicht. Halten Sie sich an die Best Practices für den Betrieb von Software, um Ihre Softwareumgebung regelmäßig zu aktualisieren. Standardmäßig verwaltet GKE Upgrades für Cluster und Knotenpools.

Upgrade für PostgreSQL ausführen

In diesem Abschnitt wird gezeigt, wie Sie ein Versionsupgrade für PostgreSQL ausführen können. In dieser Anleitung verwenden Sie eine Rolling Update-Strategie für das Upgrade Ihrer Pods, sodass zu keinem Zeitpunkt alle Pods ausgefallen sind.

So führen Sie ein Versionsupgrade durch:

  1. Übertragen Sie eine aktualisierte Version des postgresql-repmgr-Images in Artifact Registry. Definieren Sie die neue Version (z. B. 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. Lösen Sie ein Rolling Update mit kubectl aus.

    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
    

    Das StatefulSet führt ein Rolling Update durch, beginnend mit dem höchsten Ordinalreplikat bis zum niedrigsten.

    Die Ausgabe sieht in etwa so aus:

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

GKE-Upgrades auf Standardclustern planen

Dieser Abschnitt gilt, wenn Sie Standardcluster ausführen. Sie können proaktive Schritte ausführen und Konfigurationen festlegen, um Risiken zu minimieren und ein reibungsloseres Clusterupgrade bei der Ausführung zustandsorientierter Dienste zu ermöglichen. Dazu gehören:

  • Folgen Sie den Best Practices für das Upgrade von Clustern. Wählen Sie eine geeignete Upgradestrategie, um sicherzustellen, dass die Upgrades während des Wartungsfensters stattfinden:

    • Wählen Sie Surge-Upgrades aus, wenn eine Kostenoptimierung wichtig ist und Ihre Arbeitslasten ein ordnungsgemäßes Herunterfahren in weniger als 60 Minuten tolerieren können.
    • Wählen Sie Blau/Grün-Upgrades, wenn Ihre Arbeitslasten weniger störungstolerant sind und eine vorübergehende Kostenerhöhung aufgrund einer höheren Ressourcennutzung akzeptabel ist.

    Weitere Informationen finden Sie unter Cluster aktualisieren, in dem eine zustandsorientierte Arbeitslast ausgeführt wird.

  • Mit dem Dienst Recommender können Sie nach Statistiken und Empfehlungen zur Einstellung suchen, um Dienstunterbrechungen zu vermeiden.

  • Verwenden Sie Wartungsfenster, um dafür zu Sorgen, dass Upgrades plangemäß erfolgen. Prüfen Sie vor dem Wartungsfenster, ob die Datenbanksicherungen erfolgreich waren.

  • Bevor Sie Traffic zu den aktualisierten MySQL-Knoten zulassen, sollten Sie Bereitschafts- und Aktivitätsprüfungen verwenden, um sicherzustellen, dass sie für den Traffic bereit sind.

  • Erstellen Sie Prüfungen, um zu sehen, ob die Replikation synchron ist, bevor Sie den Traffic akzeptieren. Je nach Komplexität und Umfang Ihrer Datenbank können Sie dafür benutzerdefinierte Skripts verwenden.

Datenbankverfügbarkeit während Standardclusterupgrades prüfen

Dieser Abschnitt gilt, wenn Sie Standardcluster ausführen. Wenn Sie die PostgreSQL-Verfügbarkeit während der Upgrades prüfen möchten, besteht der allgemeine Prozess darin, Traffic für die PostgreSQL-Datenbank während des Upgrades zu generieren. Verwenden Sie dann pgbench, um zu prüfen, ob die Datenbank während eines Upgrades eine Referenzebene im Vergleich zu einer vollständig verfügbaren Datenbank für den Traffic verarbeiten kann.

  1. eine Verbindung zur PostgreSQL-Instanz herstellen

    ./scripts/launch-client.sh
    

    Die Ausgabe sieht in etwa so aus:

    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. Stellen Sie in Cloud Shell eine Shell-Verbindung zum Client-Pod her.

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

    pgbench -i -h $HOST_PGPOOL -U postgres postgres
    
  4. Verwenden Sie den folgenden Befehl, um Referenzergebnisse abzurufen, um zu bestätigen, dass Ihre PostgreSQL-Anwendung während des Zeitfensters für ein Upgrade hochverfügbar ist. Um ein Basisergebnis zu erhalten, testen Sie 30 Sekunden lang mit mehreren Verbindungen über mehrere Jobs (Threads).

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

    Die Ausgabe sieht dann ungefähr so aus:

    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. Damit die Verfügbarkeit während der Upgrades gewährleistet ist, können Sie eine Last für Ihre Datenbank erzeugen und dafür sorgen, dass die PostgreSQL-Anwendung während des Upgrades eine konsistente Antwortrate bietet. Generieren Sie für diesen Test Traffic mit der Datenbank mithilfe des Befehls pgbench für die Datenbank. Der folgende Befehl führt pgbench eine Stunde lang aus, führt ein Targeting auf 200 TPS (Transaktionen pro Sekunde) durch und listet die Anfragerate alle zwei Sekunden auf.

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

    Wobei:

    • --client: Anzahl der simulierten Clients, also Anzahl der gleichzeitigen Datenbanksitzungen.
    • --jobs: Anzahl der Worker-Threads in pgbench. Die Verwendung mehrerer Threads kann auf Multi-CPU-Maschinen hilfreich sein. Clients werden so gleichmäßig wie möglich auf die verfügbaren Threads verteilt. Der Standardwert ist 1.
    • --rate: Die Rate wird in Transaktionen pro Sekunde angegeben
    • --progress: Fortschrittsbericht alle Sekunden anzeigen

    Die Ausgabe sieht in etwa so aus:

    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. Kehren Sie in der Google Cloud Console zum Dashboard PostgreSQL-Übersicht in Cloud Monitoring zurück. Beachten Sie die Spitzen in den Grafiken Verbindung pro DB und Verbindung pro Pod.

  7. Beenden Sie den Client-Pod.

    exit
    
  8. Löschen Sie den Client-Pod.

    kubectl delete pod -n postgresql pg-client
    

Unterbrechung eines PostgreSQL-Dienstes simulieren

In diesem Abschnitt simulieren Sie eine Dienstunterbrechung in einem der PostgreSQL-Replikate, indem Sie den Replikationsmanager-Dienst beenden. Dadurch wird verhindert, dass der Pod Traffic an seine Peer-Replikate und seine Aktivitätsprüfungen weiterleitet.

  1. Öffnen Sie eine neue Cloud Shell-Sitzung und konfigurieren Sie den Zugriff auf die kubectl-Befehlszeile für den primären Cluster.

    gcloud container clusters get-credentials $SOURCE_CLUSTER \
    --region=$REGION --project=$PROJECT_ID
    
  2. Sehen Sie sich die in Kubernetes ausgegebenen PostgreSQL-Ereignisse an.

    kubectl get events -n postgresql --field-selector=involvedObject.name=postgresql-postgresql-ha-postgresql-0 --watch
    
  3. Simulieren Sie in der vorherigen Cloud Shell-Sitzung einen Dienstfehler, indem Sie PostgreSQL repmgr beenden.

    1. Hängen Sie Ihre Sitzung an den Datenbankcontainer an.

      kubectl exec -it -n $NAMESPACE postgresql-postgresql-ha-postgresql-0 -c postgresql -- /bin/bash
      
    2. Beenden Sie den Dienst mit repmgr und entfernen Sie den Prüfpunkt und das Argument 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
      

Die für den PostgreSQL-Container konfigurierte Aktivitätsprüfung beginnt innerhalb von fünf Sekunden. Dies wird alle zehn Sekunden wiederholt, bis der Fehlerschwellenwert von sechs Fehlern erreicht wird. Sobald der Wert failureThreshold erreicht ist, wird der Container neu gestartet. Sie können diese Parameter so konfigurieren, dass die Toleranz für Aktivitätsprüfungen verringert wird, um die SLO-Anforderungen Ihrer Bereitstellung zu optimieren.

Im Ereignisstream sehen Sie, dass die Pod-Aktivitäts- und -Bereitschaftsprüfungen fehlschlagen und eine Meldung angezeigt wird, dass der Container neu gestartet werden muss. Die Ausgabe sieht in etwa so aus:

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

Vorbereitung für die Notfallwiederherstellung

Damit Ihre Produktionsarbeitslasten im Falle eines Dienstunterbrechungsereignisses verfügbar bleiben, sollten Sie einen Plan zur Notfallwiederherstellung (Disaster Recovery, DR) erstellen. Weitere Informationen zur Planung der Notfallwiederherstellung finden Sie im Leitfaden zur Planung der Notfallwiederherstellung.

Die Notfallwiederherstellung für Kubernetes kann in zwei Phasen implementiert werden:

  • Bei der Sicherung wird ein Snapshot Ihres Zustands oder Ihrer Daten zu einem bestimmten Zeitpunkt erstellt, bevor ein Dienstunterbrechungsereignis auftritt.
  • Bei der Wiederherstellung wird Ihr Zustand oder Ihre Daten aus einer Sicherungskopie nach einem Notfall wiederhergestellt.

Zum Sichern und Wiederherstellen Ihrer Arbeitslasten in GKE-Clustern können Sie Backup for GKE verwenden. Sie können diesen Dienst auf neuen und vorhandenen Clustern aktivieren. Dadurch wird ein Sicherung für GKE-Agent bereitgestellt, der in Ihren Clustern ausgeführt wird. Der Agent ist für die Erfassung von Konfigurations- und Volume-Sicherungsdaten und die Orchestrierung der Wiederherstellung verantwortlich.

Sicherungen und Wiederherstellungen können für einen gesamten Cluster, einen Namespace oder eine Anwendung gelten (definiert durch Selektoren wie matchLabels).

Beispiel für ein Sicherungs- und Wiederherstellungsszenario in PostgreSQL

Das Beispiel in diesem Abschnitt zeigt, wie Sie einen Sicherungs- und Wiederherstellungsvorgang auf Anwendungsebene mit der benutzerdefinierten Ressource ProtectedApplication ausführen können.

Das folgende Diagramm zeigt die Komponentenressourcen in der ProtectedApplication, nämlich ein StatefulSet, das die postgresql-ha-Anwendung und eine Bereitstellung von pgpool darstellt, die dasselbe Label (app.kubernetes.io/name: postgresql-ha) verwenden.

Das Diagramm zeigt ein Beispiel für eine Sicherungs- und Wiederherstellungslösung für einen hochverfügbaren PostgreSQL-Cluster.
Abbildung 2: Beispiel für eine Sicherungs- und Wiederherstellungslösung für einen hochverfügbaren PostgreSQL-Cluster.

So bereiten Sie die PostgreSQL-Arbeitslast vor, um sie zu sichern und wiederherzustellen:

  1. Richten Sie Umgebungsvariablen ein. In diesem Beispiel verwenden Sie eine ProtectedApplication, um die PostgreSQL-Arbeitslast und ihre Volumes aus dem GKE-Quellcluster (us-central1) wiederherzustellen, und dann in einem anderen GKE-Cluster in einer anderen Region (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. Prüfen, ob Backup for GKE in Ihrem Cluster aktiviert ist. Es sollte bereits im Rahmen der zuvor ausgeführten Terraform-Einrichtung aktiviert werden.

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

    Wenn Backup for GKE aktiviert ist, wird in der Ausgabe des Befehls enabled=True angezeigt.

Sicherungsplan einrichten und Wiederherstellung ausführen

Mit Backup for GKE können Sie einen Sicherungsplan als Cronjob erstellen. Ein Sicherungsplan enthält eine Sicherungskonfiguration, die den Quellcluster, die Auswahl der zu sichernden Arbeitslasten und die Region enthält, in der die unter diesem Plan erstellten Sicherungsartefakte gespeichert werden.

So führen Sie eine Sicherung und Wiederherstellung durch:

  1. Prüfen Sie den Status von ProtectedApplication auf cluster-db1.

    kubectl get ProtectedApplication -A
    

    Die Ausgabe sieht dann ungefähr so aus:

    NAMESPACE    NAME            READY TO BACKUP
    postgresql   postgresql-ha   true
    
  2. Erstellen Sie einen Sicherungsplan für die 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. Erstellen Sie manuell eine Sicherung.

    gcloud beta container backup-restore backups create $BACKUP_NAME \
    --project=$PROJECT_ID \
    --location=$DR_REGION \
    --backup-plan=$BACKUP_PLAN_NAME \
    --wait-for-completion
    
  4. Richten Sie einen Wiederherstellungsplan ein.

    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. Nehmen Sie die Wiederherstellung aus der Sicherung vor.

    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
    

Prüfen, ob der Cluster wiederhergestellt wurde

So prüfen Sie, ob der wiederhergestellte Cluster alle Pods, PersistentVolume- und StorageClass-Ressourcen enthält:

  1. Konfigurieren Sie den Zugriff auf die kubectl-Befehlszeile für den Sicherungscluster cluster-db2.

    gcloud container clusters get-credentials $TARGET_CLUSTER --region $DR_REGION --project $PROJECT_ID
    
  2. Prüfen Sie, ob das StatefulSet mit 3/3-Pods bereit ist.

    kubectl get all -n $NAMESPACE
    

    Die Ausgabe sieht in etwa so aus:

    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. Prüfen Sie, ob alle Pods im Namespace postgres ausgeführt werden.

    kubectl get pods -n $NAMESPACE
    

    Die Ausgabe sieht in etwa so aus:

    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. Prüfen Sie die PersistentVolumes und die StorageClass. Während des Wiederherstellungsprozesses erstellt Backup for GKE eine Proxy-Klasse in der Zielarbeitslast, um die in der Quellarbeitslast bereitgestellte StorageClass zu ersetzen (gce-pd-gkebackup-dn in der Beispielausgabe).

    kubectl get pvc -n $NAMESPACE
    

    Die Ausgabe sieht in etwa so aus:

    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
    

Erwartete Daten wiederherstellen

So können Sie prüfen, ob die erwarteten Daten wiederhergestellt wurden:

  1. eine Verbindung zur PostgreSQL-Instanz herstellen

    ./scripts/launch-client.sh
    kubectl exec -it pg-client -n postgresql -- /bin/bash
    
  2. Prüfen Sie die Anzahl der Zeilen für jede Tabelle.

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

    Sie sollten ein ähnliches Ergebnis wie die Daten sehen, die Sie zuvor unter Test-Dataset erstellen geschrieben haben. Die Ausgabe sieht in etwa so aus:

    300000
    (1 row)
    
  3. Beenden Sie den Client-Pod.

    exit
    

Bereinigen

Damit Ihrem Google Cloud-Konto die in dieser Anleitung verwendeten Ressourcen nicht in Rechnung gestellt werden, löschen Sie entweder das Projekt, das die Ressourcen enthält, oder Sie behalten das Projekt und löschen die einzelnen Ressourcen.

Projekt löschen

Sie vermeiden weitere Kosten am einfachsten, wenn Sie das für die Anleitung erstellte Projekt löschen.

Google Cloud-Projekt löschen:

gcloud projects delete PROJECT_ID

Nächste Schritte