En la guía, se muestra cómo implementar clústeres de PostgreSQL en Google Kubernetes Engine (GKE) mediante el operador CloudNativePG.
PostgreSQL es una base de datos relacional de objetos de código abierto con varias décadas de desarrollo activo, lo que garantiza un rendimiento estable del cliente. Ofrece una variedad de funciones, incluidas la replicación, la recuperación de un momento determinado, las funciones de seguridad y la extensión. PostgreSQL es compatible con los principales sistemas operativos y cumple por completo con los estándares ACID (atomicidad, coherencia, aislamiento y durabilidad).
Esta guía está dirigida a administradores de plataformas, arquitectos de nube y profesionales de operaciones interesados en implementar clústeres de Postgres en GKE. Ejecutar Postgres en GKE en lugar de usar Cloud SQL puede brindar más flexibilidad y control de configuración a los administradores de bases de datos experimentados.
Ventajas
CloudNativePG es un operador de código abierto desarrollado por EDB con una licencia Apache 2. Brinda las siguientes funciones en la implementación de PostgreSQL:
- Una forma declarativa y nativa de Kubernetes de administrar, configurar los clústeres de PostgreSQL
- Administración de copias de seguridad mediante instantáneas de volumen o Cloud Storage
- La conexión de encriptado en tránsito TLS, la capacidad de usar tu propia autoridad certificadora e integrarse en el Administrador de certificados para la rotación y emisión de certificados TLS automatizada
- Actualizaciones progresivas para versiones secundarias de PostgreSQL
- Uso del servidor de la API de Kubernetes para mantener el estado del clúster de PostgreSQL y conmutaciones por error para lograr una alta disponibilidad sin necesidad de herramientas adicionales
- Una configuración integrada de exportador de Prometheus a través de métricas definidas por el usuario escritas en SQL
Objetivos
- Planificar y, además, implementar la infraestructura de GKE para Postgres
- Implementa y configura el operador de CloudNativePG Postgres con Helm
- Implementa un clúster de PostgreSQL
- Configura la autenticación y la observabilidad de PostgreSQL
Arquitectura de implementación
PostgreSQL tiene varias opciones de implementación desde un servidor de base de datos independiente hasta un clúster replicado con alta disponibilidad. Este instructivo se centra en la implementación del clúster con alta disponibilidad en GKE.
En esta implementación, las cargas de trabajo del clúster de PostgreSQL se distribuyen en varias zonas de disponibilidad dentro del clúster de GKE regional, lo que garantiza una alta disponibilidad y redundancia. Para obtener más información, consulta Clústeres regionales.
En el siguiente diagrama, se muestra un clúster de Postgres que se ejecuta en varios nodos y zonas en un clúster de GKE:
La configuración predeterminada incluye un servidor principal de PostgreSQL y dos servidores de copia de seguridad listos para actuar en caso de que el servidor principal falle, lo que garantiza una disponibilidad continua de la base de datos.
Los recursos del operador CloudNativePG usan un espacio de nombres independiente del clúster de GKE para obtener un mejor aislamiento de recursos y el enfoque de microservicios recomendado de una base de datos por clúster de PostgreSQL. La base de datos y su usuario correspondiente (usuario de la app) se definen en el recurso personalizado de Kubernetes que representa el clúster.
El almacenamiento es un componente fundamental cuando se analizan las bases de datos. El almacenamiento debe tener un rendimiento eficiente, garantizar la disponibilidad continua y la coherencia de los datos. Por estos motivos, recomendamos la clase de almacenamiento
premium-rwo
, que se basa en discos SSD. El operador CloudNativePG crea automáticamentePersistentVolumeClaims
según sea necesario cuando se configuran Pods para el Clúster de PostgreSQL.
Costos
En este documento, usarás los siguientes componentes facturables de Google Cloud:
Para generar una estimación de costos en función del uso previsto, usa la calculadora de precios.
Cuando finalices las tareas que se describen en este documento, puedes borrar los recursos que creaste para evitar que continúe la facturación. Para obtener más información, consulta Cómo realizar una limpieza.
Antes de comenzar
Cloud Shell tiene preinstalado el software que necesitas para este instructivo, incluido kubectl
, gcloud CLI, Helm y Terraform. Si no usas Cloud Shell, debes instalar 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.
-
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_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
Configura tu entorno
Para configurar tu entorno, sigue estos pasos:
Establece las variables de entorno:
export PROJECT_ID=PROJECT_ID export KUBERNETES_CLUSTER_PREFIX=postgres export REGION=us-central1
Reemplaza
PROJECT_ID
por el ID del proyecto de Google Cloud.Clona el repositorio de GitHub:
git clone https://github.com/GoogleCloudPlatform/kubernetes-engine-samples
Cambia al directorio de trabajo:
cd kubernetes-engine-samples/databases/postgresql-cloudnativepg
Crea la infraestructura del clúster
En esta sección, debes ejecutar una secuencia de comandos de Terraform para crear un clúster de GKE privado, regional y con alta disponibilidad.
Puedes instalar el operador mediante un clúster de Standard o Autopilot.
Estándar
En el siguiente diagrama, se muestra un clúster de GKE estándar regional privado implementado en tres zonas diferentes:
Para implementar esta infraestructura, ejecuta los siguientes comandos:
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}
Cuando se te solicite, escribe yes
. Es posible que este comando tarde varios minutos en completarse y que el clúster muestre un estado de preparación.
Terraform crea los siguientes recursos:
- Una red de VPC y una subred privada para los nodos de Kubernetes
- Un router para acceder a Internet a través de NAT
- Un clúster de GKE privado en la región
us-central1
- Un grupo de nodos con ajuste de escala automático habilitado (de uno a dos nodos por zona y un nodo por zona como mínimo)
El resultado es similar al siguiente:
...
Apply complete! Resources: 14 added, 0 changed, 0 destroyed.
...
Autopilot
En el siguiente diagrama, se muestra un clúster de GKE de Autopilot regional privado:
Para implementar la infraestructura, ejecuta los siguientes comandos:
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}
Cuando se te solicite, escribe yes
. Es posible que este comando tarde varios minutos en completarse y que el clúster muestre un estado de preparación.
Terraform crea los siguientes recursos:
- Una red de VPC y una subred privada para los nodos de Kubernetes
- Un router para acceder a Internet a través de NAT
- Un clúster de GKE privado en la región
us-central1
- Un
ServiceAccount
con permiso de registro y supervisión - Google Cloud Managed Service para Prometheus para la supervisión de clústeres
El resultado es similar al siguiente:
...
Apply complete! Resources: 12 added, 0 changed, 0 destroyed.
...
Conéctate al clúster
Configura kubectl
para comunicarse con el clúster:
gcloud container clusters get-credentials ${KUBERNETES_CLUSTER_PREFIX}-cluster --region ${REGION}
Implementa el operador CloudNativePG
Implementa CloudNativePG en tu clúster de Kubernetes con un gráfico de Helm:
Agrega el repositorio de gráficos de Helm para operadores de CloudNativePG:
helm repo add cnpg https://cloudnative-pg.github.io/charts
Implementa el operador de CloudNativePG con la herramienta de línea de comandos de Helm:
helm upgrade --install cnpg \ --namespace cnpg-system \ --create-namespace \ cnpg/cloudnative-pg
El resultado es similar al siguiente:
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 ...
Implementa Postgres
En el siguiente manifiesto, se describe un clúster de PostgreSQL, tal como se define en el recurso personalizado del operador CloudNativePG:
Este manifiesto tiene los siguientes campos:
spec.instances
: la cantidad de Pods del clústerspec.primaryUpdateStrategy
: la estrategia de actualización progresiva:Unsupervised
: actualiza de forma autónoma el nodo del clúster principal después de los nodos de réplicaSupervised
: se requiere un cambio manual para el nodo del clúster principal
spec.postgresql
: Anulaciones de parámetros del archivopostgres.conf
, como las reglas pg-hba, LDAP y los requisitos para que se cumplan las réplicas de sincronización.spec.storage
: la configuración relacionada con el almacenamiento, como la clase de almacenamiento, el tamaño del volumen y la configuración de registro de escritura por adelantado.spec.bootstrap
: parámetros de la base de datos inicial creada en el clúster, credenciales de usuario y opciones de restablecimiento de la base de datosspec.resources
: solicitudes y límites para Pods del clústerspec.affinity
: reglas de afinidad y antiafinidad de las cargas de trabajo del clúster
Crea un clúster básico de Postgres
Crea un espacio de nombres:
kubectl create ns pg-ns
Crea el clúster de PostgreSQL mediante el recurso personalizado:
kubectl apply -n pg-ns -f manifests/01-basic-cluster/postgreSQL_cluster.yaml
Este comando puede tardar varios minutos en completarse.
Verifica el estado del clúster:
kubectl get cluster -n pg-ns --watch
Espera a que el resultado muestre un estado de
Cluster in healthy state
antes de continuar con el siguiente paso.NAME AGE INSTANCES READY STATUS PRIMARY gke-pg-cluster 2m53s 3 3 Cluster in healthy state gke-pg-cluster-1
Inspecciona los recursos
Confirma que GKE creó los recursos para el clúster:
kubectl get cluster,pod,svc,pvc,pdb,secret,cm -n pg-ns
El resultado es similar al siguiente:
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
El operador crea los siguientes recursos:
- Un recurso de clúster personalizado que representa el clúster de PostgreSQL y que controla el operador
- Recursos PersistentVolumeClaim con Volúmenes persistentes correspondientes
- Secrets con credenciales de usuario para acceder a la base de datos y replicación entre los nodos de Postgres.
- Tres servicios de extremo de base de datos:
<name>-rw
,<name>-ro
y<name>-r
para conectarse al clúster. Para obtener más información, consulta Arquitectura de PostgreSQL.
Autentícate en Postgres
Puedes conectarte a la base de datos de PostgreSQL y verificar el acceso a través de diferentes extremos de servicio creados por el operador. Para hacerlo, usa un pod adicional con un cliente PostgreSQL y credenciales de usuario de la aplicación sincronizadas activadas como variables de entorno.
Ejecuta el Pod de cliente para interactuar con tu clúster de Postgres:
kubectl apply -n pg-ns -f manifests/02-auth/pg-client.yaml
Ejecuta un comando
exec
en el Podpg-client
y accede al Servicegke-pg-cluster-rw
:kubectl wait --for=condition=Ready -n pg-ns pod/pg-client --timeout=300s kubectl exec -n pg-ns -i -t pg-client -- /bin/sh
Accede a la base de datos con el servicio
gke-pg-cluster-rw
para establecer una conexión con privilegios de lectura y escritura:psql postgresql://$CLIENTUSERNAME:$CLIENTPASSWORD@gke-pg-cluster-rw.pg-ns/app
La terminal empieza con el nombre de tu base de datos:
app=>
Crear una tabla:
CREATE TABLE travel_agency_clients ( client VARCHAR ( 50 ) UNIQUE NOT NULL, address VARCHAR ( 50 ) UNIQUE NOT NULL, phone VARCHAR ( 50 ) UNIQUE NOT NULL);
Inserta datos en la tabla:
INSERT INTO travel_agency_clients(client, address, phone) VALUES ('Tom', 'Warsaw', '+55555') RETURNING *;
Visualiza los datos que creaste:
SELECT * FROM travel_agency_clients ;
El resultado es similar al siguiente:
client | address | phone --------+---------+--------- Tom | Warsaw | +55555 (1 row)
Sal de la sesión actual de la base de datos:
exit
Accede a la base de datos con el servicio
gke-pg-cluster-ro
para la verificación del acceso de solo lectura. Este servicio permite consultar datos, pero restringe las operaciones de escritura:psql postgresql://$CLIENTUSERNAME:$CLIENTPASSWORD@gke-pg-cluster-ro.pg-ns/app
Intenta insertar datos nuevos:
INSERT INTO travel_agency_clients(client, address, phone) VALUES ('John', 'Paris', '+55555') RETURNING *;
El resultado es similar al siguiente:
ERROR: cannot execute INSERT in a read-only transaction
Intenta leer datos:
SELECT * FROM travel_agency_clients ;
El resultado es similar al siguiente:
client | address | phone --------+---------+--------- Tom | Warsaw | +55555 (1 row)
Sal de la sesión actual de la base de datos:
exit
Sal de la shell del Pod:
exit
Comprende cómo Prometheus recopila métricas para tu clúster de Postgres
En el siguiente diagrama, se muestra cómo funciona la recopilación de métricas de Prometheus:
En el diagrama, un clúster privado de GKE contiene lo siguiente:
- Un Pod de Postgres que recopila métricas en la ruta de acceso
/
y el puerto9187
- Recopiladores basados en Prometheus que procesan las métricas del Pod de Postgres
- Un recurso
PodMonitoring
que envía métricas a Cloud Monitoring
Para habilitar la recopilación de métricas de tus Pods, sigue estos pasos:
Crea el recurso
PodMonitoring
:kubectl apply -f manifests/03-observability/pod-monitoring.yaml -n pg-ns
En la consola de Google Cloud, ve a la página Explorador de métricas:
Dirígete al Explorador de métricas
En el panel, se muestra una tasa de transferencia de métricas distinta de cero.
En Selecciona una métrica, ingresa Prometheus Target.
En la sección Categorías de métricas activas, selecciona Cnpg.
Crea un panel de métricas
Para visualizar las métricas exportadas, crea un panel de métricas.
Implementa un panel:
gcloud --project "${PROJECT_ID}" monitoring dashboards create --config-from-file manifests/03-observability/gcp-pg.json
En la consola de Google Cloud, ve a la página Paneles.
Selecciona el panel PostgreSQL Prometheus Overview.
Para revisar cómo los paneles supervisan las funciones, puedes reutilizar las acciones de la Autenticación de base de datos y aplicar solicitudes de lectura y escritura en la base de datos y, luego, revisa la visualización de las métricas recopiladas en un panel.
Conéctate al Pod cliente:
kubectl exec -n pg-ns -i -t pg-client -- /bin/sh
Inserta datos aleatorios:
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));"
Actualiza el panel. Los grafos se actualizan con métricas actualizadas.
Sal de la shell del Pod:
exit
Realiza una limpieza
Borra el proyecto
Delete a Google Cloud project:
gcloud projects delete PROJECT_ID
Borra los recursos individuales
Configurar variables de entorno
export PROJECT_ID=${PROJECT_ID} export KUBERNETES_CLUSTER_PREFIX=postgres export REGION=us-central1
Ejecuta el 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}
Reemplaza
FOLDER
porgke-autopilot
ogke-standard
.Cuando se te solicite, escribe
yes
.Busca todos los discos no conectados:
export disk_list=$(gcloud compute disks list --filter="-users:* AND labels.name=${KUBERNETES_CLUSTER_PREFIX}-cluster" --format "value[separator=|](name,zone)")
Borra los discos:
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
¿Qué sigue?
- Explora arquitecturas de referencia, diagramas y prácticas recomendadas sobre Google Cloud. Consulta nuestro Cloud Architecture Center.