In dieser Anleitung erfahren Sie, wie Sie PostgreSQL-Cluster mit dem Operator CloudNativePG in Google Kubernetes Engine (GKE) bereitstellen.
PostgreSQL ist eine objektrelationale Open-Source-Datenbank mit seit mehreren Jahrzehnten aktiver Entwicklung, die für eine stabile Clientleistung sorgt. Es bietet eine Reihe von Features, darunter Replikation, Wiederherstellung zu einem bestimmten Zeitpunkt, Sicherheitsfeatures und Erweiterbarkeit. PostgreSQL ist mit wichtigen Betriebssystemen kompatibel und entspricht vollständig den ACID-Standards (Atomarität, Konsistenz, Isolation, Langlebigkeit).
Dieser Leitfaden richtet sich an Plattformadministratoren, Cloud-Architekten und Betriebsexperten, die an der Bereitstellung von Postgres-Clustern in GKE interessiert sind. Wenn Sie Postgres in GKE anstelle von Cloud SQL ausführen, können erfahrene Datenbankadministratoren mehr Flexibilität und Konfigurationskontrollen erhalten.
Vorteile
CloudNativePG ist ein Open-Source-Operator, der von EDB unter einer Apache 2-Lizenz entwickelt wurde. Es bietet folgende Features für die PostgreSQL-Bereitstellung:
- Eine deklarative und Kubernetes-native Methode zum Verwalten und Konfigurieren von PostgreSQL-Clustern
- Sicherungsverwaltung mit Volume-Snapshots oder Cloud Storage
- Verschlüsselte TLS während der Übertragung, die Möglichkeit, Ihre eigene Zertifizierungsstelle zu verwenden und den Zertifikatmanager für die automatisierte Ausgabe und Rotation von TLS-Zertifikaten einzubinden
- Rolling Updates für PostgreSQL-Nebenversionen
- Verwendung des Kubernetes API-Servers zur Aufrechterhaltung des PostgreSQL-Clusterstatus und für Failover für Hochverfügbarkeit ohne zusätzliche Tools
- Eine integrierte Prometheus-Exporter-Konfiguration über benutzerdefinierte Messwerte, die in SQL geschrieben werden.
Ziele
- GKE-Infrastruktur für Redis planen und bereitstellen
- CloudNativePG Postgres-Operator mit Helm bereitstellen und konfigurieren
- PostgreSQL-Cluster bereitstellen
- PostgreSQL-Authentifizierung und -Beobachtbarkeit konfigurieren
Bereitstellungsarchitektur
PostgreSQL bietet verschiedene Bereitstellungsoptionen, von einem eigenständigen Datenbankserver bis zu einem replizierten hochverfügbaren Cluster. In dieser Anleitung geht es um die hochverfügbare Clusterbereitstellung in GKE.
In dieser Bereitstellung sind die PostgreSQL-Clusterarbeitslasten auf mehrere Verfügbarkeitszonen innerhalb des regionalen GKE-Clusters verteilt, um Hochverfügbarkeit und Redundanz zu gewährleisten. Weitere Informationen finden Sie unter Regionale Cluster.
Das folgende Diagramm zeigt einen Postgres-Cluster, der auf mehreren Knoten und Zonen in einem GKE-Cluster ausgeführt wird:
Die Standardeinrichtung umfasst einen Haupt-PostgreSQL-Server und zwei Sicherungsserver, die bei einem Ausfall des Hauptservers übernehmen können, um die kontinuierliche Verfügbarkeit der Datenbank zu gewährleisten.
Für die CloudNativePG-Operatorressourcen wird ein separater Namespace des GKE-Clusters verwendet, um die Ressourcenisolation und den empfohlenen Mikrodienstansatz mit einer Datenbank pro PostgreSQL-Cluster zu verbessern. Die Datenbank und der entsprechende Nutzer (Anwendungsnutzer) werden in der benutzerdefinierten Kubernetes-Ressource definiert, die den Cluster darstellt.
Speicher ist eine wichtige Komponente bei der Auseinandersetzung mit Datenbanken. Speicher müssen effizient arbeiten, kontinuierliche Verfügbarkeit gewährleisten und Datenkonsistenz gewährleisten. Aus diesen Gründen empfehlen wir die Speicherklasse
premium-rwo
, die auf SSD-Laufwerken basiert. Der CloudNativePG-Operator erstellt bei Bedarf automatischPersistentVolumeClaims
, wenn Pods für den PostgreSQL-Cluster eingerichtet werden.
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.
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.
Hinweise
Die Software, die Sie für diese Anleitung benötigen, ist in Cloud Shell vorinstalliert, einschließlich kubectl
, gcloud CLI, Helm und Terraform. Wenn Sie Cloud Shell nicht verwenden, müssen Sie die gcloud CLI installieren.
- 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.
- Install the Google Cloud CLI.
-
To initialize the gcloud CLI, run the following command:
gcloud init
-
Create or select a Google Cloud project.
-
Create a Google Cloud project:
gcloud projects create PROJECT_ID
Replace
PROJECT_ID
with a name for the Google Cloud project you are creating. -
Select the Google Cloud project that you created:
gcloud config set project PROJECT_ID
Replace
PROJECT_ID
with your Google Cloud project name.
-
-
Make sure that billing is enabled for your Google Cloud project.
-
Enable the Compute Engine, IAM, GKE, Resource Manager APIs:
gcloud services enable compute.googleapis.com
iam.googleapis.com container.googleapis.com cloudresourcemanager.googleapis.com - Install the Google Cloud CLI.
-
To initialize the gcloud CLI, run the following command:
gcloud init
-
Create or select a Google Cloud project.
-
Create a Google Cloud project:
gcloud projects create PROJECT_ID
Replace
PROJECT_ID
with a name for the Google Cloud project you are creating. -
Select the Google Cloud project that you created:
gcloud config set project PROJECT_ID
Replace
PROJECT_ID
with your Google Cloud project name.
-
-
Make sure that billing is enabled for your Google Cloud project.
-
Enable the Compute Engine, IAM, GKE, Resource Manager APIs:
gcloud services enable compute.googleapis.com
iam.googleapis.com container.googleapis.com cloudresourcemanager.googleapis.com -
Grant roles to your user account. Run the following command once for each of the following IAM roles:
roles/compute.securityAdmin, roles/compute.viewer, roles/container.clusterAdmin, roles/container.admin, roles/iam.serviceAccountAdmin, roles/iam.serviceAccountUser
gcloud projects add-iam-policy-binding PROJECT_ID --member="user:USER_IDENTIFIER" --role=ROLE
- Replace
PROJECT_ID
with your project ID. -
Replace
USER_IDENTIFIER
with the identifier for your user account. For example,user:myemail@example.com
. - Replace
ROLE
with each individual role.
- Replace
Umgebung einrichten
So richten Sie Ihre Umgebung ein:
Legen Sie Umgebungsvariablen fest:
export PROJECT_ID=PROJECT_ID export KUBERNETES_CLUSTER_PREFIX=postgres export REGION=us-central1
Ersetzen Sie
PROJECT_ID
durch Ihre Google Cloud-Projekt-ID.Klonen Sie das GitHub-Repository:
git clone https://github.com/GoogleCloudPlatform/kubernetes-engine-samples
Wechseln Sie in das Arbeitsverzeichnis:
cd kubernetes-engine-samples/databases/postgresql-cloudnativepg
Clusterinfrastruktur erstellen
In diesem Abschnitt führen Sie ein Terraform-Skript aus, um einen privaten, hochverfügbaren regionalen GKE-Cluster zu erstellen.
Sie können den Operator mit einem Standard- oder Autopilot-Cluster installieren.
Standard
Das folgende Diagramm zeigt einen privaten regionalen Standard-GKE-Cluster, der in drei verschiedenen Zonen bereitgestellt wird:
Führen Sie die folgenden Befehle aus, um diese Infrastruktur bereitzustellen:
export GOOGLE_OAUTH_ACCESS_TOKEN=$(gcloud auth print-access-token)
terraform -chdir=terraform/gke-standard init
terraform -chdir=terraform/gke-standard apply \
-var project_id=${PROJECT_ID} \
-var region=${REGION} \
-var cluster_prefix=${KUBERNETES_CLUSTER_PREFIX}
Geben Sie bei Aufforderung yes
ein. Es kann einige Minuten dauern, bis dieser Befehl abgeschlossen ist und der Cluster den Status „Bereit“ anzeigt.
Terraform erstellt die folgenden Ressourcen:
- Ein VPC-Netzwerk und ein privates Subnetz für die Kubernetes-Knoten
- Ein Router für den Zugriff auf das Internet über NAT
- Ein privater GKE-Cluster in der Region
us-central1
- Knotenpools mit aktiviertem Autoscaling (ein bis zwei Knoten pro Zone, mindestens ein Knoten pro Zone)
Die Ausgabe sieht in etwa so aus:
...
Apply complete! Resources: 14 added, 0 changed, 0 destroyed.
...
Autopilot
Das folgende Diagramm zeigt einen privaten regionalen Autopilot-GKE-Cluster:
Führen Sie die folgenden Befehle aus, um die Infrastruktur bereitzustellen:
export GOOGLE_OAUTH_ACCESS_TOKEN=$(gcloud auth print-access-token)
terraform -chdir=terraform/gke-autopilot init
terraform -chdir=terraform/gke-autopilot apply \
-var project_id=${PROJECT_ID} \
-var region=${REGION} \
-var cluster_prefix=${KUBERNETES_CLUSTER_PREFIX}
Geben Sie bei Aufforderung yes
ein. Es kann einige Minuten dauern, bis dieser Befehl abgeschlossen ist und der Cluster den Status „Bereit“ anzeigt.
Terraform erstellt die folgenden Ressourcen:
- Ein VPC-Netzwerk und ein privates Subnetz für die Kubernetes-Knoten
- Ein Router für den Zugriff auf das Internet über NAT
- Ein privater GKE-Cluster in der Region
us-central1
- Ein
ServiceAccount
mit Logging- und Monitoring-Berechtigung - Google Cloud Managed Service for Prometheus für das Clustermonitoring
Die Ausgabe sieht in etwa so aus:
...
Apply complete! Resources: 12 added, 0 changed, 0 destroyed.
...
Mit dem Cluster verbinden
Konfigurieren Sie kubectl
für die Kommunikation mit dem Cluster:
gcloud container clusters get-credentials ${KUBERNETES_CLUSTER_PREFIX}-cluster --region ${REGION}
CloudNativePG-Operator bereitstellen
Stellen Sie die CloudNativePG mithilfe eines Helm-Diagramms in Ihrem Kubernetes-Cluster bereit:
Fügen Sie das Helm-Diagramm-Repository für den CloudNativePG-Operator hinzu:
helm repo add cnpg https://cloudnative-pg.github.io/charts
Stellen Sie den CloudNativePG-Operator mit dem Helm-Befehlszeilentool bereit:
helm upgrade --install cnpg \ --namespace cnpg-system \ --create-namespace \ cnpg/cloudnative-pg
Die Ausgabe sieht in etwa so aus:
Release "cnpg" does not exist. Installing it now. NAME: cnpg LAST DEPLOYED: Fri Oct 13 13:52:36 2023 NAMESPACE: cnpg-system STATUS: deployed REVISION: 1 TEST SUITE: None ...
Postgres bereitstellen
Das folgende Manifest beschreibt einen PostgreSQL-Cluster, wie durch die benutzerdefinierte Ressource des CloudNativePG-Operators definiert:
Dieses Manifest hat die folgenden Felder:
spec.instances
: die Anzahl der Cluster-Podsspec.primaryUpdateStrategy
: die Rolling Update-Strategie:Unsupervised
: aktualisiert den primären Clusterknoten automatisch nach den ReplikatknotenSupervised
: für den primären Clusterknoten ist ein manueller Switchover erforderlich
spec.postgresql
:postgres.conf
-Dateiparameterüberschreibungen, z. B. pg-hba-Regeln, LDAP und Anforderungen für die Erfüllung von Synchronisierungsreplikaten.spec.storage
: speicherbezogene Einstellungen wie Speicherklasse, Volume-Größe und Write-Ahead-Log-Einstellungen.spec.bootstrap
: Parameter der ersten im Cluster erstellten Datenbank, Nutzeranmeldedaten und Optionen zur Datenbankwiederherstellungspec.resources
sind Anfragen und Limits für Cluster-Podsspec.affinity
: Affinitäts- und Anti-Affinitätsregeln der Clusterarbeitslasten
Einfachen Postgres-Cluster erstellen
Erstellen Sie einen Namespace:
kubectl create ns pg-ns
Erstellen Sie den PostgreSQL-Cluster mit der benutzerdefinierten Ressource:
kubectl apply -n pg-ns -f manifests/01-basic-cluster/postgreSQL_cluster.yaml
Die Ausführung dieses Befehls kann mehrere Minuten dauern.
Prüfen Sie den Clusterstatus:
kubectl get cluster -n pg-ns --watch
Warten Sie, bis die Ausgabe den Status
Cluster in healthy state
anzeigt, bevor Sie mit dem nächsten Schritt fortfahren.NAME AGE INSTANCES READY STATUS PRIMARY gke-pg-cluster 2m53s 3 3 Cluster in healthy state gke-pg-cluster-1
Ressourcen überprüfen
Prüfen Sie, ob GKE die Ressourcen für den Cluster erstellt hat:
kubectl get cluster,pod,svc,pvc,pdb,secret,cm -n pg-ns
Die Ausgabe sieht in etwa so aus:
NAME AGE INSTANCES READY STATUS PRIMARY
cluster.postgresql.cnpg.io/gke-pg-cluster 32m 3 3 Cluster in healthy state gke-pg-cluster-1
NAME READY STATUS RESTARTS AGE
pod/gke-pg-cluster-1 1/1 Running 0 31m
pod/gke-pg-cluster-2 1/1 Running 0 30m
pod/gke-pg-cluster-3 1/1 Running 0 29m
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/gke-pg-cluster-r ClusterIP 10.52.11.24 <none> 5432/TCP 32m
service/gke-pg-cluster-ro ClusterIP 10.52.9.233 <none> 5432/TCP 32m
service/gke-pg-cluster-rw ClusterIP 10.52.1.135 <none> 5432/TCP 32m
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
persistentvolumeclaim/gke-pg-cluster-1 Bound pvc-bbdd1cdd-bdd9-4e7c-8f8c-1a14a87e5329 2Gi RWO standard 32m
persistentvolumeclaim/gke-pg-cluster-2 Bound pvc-e7a8b4df-6a3e-43ce-beb0-b54ec1d24011 2Gi RWO standard 31m
persistentvolumeclaim/gke-pg-cluster-3 Bound pvc-dac7f931-6ac5-425f-ac61-0cfc55aae72f 2Gi RWO standard 30m
NAME MIN AVAILABLE MAX UNAVAILABLE ALLOWED DISRUPTIONS AGE
poddisruptionbudget.policy/gke-pg-cluster 1 N/A 1 32m
poddisruptionbudget.policy/gke-pg-cluster-primary 1 N/A 0 32m
NAME TYPE DATA AGE
secret/gke-pg-cluster-app kubernetes.io/basic-auth 3 32m
secret/gke-pg-cluster-ca Opaque 2 32m
secret/gke-pg-cluster-replication kubernetes.io/tls 2 32m
secret/gke-pg-cluster-server kubernetes.io/tls 2 32m
secret/gke-pg-cluster-superuser kubernetes.io/basic-auth 3 32m
NAME DATA AGE
configmap/cnpg-default-monitoring 1 32m
configmap/kube-root-ca.crt 1 135m
Der Operator erstellt die folgenden Ressourcen:
- Eine benutzerdefinierte Clusterressource, die den vom Operator gesteuerten PostgreSQL-Cluster darstellt
- PersistentVolumeClaim-Ressourcen mit entsprechenden nichtflüchtigen Volumes
- Secrets mit Nutzeranmeldedaten für den Zugriff auf die Datenbank und die Replikation zwischen Postgres-Knoten.
- Drei Datenbank-Endpunktdienste:
<name>-rw
,<name>-ro
und<name>-r
zum Herstellen einer Verbindung zum Cluster. Weitere Informationen finden Sie unter PostgreSQL-Architektur.
Bei Postgres authentifizieren
Sie können eine Verbindung zur PostgreSQL-Datenbank herstellen und den Zugriff über verschiedene vom Operator erstellte Dienstendpunkte prüfen. Dazu verwenden Sie einen zusätzlichen Pod mit einem PostgreSQL-Client und synchronisierten Anmeldedaten von Anwendungsnutzern, die als Umgebungsvariablen bereitgestellt wurden.
Führen Sie den Client-Pod aus, um mit Ihrem Postgres-Cluster zu interagieren:
kubectl apply -n pg-ns -f manifests/02-auth/pg-client.yaml
Führen Sie einen
exec
-Befehl auf dem Podpg-client
aus und melden Sie sich beim Dienstgke-pg-cluster-rw
an:kubectl wait --for=condition=Ready -n pg-ns pod/pg-client --timeout=300s kubectl exec -n pg-ns -i -t pg-client -- /bin/sh
Melden Sie sich mit dem Dienst
gke-pg-cluster-rw
bei der Datenbank an, um eine Verbindung mit Lese-/Schreibberechtigungen herzustellen:psql postgresql://$CLIENTUSERNAME:$CLIENTPASSWORD@gke-pg-cluster-rw.pg-ns/app
Das Terminal beginnt mit dem Namen Ihrer Datenbank:
app=>
Eine Tabelle erstellen:
CREATE TABLE travel_agency_clients ( client VARCHAR ( 50 ) UNIQUE NOT NULL, address VARCHAR ( 50 ) UNIQUE NOT NULL, phone VARCHAR ( 50 ) UNIQUE NOT NULL);
Fügen Sie Daten in die Tabelle ein:
INSERT INTO travel_agency_clients(client, address, phone) VALUES ('Tom', 'Warsaw', '+55555') RETURNING *;
Rufen Sie die von Ihnen erstellten Daten auf:
SELECT * FROM travel_agency_clients ;
Die Ausgabe sieht in etwa so aus:
client | address | phone --------+---------+--------- Tom | Warsaw | +55555 (1 row)
Melden Sie sich von der aktuellen Datenbanksitzung ab:
exit
Melden Sie sich mit dem Dienst
gke-pg-cluster-ro
bei der Datenbank an, um den Lesezugriff zu prüfen. Dieser Dienst ermöglicht das Abfragen von Daten, schränkt jedoch alle Schreibvorgänge ein:psql postgresql://$CLIENTUSERNAME:$CLIENTPASSWORD@gke-pg-cluster-ro.pg-ns/app
Versuchen Sie, neue Daten einzufügen:
INSERT INTO travel_agency_clients(client, address, phone) VALUES ('John', 'Paris', '+55555') RETURNING *;
Die Ausgabe sieht in etwa so aus:
ERROR: cannot execute INSERT in a read-only transaction
Versuchen, Daten zu lesen:
SELECT * FROM travel_agency_clients ;
Die Ausgabe sieht in etwa so aus:
client | address | phone --------+---------+--------- Tom | Warsaw | +55555 (1 row)
Melden Sie sich von der aktuellen Datenbanksitzung ab:
exit
Beenden Sie die Pod-Shell:
exit
Informationen zum Erfassen von Messwerten für den Postgres-Cluster durch Prometheus
Das folgende Diagramm zeigt, wie die Erfassung von Prometheus-Messwerten funktioniert:
Im Diagramm enthält ein privater GKE-Cluster Folgendes:
- Einen Postgres-Pod, der Messwerte für den Pfad
/
und den Port9187
erfasst. - Prometheus-basierte Collectors, die die Messwerte aus dem Postgres-Pod verarbeiten.
- Eine
PodMonitoring
-Ressource, die Messwerte an Cloud Monitoring sendet
Führen Sie die folgenden Schritte aus, um das Erfassen von Messwerten aus Ihren Pods zu ermöglichen:
Erstellen Sie die Ressource
PodMonitoring
:kubectl apply -f manifests/03-observability/pod-monitoring.yaml -n pg-ns
Rufen Sie in der Google Cloud Console die Seite Metrics Explorer auf.
Im Dashboard wird eine Datenaufnahmerate ungleich null angezeigt.
Geben Sie unter Messwert auswählen den Wert Prometheus-Ziel ein.
Wählen Sie im Bereich Aktive Messwertkategorien die Option Cnpg aus.
Messwert-Dashboard erstellen
Erstellen Sie ein Messwert-Dashboard, um die exportierten Messwerte zu visualisieren.
Stellen Sie ein Dashboard bereit:
gcloud --project "${PROJECT_ID}" monitoring dashboards create --config-from-file manifests/03-observability/gcp-pg.json
Rufen Sie in der Google Cloud Console die Seite Dashboards auf.
Wählen Sie das Dashboard PostgresQL Prometheus – Übersicht aus.
Wenn Sie prüfen möchten, wie Dashboards Funktionen überwachen, können Sie Aktionen aus dem Abschnitt Datenbankauthentifizierung wiederverwenden, Lese- und Schreibanfragen auf die Datenbank anwenden und die Visualisierung der erfassten Messwerte in einem Dashboard ansehen.
Stellen Sie eine Verbindung zum Client-Pod her:
kubectl exec -n pg-ns -i -t pg-client -- /bin/sh
Zufällige Daten einfügen:
psql postgresql://$CLIENTUSERNAME:$CLIENTPASSWORD@gke-pg-cluster-rw.pg-ns/app -c "CREATE TABLE test (id serial PRIMARY KEY, randomdata VARCHAR ( 50 ) NOT NULL);INSERT INTO test (randomdata) VALUES (generate_series(1, 1000));"
Dashboard aktualisieren Die Grafiken werden mit den aktualisierten Messwerten aktualisiert.
Beenden Sie die Pod-Shell:
exit
Bereinigen
Projekt löschen
Delete a Google Cloud project:
gcloud projects delete PROJECT_ID
Einzelne Ressourcen löschen
Umgebungsvariablen festlegen
export PROJECT_ID=${PROJECT_ID} export KUBERNETES_CLUSTER_PREFIX=postgres export REGION=us-central1
Führen Sie den Befehl
terraform destroy
aus:export GOOGLE_OAUTH_ACCESS_TOKEN=$(gcloud auth print-access-token) terraform -chdir=terraform/FOLDER destroy \ -var project_id=${PROJECT_ID} \ -var region=${REGION} \ -var cluster_prefix=${KUBERNETES_CLUSTER_PREFIX}
Ersetzen Sie
FOLDER
durchgke-autopilot
odergke-standard
.Geben Sie bei Aufforderung
yes
ein.Alle nicht angehängten Laufwerke suchen:
export disk_list=$(gcloud compute disks list --filter="-users:* AND labels.name=${KUBERNETES_CLUSTER_PREFIX}-cluster" --format "value[separator=|](name,zone)")
Laufwerke löschen:
for i in $disk_list; do disk_name=$(echo $i| cut -d'|' -f1) disk_zone=$(echo $i| cut -d'|' -f2|sed 's|.*/||') echo "Deleting $disk_name" gcloud compute disks delete $disk_name --zone $disk_zone --quiet done
Nächste Schritte
- Referenzarchitekturen, Diagramme und Best Practices zu Google Cloud kennenlernen. Weitere Informationen zu Cloud Architecture Center