La guida mostra come utilizzare l'operatore Zalando Postgres per eseguire il deployment di cluster Postgres in Google Kubernetes Engine (GKE).
PostgreSQL è un potente sistema di database relazionale a oggetti open source con diversi decenni di sviluppo attivo che gli hanno valso una solida reputazione per affidabilità, robustezza delle funzionalità e prestazioni.
Questa guida è pensata per amministratori di piattaforme, architetti cloud e professionisti delle operazioni interessati a eseguire PostgreSQL come applicazione di database su GKE anziché utilizzare Cloud SQL per PostgreSQL.
Obiettivi
- Pianifica ed esegui il deployment dell'infrastruttura GKE per Postgres
- Esegui il deployment e configura l'operatore Zalando Postgres
- Configura Postgres utilizzando l'operatore per garantire disponibilità, sicurezza, osservabilità e prestazioni
Vantaggi
Zalando offre i seguenti vantaggi:
- Un modo dichiarativo e nativo di Kubernetes per gestire e configurare i cluster PostgreSQL
- Alta disponibilità fornita da Patroni
- Supporto per la gestione dei backup tramite bucket Cloud Storage
- Aggiornamenti in sequenza delle modifiche al cluster Postgres, inclusi aggiornamenti rapidi delle versioni secondarie
- Gestione utenti dichiarativa con generazione e rotazione delle password utilizzando risorse personalizzate
- Supporto di TLS, rotazione dei certificati e pool di connessioni
- Clonazione del cluster e replica dei dati
Architettura di deployment
In questo tutorial utilizzerai l'operatore Zalando Postgres per eseguire il deployment e configurare un cluster Postgres a disponibilità elevata in GKE. Il cluster ha una replica leader e due repliche di standby (di sola lettura) gestite da Patroni. Patroni è una soluzione open source gestita da Zalando per fornire funzionalità di alta disponibilità e failover automatico a Postgres. In caso di errore del leader, una replica di standby viene promossa automaticamente al ruolo di leader.
Esegui anche il deployment di un cluster GKE regionale ad alta disponibilità per PostgreSQL, con più nodi Kubernetes distribuiti in diverse zone di disponibilità. Questa configurazione contribuisce a garantire tolleranza di errore, scalabilità e ridondanza geografica. Consente aggiornamenti e manutenzione in sequenza, fornendo al contempo SLA per uptime e disponibilità. Per saperne di più, consulta Cluster regionali.
Il seguente diagramma mostra un cluster Postgres in esecuzione su più nodi e zone in un cluster GKE:
Nel diagramma, il StatefulSet
Postgres viene implementato su tre nodi in tre zone diverse. Puoi controllare la modalità di deployment di GKE sui nodi impostando le regole di affinità e anti-affinità dei pod richieste nella specifica della risorsa personalizzata postgresql
. Se una zona non funziona, utilizzando la configurazione consigliata, GKE riprogramma i pod su altri nodi disponibili nel cluster. Per
rendere persistenti i dati, utilizzi dischi SSD (premium-rwo
StorageClass), che sono
consigliati nella maggior parte dei casi per i database
con carico elevato grazie alla
bassa latenza e agli IOPS elevati.
Costi
In questo documento vengono utilizzati i seguenti componenti fatturabili di Google Cloud:
Per generare una stima dei costi in base all'utilizzo previsto,
utilizza il calcolatore prezzi.
Al termine delle attività descritte in questo documento, puoi evitare l'addebito di ulteriori costi eliminando le risorse che hai creato. Per ulteriori informazioni, vedi Pulizia.
Prima di iniziare
Cloud Shell è preinstallato con il software necessario
per questo tutorial, tra cui
kubectl
, gcloud CLI, Helm e Terraform. Se non utilizzi Cloud Shell, devi
installare gcloud CLI.
- 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.
-
Se utilizzi un provider di identità (IdP) esterno, devi prima accedere alla gcloud CLI con la tua identità federata.
-
Per inizializzare gcloud CLI, esegui questo comando:
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, Backup for GKE APIs:
gcloud services enable compute.googleapis.com
iam.googleapis.com container.googleapis.com gkebackup.googleapis.com -
Install the Google Cloud CLI.
-
Se utilizzi un provider di identità (IdP) esterno, devi prima accedere alla gcloud CLI con la tua identità federata.
-
Per inizializzare gcloud CLI, esegui questo comando:
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, Backup for GKE APIs:
gcloud services enable compute.googleapis.com
iam.googleapis.com container.googleapis.com gkebackup.googleapis.com -
Grant roles to your user account. Run the following command once for each of the following IAM roles:
roles/storage.objectViewer, roles/container.admin, roles/iam.serviceAccountAdmin, roles/compute.admin, roles/gkebackup.admin, roles/monitoring.viewer
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
Imposta le variabili di ambiente:
export PROJECT_ID=PROJECT_ID export KUBERNETES_CLUSTER_PREFIX=postgres export REGION=us-central1
Sostituisci
PROJECT_ID
con l' Google Cloud ID progetto.Clona il repository GitHub:
git clone https://github.com/GoogleCloudPlatform/kubernetes-engine-samples
Passa alla directory di lavoro:
cd kubernetes-engine-samples/databases/postgres-zalando
- Una rete VPC e una subnet privata per i nodi Kubernetes
- Un router per accedere a internet tramite NAT
- Un cluster GKE privato nella regione
us-central1
- Un node pool con scalabilità automatica abilitata (da uno a due nodi per zona, minimo un nodo per zona)
- Un
ServiceAccount
con autorizzazioni di logging e monitoraggio - Backup per GKE per il ripristino di emergenza
- Google Cloud Managed Service per Prometheus per il monitoraggio del cluster
- Una rete VPC e una subnet privata per i nodi Kubernetes
- Un router per accedere a internet tramite NAT
- Un cluster GKE privato nella regione
us-central1
- Un
ServiceAccount
con l'autorizzazione di logging e monitoraggio - Google Cloud Managed Service per Prometheus per il monitoraggio del cluster
Aggiungi il repository del grafico Helm dell'operatore Zalando:
helm repo add postgres-operator-charts https://opensource.zalando.com/postgres-operator/charts/postgres-operator
Crea uno spazio dei nomi per l'operatore Zalando e il cluster Postgres:
kubectl create ns postgres kubectl create ns zalando
Esegui il deployment dell'operatore Zalando utilizzando lo strumento a riga di comando Helm:
helm install postgres-operator postgres-operator-charts/postgres-operator -n zalando \ --set configKubernetes.enable_pod_antiaffinity=true \ --set configKubernetes.pod_antiaffinity_preferred_during_scheduling=true \ --set configKubernetes.pod_antiaffinity_topology_key="topology.kubernetes.io/zone" \ --set configKubernetes.spilo_fsgroup="103"
Non puoi configurare le impostazioni di
podAntiAffinity
direttamente sulla risorsa personalizzata che rappresenta il cluster Postgres. Imposta invece le impostazioni dipodAntiAffinity
a livello globale per tutti i cluster Postgres nelle impostazioni dell'operatore.Controlla lo stato del deployment dell'operatore Zalando utilizzando Helm:
helm ls -n zalando
L'output è simile al seguente:
NAME NAMESPACE REVISION UPDATED STATUS CHART APP VERSION postgres-operator zalando 1 2023-10-13 16:04:13.945614 +0200 CEST deployed postgres-operator-1.10.1 1.10.1
- Tre repliche Postgres: una leader e due standby.
- Allocazione delle risorse CPU di una richiesta di CPU e due limiti di CPU, con 4 GB di richieste e limiti di memoria.
- Tolleranze,
nodeAffinities
etopologySpreadConstraints
configurati per ogni workload, garantendo una distribuzione corretta tra i nodi Kubernetes, utilizzando i rispettivi node pool e diverse zone di disponibilità. spec.teamId
: un prefisso per gli oggetti del cluster che sceglispec.numberOfInstances
: il numero totale di istanze per un clusterspec.users
: l'elenco di utenti con privilegispec.databases
: l'elenco dei database nel formatodbname: ownername
spec.postgresql
: parametri postgresspec.volume
: parametri di Persistent Diskspec.tolerations
: il modello di pod con tolleranze che consente di programmare i pod del cluster sui nodipool-postgres
spec.nodeAffinity
: il modello di podnodeAffinity
che indica a GKE che i pod del cluster preferiscono essere pianificati sui nodipool-postgres
.spec.resources
: richieste e limiti per i pod del clusterspec.sidecars
: un elenco di container sidecar, che contienepostgres-exporter
Crea un nuovo cluster Postgres utilizzando la configurazione di base:
kubectl apply -n postgres -f manifests/01-basic-cluster/my-cluster.yaml
Questo comando crea una risorsa personalizzata PostgreSQL dell'operatore Zalando con:
- Richieste e limiti di CPU e memoria
- Incompatibilità e affinità per distribuire le repliche di pod di cui è stato eseguito il provisioning tra i nodi GKE.
- Un database
- Due utenti con autorizzazioni di proprietario del database
- Un utente senza autorizzazioni
Attendi che GKE avvii i carichi di lavoro richiesti:
kubectl wait pods -l cluster-name=my-cluster --for condition=Ready --timeout=300s -n postgres
Il completamento di questo comando potrebbe richiedere alcuni minuti.
Verifica che GKE abbia creato i workload Postgres:
kubectl get pod,svc,statefulset,deploy,pdb,secret -n postgres
L'output è simile al seguente:
NAME READY STATUS RESTARTS AGE pod/my-cluster-0 1/1 Running 0 6m41s pod/my-cluster-1 1/1 Running 0 5m56s pod/my-cluster-2 1/1 Running 0 5m16s pod/postgres-operator-db9667d4d-rgcs8 1/1 Running 0 12m NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE service/my-cluster ClusterIP 10.52.12.109 <none> 5432/TCP 6m43s service/my-cluster-config ClusterIP None <none> <none> 5m55s service/my-cluster-repl ClusterIP 10.52.6.152 <none> 5432/TCP 6m43s service/postgres-operator ClusterIP 10.52.8.176 <none> 8080/TCP 12m NAME READY AGE statefulset.apps/my-cluster 3/3 6m43s NAME READY UP-TO-DATE AVAILABLE AGE deployment.apps/postgres-operator 1/1 1 1 12m NAME MIN AVAILABLE MAX UNAVAILABLE ALLOWED DISRUPTIONS AGE poddisruptionbudget.policy/postgres-my-cluster-pdb 1 N/A 0 6m44s NAME TYPE DATA AGE secret/my-user.my-cluster.credentials.postgresql.acid.zalan.do Opaque 2 6m45s secret/postgres.my-cluster.credentials.postgresql.acid.zalan.do Opaque 2 6m44s secret/sh.helm.release.v1.postgres-operator.v1 helm.sh/release.v1 1 12m secret/standby.my-cluster.credentials.postgresql.acid.zalan.do Opaque 2 6m44s secret/zalando.my-cluster.credentials.postgresql.acid.zalan.do Opaque 2 6m44s
- Un StatefulSet Postgres, che controlla tre repliche di pod per Postgres
- Un
PodDisruptionBudgets
, che garantisce un minimo di una replica disponibile - Il servizio
my-cluster
, che ha come target solo la replica leader - Il servizio
my-cluster-repl
, che espone la porta Postgres per le connessioni in entrata e per la replica tra le repliche Postgres - Il servizio headless
my-cluster-config
, per ottenere l'elenco delle repliche dei pod Postgres in esecuzione - Secret con le credenziali utente per accedere al database e alla replica tra i nodi Postgres
- L'utente
mydatabaseowner
dispone dei ruoliSUPERUSER
eCREATEDB
, che consentono diritti di amministratore completi (ad es. gestire la configurazione di Postgres, creare nuovi database, tabelle e utenti). Non devi condividere questo utente con i clienti. Ad esempio, Cloud SQL non consente ai clienti di accedere a utenti con il ruoloSUPERUSER
. - All'utente
myuser
non sono stati assegnati ruoli. Ciò segue la best practice di utilizzareSUPERUSER
per creare utenti con privilegi minimi. I diritti granulari sono concessi amyuser
damydatabaseowner
. Per mantenere la sicurezza, devi condividere le credenzialimyuser
solo con le applicazioni client. Esegui il pod client per interagire con il cluster Postgres:
kubectl apply -n postgres -f manifests/02-auth/client-pod.yaml
Le credenziali degli utenti
myuser
emydatabaseowner
vengono prese dai secret correlati e montate come variabili di ambiente nel pod.Connettiti al pod quando è pronto:
kubectl wait pod postgres-client --for=condition=Ready --timeout=300s -n postgres kubectl exec -it postgres-client -n postgres -- /bin/bash
Connettiti a Postgres e tenta di creare una nuova tabella utilizzando le credenziali
myuser
:PGPASSWORD=$CLIENTPASSWORD psql \ -h my-cluster \ -U $CLIENTUSERNAME \ -d mydatabase \ -c "CREATE TABLE test (id serial PRIMARY KEY, randomdata VARCHAR ( 50 ) NOT NULL);"
Il comando dovrebbe non riuscire e restituire un errore simile al seguente:
ERROR: permission denied for schema public LINE 1: CREATE TABLE test (id serial PRIMARY KEY, randomdata VARCHAR...
Il comando non riesce perché gli utenti senza privilegi assegnati per impostazione predefinita possono accedere solo a Postgres ed elencare i database.
Crea una tabella con le credenziali
mydatabaseowner
e concedi tutti i privilegi sulla tabella amyuser
:PGPASSWORD=$OWNERPASSWORD psql \ -h my-cluster \ -U $OWNERUSERNAME \ -d mydatabase \ -c "CREATE TABLE test (id serial PRIMARY KEY, randomdata VARCHAR ( 50 ) NOT NULL);GRANT ALL ON test TO myuser;GRANT ALL ON SEQUENCE test_id_seq TO myuser;"
L'output è simile al seguente:
CREATE TABLE GRANT GRANT
Inserisci dati casuali nella tabella utilizzando le credenziali
myuser
:for i in {1..10}; do DATA=$(tr -dc A-Za-z0-9 </dev/urandom | head -c 13) PGPASSWORD=$CLIENTPASSWORD psql \ -h my-cluster \ -U $CLIENTUSERNAME \ -d mydatabase \ -c "INSERT INTO test(randomdata) VALUES ('$DATA');" done
L'output è simile al seguente:
INSERT 0 1 INSERT 0 1 INSERT 0 1 INSERT 0 1 INSERT 0 1 INSERT 0 1 INSERT 0 1 INSERT 0 1 INSERT 0 1 INSERT 0 1
Recupera i valori che hai inserito:
PGPASSWORD=$CLIENTPASSWORD psql \ -h my-cluster \ -U $CLIENTUSERNAME \ -d mydatabase \ -c "SELECT * FROM test;"
L'output è simile al seguente:
id | randomdata ----+--------------- 1 | jup9HYsAjwtW4 2 | 9rLAyBlcpLgNT 3 | wcXSqxb5Yz75g 4 | KoDRSrx3muD6T 5 | b9atC7RPai7En 6 | 20d7kC8E6Vt1V 7 | GmgNxaWbkevGq 8 | BkTwFWH6hWC7r 9 | nkLXHclkaqkqy 10 | HEebZ9Lp71Nm3 (10 rows)
Esci dalla shell del pod:
exit
- Un pod Postgres che raccoglie metriche sul percorso
/
e sulla porta9187
- Raccoglitori basati su Prometheus che elaborano le metriche del pod Postgres
- Una risorsa
PodMonitoring
che invia metriche a Cloud Monitoring Crea la risorsa
PodMonitoring
per estrarre le metriche in base alabelSelector
:kubectl apply -n postgres -f manifests/03-prometheus-metrics/pod-monitoring.yaml
Nella console Google Cloud , vai alla pagina Dashboard cluster GKE.
Vai alla dashboard dei cluster GKE
La dashboard mostra una velocità di importazione delle metriche diversa da zero.
Nella console Google Cloud , vai alla pagina Dashboard.
Apri la dashboard Panoramica di PostgreSQL Prometheus. La dashboard mostra il numero di righe recuperate. Potrebbero essere necessari diversi minuti prima che la dashboard venga sottoposta al provisioning automatico.
Connettiti al pod client:
kubectl exec -it postgres-client -n postgres -- /bin/bash
Inserisci dati casuali:
for i in {1..100}; do DATA=$(tr -dc A-Za-z0-9 </dev/urandom | head -c 13) PGPASSWORD=$CLIENTPASSWORD psql \ -h my-cluster \ -U $CLIENTUSERNAME \ -d mydatabase \ -c "INSERT INTO test(randomdata) VALUES ('$DATA');" done
Aggiorna la pagina. I grafici Righe e Blocchi si aggiornano per mostrare lo stato effettivo del database.
Esci dalla shell del pod:
exit
Imposta le variabili di ambiente.
export PROJECT_ID=${PROJECT_ID} export KUBERNETES_CLUSTER_PREFIX=postgres export REGION=us-central1
Esegui il comando
terraform destroy
: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}
Sostituisci
FOLDER
congke-autopilot
ogke-standard
.Quando richiesto, digita
yes
.Trova tutti i dischi scollegati:
export disk_list=$(gcloud compute disks list --filter="-users:* AND labels.name=${KUBERNETES_CLUSTER_PREFIX}-cluster" --format "value[separator=|](name,zone)")
Elimina i dischi:
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
Elimina il repository GitHub:
rm -r ~/kubernetes-engine-samples/
- Esplora architetture di riferimento, diagrammi e best practice su Google Cloud. Consulta il nostro Cloud Architecture Center.
Configura l'ambiente
Per configurare l'ambiente:
Crea l'infrastruttura del cluster
In questa sezione, esegui uno script Terraform per creare un cluster GKE regionale privato ad alta disponibilità.
Puoi installare l'operatore utilizzando un cluster standard o Autopilot.
Standard
Il seguente diagramma mostra un cluster GKE Standard regionale privato di cui è stato eseguito il deployment in tre zone diverse:
Esegui il deployment di questa infrastruttura:
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}
Quando richiesto, digita yes
. Il completamento di questo comando e la visualizzazione dello stato pronto del cluster potrebbero richiedere diversi minuti.
Terraform crea le seguenti risorse:
L'output è simile al seguente:
...
Apply complete! Resources: 14 added, 0 changed, 0 destroyed.
...
Autopilot
Il seguente diagramma mostra un cluster GKE Autopilot regionale privato:
Esegui il deployment dell'infrastruttura:
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}
Quando richiesto, digita yes
. Il completamento di questo comando e la visualizzazione dello stato pronto del cluster potrebbero richiedere diversi minuti.
Terraform crea le seguenti risorse:
L'output è simile al seguente:
...
Apply complete! Resources: 12 added, 0 changed, 0 destroyed.
...
Connettiti al cluster
Configura kubectl
per comunicare con il cluster:
gcloud container clusters get-credentials ${KUBERNETES_CLUSTER_PREFIX}-cluster --region ${REGION}
Esegui il deployment dell'operatore Zalando nel tuo cluster
Esegui il deployment dell'operatore Zalando nel tuo cluster Kubernetes utilizzando un grafico Helm.
Esegui il deployment di Postgres
La configurazione di base per l'istanza del cluster Postgres include i seguenti componenti:
Questa configurazione rappresenta la configurazione minima richiesta per creare un cluster Postgres pronto per la produzione.
Il seguente manifest descrive un cluster Postgres:
Questo manifest contiene i seguenti campi:
Per saperne di più, consulta la documentazione di riferimento del manifest del cluster nella documentazione di Postgres.
Crea un cluster Postgres di base
L'operatore crea le seguenti risorse:
Autenticarsi in Postgres
Puoi creare utenti Postgres e assegnare loro le autorizzazioni del database. Ad esempio, il seguente manifest descrive una risorsa personalizzata che assegna utenti e ruoli:
apiVersion: "acid.zalan.do/v1"
kind: postgresql
metadata:
name: my-cluster
spec:
...
users:
mydatabaseowner:
- superuser
- createdb
myuser: []
databases:
mydatabase: mydatabaseowner
In questo manifest:
Memorizzare le password
Ti consigliamo di utilizzare il scram-sha-256
metodo consigliato per archiviare le password. Ad esempio, il seguente manifest descrive una risorsa personalizzata
che specifica la crittografia scram-sha-256
utilizzando il
campo postgresql.parameters.password_encryption
:
apiVersion: "acid.zalan.do/v1"
kind: postgresql
metadata:
name: my-cluster
spec:
...
postgresql:
parameters:
password_encryption: scram-sha-256
Ruota le credenziali utente
Puoi
ruotare le credenziali utente
archiviate nei secret di Kubernetes con Zalando. Ad esempio, il seguente
manifest descrive una risorsa personalizzata che definisce la rotazione delle credenziali utente utilizzando
il campo usersWithSecretRotation
:
apiVersion: "acid.zalan.do/v1"
kind: postgresql
metadata:
name: my-cluster
spec:
...
usersWithSecretRotation:
- myuser
- myanotheruser
- ...
Esempio di autenticazione: connettiti a Postgres
Questa sezione mostra come eseguire il deployment di un client Postgres di esempio e connettersi al database utilizzando la password di un secret Kubernetes.
Scopri come Prometheus raccoglie le metriche per il tuo cluster Postgres
Il seguente diagramma mostra come funziona la raccolta delle metriche Prometheus:
Nel diagramma, un cluster GKE privato contiene:
Google Cloud Managed Service per Prometheus supporta la raccolta delle metriche nel formato Prometheus. Cloud Monitoring utilizza una dashboard integrata per le metriche di Postgres.
Zalando espone le metriche del cluster nel formato Prometheus utilizzando il componente postgres_exporter come contenitore sidecar.
Esegui la pulizia
Elimina il progetto
Delete a Google Cloud project:
gcloud projects delete PROJECT_ID