Implementación de una base de datos PostgreSQL de alta disponibilidad en AKS
En este artículo, implementará una base de datos PostgreSQL de alta disponibilidad en AKS.
- Si aún no ha creado la infraestructura necesaria para esta implementación, siga los pasos descritos en Creación de una infraestructura para implementar una base de datos PostgreSQL de alta disponibilidad en AKS para configurarla y, a continuación, puede volver a este artículo.
Importante
El software de código abierto se menciona en toda la documentación y ejemplos de AKS. El software que implemente se excluye de los contratos de nivel de servicio de AKS, la garantía limitada y el soporte técnico de Azure. A medida que usa la tecnología de código abierto junto con AKS, consulte las opciones de soporte técnico disponibles en las comunidades y los mantenedores de proyectos respectivos para desarrollar un plan.
Por ejemplo, el Repositorio Ray de GitHub describe varias plataformas que varían en el tiempo de respuesta, el propósito y el nivel de soporte técnico.
Microsoft asume la responsabilidad de crear los paquetes de código abierto que implementamos en AKS. Esa responsabilidad incluye tener la propiedad completa del proceso de compilación, examen, firma, validación y revisión, junto con el control sobre los archivos binarios en imágenes de contenedor. Para obtener más información, consulte Administración de vulnerabilidades para AKS y Cobertura del soporte técnico de AKS.
Creación de un secreto para el usuario de la aplicación de arranque
Genere un secreto para validar la implementación de PostgreSQL mediante el inicio de sesión interactivo de un usuario de aplicación de arranque mediante el comando
kubectl create secret
.PG_DATABASE_APPUSER_SECRET=$(echo -n | openssl rand -base64 16) kubectl create secret generic db-user-pass \ --from-literal=username=app \ --from-literal=password="${PG_DATABASE_APPUSER_SECRET}" \ --namespace $PG_NAMESPACE \ --context $AKS_PRIMARY_CLUSTER_NAME
Compruebe que el secreto se creó correctamente mediante el comando
kubectl get
.kubectl get secret db-user-pass --namespace $PG_NAMESPACE --context $AKS_PRIMARY_CLUSTER_NAME
Establecimiento de variables de entorno para el clúster de PostgreSQL
Implemente un objeto ConfigMap para establecer variables de entorno para el clúster de PostgreSQL mediante el siguiente comando
kubectl apply
:cat <<EOF | kubectl apply --context $AKS_PRIMARY_CLUSTER_NAME -n $PG_NAMESPACE -f - apiVersion: v1 kind: ConfigMap metadata: name: cnpg-controller-manager-config data: ENABLE_AZURE_PVC_UPDATES: 'true' EOF
Instalación de PodMonitors de Prometheus
Prometheus crea PodMonitors para las instancias de CNPG mediante un conjunto de reglas de grabación predeterminadas almacenadas en el repositorio de ejemplos de CNPG de GitHub. En un entorno de producción, estas reglas se modificarían según sea necesario.
Agregue el repositorio de Helm de la comunidad de Prometheus mediante el comando
helm repo add
.helm repo add prometheus-community \ https://prometheus-community.github.io/helm-charts
Actualice el repositorio de Helm de la comunidad de Prometheus e instálelo en el clúster principal mediante el comando
helm upgrade
con la marca--install
.helm upgrade --install \ --namespace $PG_NAMESPACE \ -f https://raw.githubusercontent.com/cloudnative-pg/cloudnative-pg/main/docs/src/samples/monitoring/kube-stack-config.yaml \ prometheus-community \ prometheus-community/kube-prometheus-stack \ --kube-context=$AKS_PRIMARY_CLUSTER_NAME
Compruebe que se crea el monitor de pod.
kubectl --namespace $PG_NAMESPACE \
--context $AKS_PRIMARY_CLUSTER_NAME \
get podmonitors.monitoring.coreos.com \
$PG_PRIMARY_CLUSTER_NAME \
-o yaml
Creación de una credencial federada
En esta sección, creará una credencial de identidad federada para la copia de seguridad de PostgreSQL para permitir que CNPG use la identidad de carga de trabajo de AKS para autenticarse en el destino de la cuenta de almacenamiento para las copias de seguridad. El operador CNPG crea una cuenta de servicio de Kubernetes con el mismo nombre que el clúster denominado usado en el manifiesto de implementación del clúster CNPG.
Obtenga la dirección URL del emisor de OIDC del clúster mediante el comando
az aks show
.export AKS_PRIMARY_CLUSTER_OIDC_ISSUER="$(az aks show \ --name $AKS_PRIMARY_CLUSTER_NAME \ --resource-group $RESOURCE_GROUP_NAME \ --query "oidcIssuerProfile.issuerUrl" \ --output tsv)"
Cree una credencial de identidad federada mediante el comando
az identity federated-credential create
.az identity federated-credential create \ --name $AKS_PRIMARY_CLUSTER_FED_CREDENTIAL_NAME \ --identity-name $AKS_UAMI_CLUSTER_IDENTITY_NAME \ --resource-group $RESOURCE_GROUP_NAME \ --issuer "${AKS_PRIMARY_CLUSTER_OIDC_ISSUER}" \ --subject system:serviceaccount:"${PG_NAMESPACE}":"${PG_PRIMARY_CLUSTER_NAME}" \ --audience api://AzureADTokenExchange
Implementación de un clúster de PostgreSQL de alta disponibilidad
En esta sección, implementará un clúster de PostgreSQL de alta disponibilidad mediante la definición de recursos personalizados (CRD) del clúster CNPG.
En la tabla siguiente se describen las propiedades clave establecidas en el manifiesto de implementación de YAML para el CRD de clúster:
Propiedad | Definición |
---|---|
inheritedMetadata |
Específico del operador CNPG. Todos los objetos relacionados con el clúster heredan los metadatos. |
annotations: service.beta.kubernetes.io/azure-dns-label-name |
Etiqueta DNS para su uso al exponer los puntos de conexión de clúster de Postgres de solo lectura y escritura. |
labels: azure.workload.identity/use: "true" |
Indica que AKS debe insertar dependencias de identidad de carga de trabajo en los pods que hospedan las instancias del clúster de PostgreSQL. |
topologySpreadConstraints |
Requerir zonas diferentes y nodos diferentes con la etiqueta "workload=postgres" . |
resources |
Configura una clase de calidad de servicio (QoS) de Garantizado. En un entorno de producción, estos valores son clave para maximizar el uso de la máquina virtual del nodo subyacente y variar en función de la SKU de máquina virtual de Azure usada. |
bootstrap |
Específico del operador CNPG. Inicializa con una base de datos de aplicación vacía. |
storage / walStorage |
Específico del operador CNPG. Define plantillas de almacenamiento para PersistentVolumeClaims (PVC) para el almacenamiento de datos y registros. También es posible especificar el almacenamiento para que los espacios de tablas se particionen para aumentar las E/S por segundo. |
replicationSlots |
Específico del operador CNPG. Habilita ranuras de replicación para alta disponibilidad. |
postgresql |
Específico del operador CNPG. Asigna la configuración de postgresql.conf , pg_hba.conf y pg_ident.conf config . |
serviceAccountTemplate |
Contiene la plantilla necesaria para generar las cuentas de servicio y asignar la credencial de identidad federada de AKS a la UAMI para habilitar la autenticación de identidad de carga de trabajo de AKS desde los pods que hospedan las instancias de PostgreSQL a recursos externos de Azure. |
barmanObjectStore |
Específico del operador CNPG. Configura el conjunto de herramientas barman-cloud mediante la identidad de carga de trabajo de AKS para la autenticación en el almacén de objetos de Azure Blob Storage. |
Implemente el clúster de PostgreSQL con el CRD de clúster mediante el comando
kubectl apply
.cat <<EOF | kubectl apply --context $AKS_PRIMARY_CLUSTER_NAME -n $PG_NAMESPACE -v 9 -f - apiVersion: postgresql.cnpg.io/v1 kind: Cluster metadata: name: $PG_PRIMARY_CLUSTER_NAME spec: inheritedMetadata: annotations: service.beta.kubernetes.io/azure-dns-label-name: $AKS_PRIMARY_CLUSTER_PG_DNSPREFIX labels: azure.workload.identity/use: "true" instances: 3 startDelay: 30 stopDelay: 30 minSyncReplicas: 1 maxSyncReplicas: 1 replicationSlots: highAvailability: enabled: true updateInterval: 30 topologySpreadConstraints: - maxSkew: 1 topologyKey: topology.kubernetes.io/zone whenUnsatisfiable: DoNotSchedule labelSelector: matchLabels: cnpg.io/cluster: $PG_PRIMARY_CLUSTER_NAME affinity: nodeSelector: workload: postgres resources: requests: memory: '8Gi' cpu: 2 limits: memory: '8Gi' cpu: 2 bootstrap: initdb: database: appdb owner: app secret: name: db-user-pass dataChecksums: true storage: size: 2Gi pvcTemplate: accessModes: - ReadWriteOnce resources: requests: storage: 2Gi storageClassName: managed-csi-premium walStorage: size: 2Gi pvcTemplate: accessModes: - ReadWriteOnce resources: requests: storage: 2Gi storageClassName: managed-csi-premium monitoring: enablePodMonitor: true postgresql: parameters: archive_timeout: '5min' auto_explain.log_min_duration: '10s' checkpoint_completion_target: '0.9' checkpoint_timeout: '15min' shared_buffers: '256MB' effective_cache_size: '512MB' pg_stat_statements.max: '1000' pg_stat_statements.track: 'all' max_connections: '400' max_prepared_transactions: '400' max_parallel_workers: '32' max_parallel_maintenance_workers: '8' max_parallel_workers_per_gather: '8' max_replication_slots: '32' max_worker_processes: '32' wal_keep_size: '512MB' max_wal_size: '1GB' pg_hba: - host all all all scram-sha-256 serviceAccountTemplate: metadata: annotations: azure.workload.identity/client-id: "$AKS_UAMI_WORKLOAD_CLIENTID" labels: azure.workload.identity/use: "true" backup: barmanObjectStore: destinationPath: "https://${PG_PRIMARY_STORAGE_ACCOUNT_NAME}.blob.core.windows.net/backups" azureCredentials: inheritFromAzureAD: true retentionPolicy: '7d' EOF
Compruebe que el clúster de PostgreSQL principal se creó correctamente mediante el comando
kubectl get
. La CRD del clúster CNPG especificó tres instancias, que se pueden validar mediante la visualización de pods en ejecución una vez que cada instancia se abre y se une para la replicación. Tenga paciencia, ya que puede tardar algún tiempo en conectarse a las tres instancias y unirse al clúster.kubectl get pods --context $AKS_PRIMARY_CLUSTER_NAME --namespace $PG_NAMESPACE -l cnpg.io/cluster=$PG_PRIMARY_CLUSTER_NAME
Salida de ejemplo
NAME READY STATUS RESTARTS AGE pg-primary-cnpg-r8c7unrw-1 1/1 Running 0 4m25s pg-primary-cnpg-r8c7unrw-2 1/1 Running 0 3m33s pg-primary-cnpg-r8c7unrw-3 1/1 Running 0 2m49s
Validar que Prometheus PodMonitor se está ejecutando
El operador CNPG crea automáticamente un PodMonitor para la instancia principal mediante las reglas de grabación creadas durante la instalación de Prometheus Community.
Valide que PodMonitor se está ejecutando con el comando
kubectl get
.kubectl --namespace $PG_NAMESPACE \ --context $AKS_PRIMARY_CLUSTER_NAME \ get podmonitors.monitoring.coreos.com \ $PG_PRIMARY_CLUSTER_NAME \ --output yaml
Salida de ejemplo
kind: PodMonitor metadata: annotations: cnpg.io/operatorVersion: 1.23.1 ...
Si usa Azure Monitor para Prometheus administrado, deberá agregar otro monitor de pod mediante el nombre del grupo personalizado. Prometheus administrado no recoge las definiciones de recursos personalizados (CRD) de la comunidad de Prometheus. Aparte del nombre del grupo, los CRD son los mismos. Esto permite que los monitores de pod para Prometheus administrado existan en paralelo con aquellos que usan el monitor de pods de la comunidad. Si no usa Prometheus administrado, puede omitirlo. Cree un nuevo monitor de pod:
cat <<EOF | kubectl apply --context $AKS_PRIMARY_CLUSTER_NAME --namespace $PG_NAMESPACE -f -
apiVersion: azmonitoring.coreos.com/v1
kind: PodMonitor
metadata:
name: cnpg-cluster-metrics-managed-prometheus
namespace: ${PG_NAMESPACE}
labels:
azure.workload.identity/use: "true"
cnpg.io/cluster: ${PG_PRIMARY_CLUSTER_NAME}
spec:
selector:
matchLabels:
azure.workload.identity/use: "true"
cnpg.io/cluster: ${PG_PRIMARY_CLUSTER_NAME}
podMetricsEndpoints:
- port: metrics
EOF
Compruebe que se crea el monitor de pods (tenga en cuenta la diferencia en el nombre del grupo).
kubectl --namespace $PG_NAMESPACE \
--context $AKS_PRIMARY_CLUSTER_NAME \
get podmonitors.azmonitoring.coreos.com \
-l cnpg.io/cluster=$PG_PRIMARY_CLUSTER_NAME \
-o yaml
Opción A: área de trabajo de Azure Monitor
Una vez implementado el clúster de Postgres y el monitor de pods, puede ver las métricas mediante Azure Portal en un área de trabajo de Azure Monitor.
Opción B: Grafana administrada
Como alternativa, una vez implementados los monitores de pod y clúster de Postgres, puede crear un panel de métricas en la instancia de Grafana administrada creada por el script de implementación para visualizar las métricas exportadas al área de trabajo de Azure Monitor. Puede acceder a Grafana administrada a través de Azure Portal. Vaya a la instancia de Grafana administrada creada por el script de implementación y haga clic en el vínculo Punto de conexión, como se muestra aquí:
Al hacer clic en el vínculo Punto de conexión, se abrirá una nueva ventana del explorador donde puede crear paneles en la instancia de Grafana administrada. Siguiendo las instrucciones para configurar un origen de datos de Azure Monitor, puede agregar visualizaciones para crear un panel de métricas desde el clúster de Postgres. Después de configurar la conexión de origen de datos, en el menú principal, haga clic en la opción Orígenes de datos y debería ver un conjunto de opciones de origen de datos para la conexión del origen de datos, como se muestra aquí:
En la opción Prometheus administrado, haga clic en la opción para crear un panel para abrir el editor del panel. Una vez que se abra la ventana del editor, haga clic en la opción Agregar visualización y, a continuación, haga clic en la opción Prometheus administrado para examinar las métricas desde el clúster de Postgres. Una vez que haya seleccionado la métrica que desea visualizar, haga clic en el botón Ejecutar consultas para capturar los datos de la visualización, como se muestra aquí:
Haga clic en el botón Guardar para agregar el panel al panel. Puede agregar otros paneles haciendo clic en el botón Agregar en el editor del panel y repitiendo este proceso para visualizar otras métricas. Al agregar las visualizaciones de métricas, debe tener algo similar al siguiente:
Haga clic en el icono Guardar para guardar el panel.
Inspección del clúster de PostgreSQL implementado
Compruebe que PostgreSQL se distribuye entre varias zonas de disponibilidad mediante la recuperación de los detalles del nodo de AKS mediante el comando kubectl get
.
kubectl get nodes \
--context $AKS_PRIMARY_CLUSTER_NAME \
--namespace $PG_NAMESPACE \
--output json | jq '.items[] | {node: .metadata.name, zone: .metadata.labels."failure-domain.beta.kubernetes.io/zone"}'
La salida debe ser similar a la siguiente salida de ejemplo con la zona de disponibilidad que se muestra para cada nodo:
{
"node": "aks-postgres-15810965-vmss000000",
"zone": "westus3-1"
}
{
"node": "aks-postgres-15810965-vmss000001",
"zone": "westus3-2"
}
{
"node": "aks-postgres-15810965-vmss000002",
"zone": "westus3-3"
}
{
"node": "aks-systempool-26112968-vmss000000",
"zone": "westus3-1"
}
{
"node": "aks-systempool-26112968-vmss000001",
"zone": "westus3-2"
}
Conexión a PostgreSQL y creación de un conjunto de datos de ejemplo
En esta sección, creará una tabla e insertará algunos datos en la base de datos de la aplicación que se creó en el CRD del clúster CNPG que implementó anteriormente. Use estos datos para validar las operaciones de copia de seguridad y restauración del clúster de PostgreSQL.
Cree una tabla e inserte datos en la base de datos de la aplicación mediante los siguientes comandos:
kubectl cnpg psql $PG_PRIMARY_CLUSTER_NAME --namespace $PG_NAMESPACE
# Run the following PSQL commands to create a small dataset # postgres=# CREATE TABLE datasample (id INTEGER,name VARCHAR(255)); INSERT INTO datasample (id, name) VALUES (1, 'John'); INSERT INTO datasample (id, name) VALUES (2, 'Jane'); INSERT INTO datasample (id, name) VALUES (3, 'Alice'); SELECT COUNT(*) FROM datasample; # Type \q to exit psql
La salida debería ser similar a la salida de ejemplo siguiente:
CREATE TABLE INSERT 0 1 INSERT 0 1 INSERT 0 1 count ------- 3 (1 row)
Conexión a réplicas de solo lectura de PostgreSQL
Conéctese a las réplicas de solo lectura de PostgreSQL y valide el conjunto de datos de ejemplo mediante los siguientes comandos:
kubectl cnpg psql --replica $PG_PRIMARY_CLUSTER_NAME --namespace $PG_NAMESPACE
#postgres=# SELECT pg_is_in_recovery();
Salida de ejemplo
# pg_is_in_recovery #------------------- # t #(1 row)
#postgres=# SELECT COUNT(*) FROM datasample;
Salida de ejemplo
# count #------- # 3 #(1 row) # Type \q to exit psql
Configuración de copias de seguridad de PostgreSQL a petición y programadas mediante Barman
Compruebe que el clúster de PostgreSQL puede acceder a la cuenta de almacenamiento de Azure especificada en el CRD del clúster CNPG y que
Working WAL archiving
notifica comoOK
mediante el comando siguiente:kubectl cnpg status $PG_PRIMARY_CLUSTER_NAME 1 \ --context $AKS_PRIMARY_CLUSTER_NAME \ --namespace $PG_NAMESPACE
Salida de ejemplo
Continuous Backup status First Point of Recoverability: Not Available Working WAL archiving: OK WALs waiting to be archived: 0 Last Archived WAL: 00000001000000000000000A @ 2024-07-09T17:18:13.982859Z Last Failed WAL: -
Implemente una copia de seguridad a petición en Azure Storage, que usa la integración de identidades de carga de trabajo de AKS mediante el archivo YAML con el comando
kubectl apply
.export BACKUP_ONDEMAND_NAME="on-demand-backup-1" cat <<EOF | kubectl apply --context $AKS_PRIMARY_CLUSTER_NAME --namespace $PG_NAMESPACE -v 9 -f - apiVersion: postgresql.cnpg.io/v1 kind: Backup metadata: name: $BACKUP_ONDEMAND_NAME spec: method: barmanObjectStore cluster: name: $PG_PRIMARY_CLUSTER_NAME EOF
Valide el estado de la copia de seguridad a petición mediante el comando
kubectl describe
.kubectl describe backup $BACKUP_ONDEMAND_NAME \ --context $AKS_PRIMARY_CLUSTER_NAME \ --namespace $PG_NAMESPACE
Salida de ejemplo
Type Reason Age From Message ---- ------ ---- ---- ------- Normal Starting 6s cloudnative-pg-backup Starting backup for cluster pg-primary-cnpg-r8c7unrw Normal Starting 5s instance-manager Backup started Normal Completed 1s instance-manager Backup completed
Compruebe que el clúster tiene un primer punto de capacidad de recuperación mediante el siguiente comando:
kubectl cnpg status $PG_PRIMARY_CLUSTER_NAME 1 \ --context $AKS_PRIMARY_CLUSTER_NAME \ --namespace $PG_NAMESPACE
Salida de ejemplo
Continuous Backup status First Point of Recoverability: 2024-06-05T13:47:18Z Working WAL archiving: OK
Configure una copia de seguridad programada para cada hora a 15 minutos después de la hora mediante el archivo YAML con el comando
kubectl apply
.export BACKUP_SCHEDULED_NAME="scheduled-backup-1" cat <<EOF | kubectl apply --context $AKS_PRIMARY_CLUSTER_NAME --namespace $PG_NAMESPACE -v 9 -f - apiVersion: postgresql.cnpg.io/v1 kind: ScheduledBackup metadata: name: $BACKUP_SCHEDULED_NAME spec: # Backup once per hour schedule: "0 15 * ? * *" backupOwnerReference: self cluster: name: $PG_PRIMARY_CLUSTER_NAME EOF
Valide el estado de la copia de seguridad programada mediante el comando
kubectl describe
.kubectl describe scheduledbackup $BACKUP_SCHEDULED_NAME \ --context $AKS_PRIMARY_CLUSTER_NAME \ --namespace $PG_NAMESPACE
Vea los archivos de copia de seguridad almacenados en Azure Blob Storage para el clúster principal mediante el comando
az storage blob list
.az storage blob list \ --account-name $PG_PRIMARY_STORAGE_ACCOUNT_NAME \ --container-name backups \ --query "[*].name" \ --only-show-errors
La salida debe ser similar a la siguiente salida de ejemplo, lo que valida que la copia de seguridad se realizó correctamente:
[ "pg-primary-cnpg-r8c7unrw/base/20240605T134715/backup.info", "pg-primary-cnpg-r8c7unrw/base/20240605T134715/data.tar", "pg-primary-cnpg-r8c7unrw/wals/0000000100000000/000000010000000000000001", "pg-primary-cnpg-r8c7unrw/wals/0000000100000000/000000010000000000000002", "pg-primary-cnpg-r8c7unrw/wals/0000000100000000/000000010000000000000003", "pg-primary-cnpg-r8c7unrw/wals/0000000100000000/000000010000000000000003.00000028.backup", "pg-primary-cnpg-r8c7unrw/wals/0000000100000000/000000010000000000000004", "pg-primary-cnpg-r8c7unrw/wals/0000000100000000/000000010000000000000005", "pg-primary-cnpg-r8c7unrw/wals/0000000100000000/000000010000000000000005.00000028.backup", "pg-primary-cnpg-r8c7unrw/wals/0000000100000000/000000010000000000000006", "pg-primary-cnpg-r8c7unrw/wals/0000000100000000/000000010000000000000007", "pg-primary-cnpg-r8c7unrw/wals/0000000100000000/000000010000000000000008", "pg-primary-cnpg-r8c7unrw/wals/0000000100000000/000000010000000000000009" ]
Restauración de la copia de seguridad a petición en un nuevo clúster de PostgreSQL
En esta sección, restaurará la copia de seguridad a petición que creó anteriormente mediante el operador CNPG en una nueva instancia mediante el CRD de clúster de arranque. Se usa un único clúster de instancia para simplificar. Recuerde que la identidad de carga de trabajo de AKS (a través de inheritFromAzureAD de CNPG) tiene acceso a los archivos de copia de seguridad y que el nombre del clúster de recuperación se usa para generar una nueva cuenta de servicio de Kubernetes específica del clúster de recuperación.
También se crea una segunda credencial federada para asignar la nueva cuenta de servicio de clúster de recuperación a la UAMI existente que tiene acceso de "Colaborador de datos de blobs de almacenamiento" a los archivos de copia de seguridad en Blob Storage.
Cree una segunda credencial de identidad federada mediante el comando
az identity federated-credential create
.export PG_PRIMARY_CLUSTER_NAME_RECOVERED="$PG_PRIMARY_CLUSTER_NAME-recovered-db" az identity federated-credential create \ --name $PG_PRIMARY_CLUSTER_NAME_RECOVERED \ --identity-name $AKS_UAMI_CLUSTER_IDENTITY_NAME \ --resource-group $RESOURCE_GROUP_NAME \ --issuer "${AKS_PRIMARY_CLUSTER_OIDC_ISSUER}" \ --subject system:serviceaccount:"${PG_NAMESPACE}":"${PG_PRIMARY_CLUSTER_NAME_RECOVERED}" \ --audience api://AzureADTokenExchange
Restaure la copia de seguridad a petición mediante el CRD de clúster con el comando
kubectl apply
.cat <<EOF | kubectl apply --context $AKS_PRIMARY_CLUSTER_NAME --namespace $PG_NAMESPACE -v 9 -f - apiVersion: postgresql.cnpg.io/v1 kind: Cluster metadata: name: $PG_PRIMARY_CLUSTER_NAME_RECOVERED spec: inheritedMetadata: annotations: service.beta.kubernetes.io/azure-dns-label-name: $AKS_PRIMARY_CLUSTER_PG_DNSPREFIX labels: azure.workload.identity/use: "true" instances: 1 affinity: nodeSelector: workload: postgres # Point to cluster backup created earlier and stored on Azure Blob Storage bootstrap: recovery: source: clusterBackup storage: size: 2Gi pvcTemplate: accessModes: - ReadWriteOnce resources: requests: storage: 2Gi storageClassName: managed-csi-premium volumeMode: Filesystem walStorage: size: 2Gi pvcTemplate: accessModes: - ReadWriteOnce resources: requests: storage: 2Gi storageClassName: managed-csi-premium volumeMode: Filesystem serviceAccountTemplate: metadata: annotations: azure.workload.identity/client-id: "$AKS_UAMI_WORKLOAD_CLIENTID" labels: azure.workload.identity/use: "true" externalClusters: - name: clusterBackup barmanObjectStore: destinationPath: https://${PG_PRIMARY_STORAGE_ACCOUNT_NAME}.blob.core.windows.net/backups serverName: $PG_PRIMARY_CLUSTER_NAME azureCredentials: inheritFromAzureAD: true wal: maxParallel: 8 EOF
Conéctese a la instancia recuperada y, a continuación, compruebe que el conjunto de datos creado en el clúster original donde se realizó la copia de seguridad completa está presente mediante el siguiente comando:
kubectl cnpg psql $PG_PRIMARY_CLUSTER_NAME_RECOVERED --namespace $PG_NAMESPACE
postgres=# SELECT COUNT(*) FROM datasample;
Salida de ejemplo
# count #------- # 3 #(1 row) # Type \q to exit psql
Elimine el clúster recuperado mediante el comando siguiente:
kubectl cnpg destroy $PG_PRIMARY_CLUSTER_NAME_RECOVERED 1 \ --context $AKS_PRIMARY_CLUSTER_NAME \ --namespace $PG_NAMESPACE
Elimine la credencial de identidad federada mediante el comando
az identity federated-credential delete
.az identity federated-credential delete \ --name $PG_PRIMARY_CLUSTER_NAME_RECOVERED \ --identity-name $AKS_UAMI_CLUSTER_IDENTITY_NAME \ --resource-group $RESOURCE_GROUP_NAME \ --yes
Exposición del clúster de PostgreSQL mediante un equilibrador de carga público
En esta sección, configurará la infraestructura necesaria para exponer públicamente los puntos de conexión de lectura y escritura de PostgreSQL y de solo lectura con restricciones de origen de IP a la dirección IP pública de la estación de trabajo cliente.
También se recuperan los siguientes puntos de conexión del servicio IP del clúster:
- Un punto de conexión de lectura y escritura principal que termina con
*-rw
. - Cero a N (dependiendo del número de réplicas) puntos de conexión de solo lectura que terminan con
*-ro
. - Un punto de conexión de replicación que termina con
*-r
.
Obtenga los detalles del servicio IP del clúster mediante el comando
kubectl get
.kubectl get services \ --context $AKS_PRIMARY_CLUSTER_NAME \ --namespace $PG_NAMESPACE \ -l cnpg.io/cluster=$PG_PRIMARY_CLUSTER_NAME
Salida del ejemplo
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE pg-primary-cnpg-sryti1qf-r ClusterIP 10.0.193.27 <none> 5432/TCP 3h57m pg-primary-cnpg-sryti1qf-ro ClusterIP 10.0.237.19 <none> 5432/TCP 3h57m pg-primary-cnpg-sryti1qf-rw ClusterIP 10.0.244.125 <none> 5432/TCP 3h57m
Nota:
Hay tres servicios:
namespace/cluster-name-ro
asignados al puerto 5433,namespace/cluster-name-rw
ynamespace/cluster-name-r
asignados al puerto 5433. Es importante evitar el uso del mismo puerto que el nodo de lectura y escritura del clúster de base de datos PostgreSQL. Si desea que las aplicaciones accedan solo a la réplica de solo lectura del clúster de base de datos de PostgreSQL, apúntelas al puerto 5433. El servicio final se usa normalmente para las copias de seguridad de datos, pero también puede funcionar como un nodo de solo lectura.Obtenga los detalles del servicio mediante el comando
kubectl get
.export PG_PRIMARY_CLUSTER_RW_SERVICE=$(kubectl get services \ --namespace $PG_NAMESPACE \ --context $AKS_PRIMARY_CLUSTER_NAME \ -l "cnpg.io/cluster" \ --output json | jq -r '.items[] | select(.metadata.name | endswith("-rw")) | .metadata.name') echo $PG_PRIMARY_CLUSTER_RW_SERVICE export PG_PRIMARY_CLUSTER_RO_SERVICE=$(kubectl get services \ --namespace $PG_NAMESPACE \ --context $AKS_PRIMARY_CLUSTER_NAME \ -l "cnpg.io/cluster" \ --output json | jq -r '.items[] | select(.metadata.name | endswith("-ro")) | .metadata.name') echo $PG_PRIMARY_CLUSTER_RO_SERVICE
Configure el servicio de equilibrador de carga con los siguientes archivos YAML mediante el comando
kubectl apply
.cat <<EOF | kubectl apply --context $AKS_PRIMARY_CLUSTER_NAME -f - apiVersion: v1 kind: Service metadata: annotations: service.beta.kubernetes.io/azure-load-balancer-resource-group: $AKS_PRIMARY_CLUSTER_NODERG_NAME service.beta.kubernetes.io/azure-pip-name: $AKS_PRIMARY_CLUSTER_PUBLICIP_NAME service.beta.kubernetes.io/azure-dns-label-name: $AKS_PRIMARY_CLUSTER_PG_DNSPREFIX name: cnpg-cluster-load-balancer-rw namespace: "${PG_NAMESPACE}" spec: type: LoadBalancer ports: - protocol: TCP port: 5432 targetPort: 5432 selector: cnpg.io/instanceRole: primary cnpg.io/podRole: instance loadBalancerSourceRanges: - "$MY_PUBLIC_CLIENT_IP/32" EOF cat <<EOF | kubectl apply --context $AKS_PRIMARY_CLUSTER_NAME -f - apiVersion: v1 kind: Service metadata: annotations: service.beta.kubernetes.io/azure-load-balancer-resource-group: $AKS_PRIMARY_CLUSTER_NODERG_NAME service.beta.kubernetes.io/azure-pip-name: $AKS_PRIMARY_CLUSTER_PUBLICIP_NAME service.beta.kubernetes.io/azure-dns-label-name: $AKS_PRIMARY_CLUSTER_PG_DNSPREFIX name: cnpg-cluster-load-balancer-ro namespace: "${PG_NAMESPACE}" spec: type: LoadBalancer ports: - protocol: TCP port: 5433 targetPort: 5432 selector: cnpg.io/instanceRole: replica cnpg.io/podRole: instance loadBalancerSourceRanges: - "$MY_PUBLIC_CLIENT_IP/32" EOF
Obtenga los detalles del servicio mediante el comando
kubectl describe
.kubectl describe service cnpg-cluster-load-balancer-rw \ --context $AKS_PRIMARY_CLUSTER_NAME \ --namespace $PG_NAMESPACE kubectl describe service cnpg-cluster-load-balancer-ro \ --context $AKS_PRIMARY_CLUSTER_NAME \ --namespace $PG_NAMESPACE export AKS_PRIMARY_CLUSTER_ALB_DNSNAME="$(az network public-ip show \ --resource-group $AKS_PRIMARY_CLUSTER_NODERG_NAME \ --name $AKS_PRIMARY_CLUSTER_PUBLICIP_NAME \ --query "dnsSettings.fqdn" --output tsv)" echo $AKS_PRIMARY_CLUSTER_ALB_DNSNAME
Validación de puntos de conexión públicos de PostgreSQL
En esta sección, validará que Azure Load Balancer está configurado correctamente mediante la dirección IP estática que creó anteriormente y enrutar conexiones a las réplicas principales de lectura y escritura y de solo lectura y usar la CLI de psql para conectarse a ambas.
Recuerde que el punto de conexión principal de lectura y escritura se asigna al puerto TCP 5432 y los puntos de conexión de réplica de solo lectura se asignan al puerto 5433 para permitir que se use el mismo nombre DNS de PostgreSQL para lectores y escritores.
Nota:
Necesita el valor de la contraseña de usuario de la aplicación para la autenticación básica de PostgreSQL que se generó anteriormente y se almacenó en la variable de entorno $PG_DATABASE_APPUSER_SECRET
.
Valide los puntos de conexión públicos de PostgreSQL mediante los siguientes comandos
psql
:echo "Public endpoint for PostgreSQL cluster: $AKS_PRIMARY_CLUSTER_ALB_DNSNAME" # Query the primary, pg_is_in_recovery = false psql -h $AKS_PRIMARY_CLUSTER_ALB_DNSNAME \ -p 5432 -U app -d appdb -W -c "SELECT pg_is_in_recovery();"
Salida de ejemplo
pg_is_in_recovery ------------------- f (1 row)
echo "Query a replica, pg_is_in_recovery = true" psql -h $AKS_PRIMARY_CLUSTER_ALB_DNSNAME \ -p 5433 -U app -d appdb -W -c "SELECT pg_is_in_recovery();"
Salida de ejemplo
# Example output pg_is_in_recovery ------------------- t (1 row)
Cuando se conecta correctamente al punto de conexión de lectura y escritura principal, la función PostgreSQL devuelve
f
para false, lo que indica que la conexión actual se puede escribir.Cuando se conecta a una réplica, la función devuelve
t
para true, lo que indica que la base de datos está en recuperación y de solo lectura.
Simular una conmutación por error no planeada
En esta sección, desencadenará un error repentino eliminando el pod que ejecuta la principal, lo que simula un bloqueo repentino o una pérdida de conectividad de red al nodo que hospeda la base de datos principal de PostgreSQL.
Compruebe el estado de las instancias de pod en ejecución mediante el comando siguiente:
kubectl cnpg status $PG_PRIMARY_CLUSTER_NAME --namespace $PG_NAMESPACE
Salida de ejemplo
Name Current LSN Rep role Status Node --------------------------- ----------- -------- ------- ----------- pg-primary-cnpg-sryti1qf-1 0/9000060 Primary OK aks-postgres-32388626-vmss000000 pg-primary-cnpg-sryti1qf-2 0/9000060 Standby (sync) OK aks-postgres-32388626-vmss000001 pg-primary-cnpg-sryti1qf-3 0/9000060 Standby (sync) OK aks-postgres-32388626-vmss000002
Elimine el pod principal mediante el comando
kubectl delete
.PRIMARY_POD=$(kubectl get pod \ --namespace $PG_NAMESPACE \ --no-headers \ -o custom-columns=":metadata.name" \ -l role=primary) kubectl delete pod $PRIMARY_POD --grace-period=1 --namespace $PG_NAMESPACE
Compruebe que la instancia de pod
pg-primary-cnpg-sryti1qf-2
es ahora la principal mediante el siguiente comando:kubectl cnpg status $PG_PRIMARY_CLUSTER_NAME --namespace $PG_NAMESPACE
Salida de ejemplo
pg-primary-cnpg-sryti1qf-2 0/9000060 Primary OK aks-postgres-32388626-vmss000001 pg-primary-cnpg-sryti1qf-1 0/9000060 Standby (sync) OK aks-postgres-32388626-vmss000000 pg-primary-cnpg-sryti1qf-3 0/9000060 Standby (sync) OK aks-postgres-32388626-vmss000002
Restablezca la instancia de pod
pg-primary-cnpg-sryti1qf-1
como principal mediante el comando siguiente:kubectl cnpg promote $PG_PRIMARY_CLUSTER_NAME 1 --namespace $PG_NAMESPACE
Compruebe que las instancias de pod se han devuelto a su estado original antes de la prueba de conmutación por error no planeada mediante el siguiente comando:
kubectl cnpg status $PG_PRIMARY_CLUSTER_NAME --namespace $PG_NAMESPACE
Salida de ejemplo
Name Current LSN Rep role Status Node --------------------------- ----------- -------- ------- ----------- pg-primary-cnpg-sryti1qf-1 0/9000060 Primary OK aks-postgres-32388626-vmss000000 pg-primary-cnpg-sryti1qf-2 0/9000060 Standby (sync) OK aks-postgres-32388626-vmss000001 pg-primary-cnpg-sryti1qf-3 0/9000060 Standby (sync) OK aks-postgres-32388626-vmss000002
Limpieza de recursos
Una vez que haya terminado de revisar la implementación, elimine todos los recursos que creó en esta guía mediante el comando
az group delete
.az group delete --resource-group $RESOURCE_GROUP_NAME --no-wait --yes
Pasos siguientes
En esta guía paso a paso, ha aprendido lo siguiente:
- Use la CLI de Azure para crear un clúster de AKS de varias zonas.
- Implemente un clúster y una base de datos de PostgreSQL de alta disponibilidad mediante el operador CNPG.
- Configure la supervisión de PostgreSQL mediante Prometheus y Grafana.
- Implemente un conjunto de datos de ejemplo en la base de datos PostgreSQL.
- Realice actualizaciones de clúster de PostgreSQL y AKS.
- Simulación de una interrupción del clúster y conmutación por error de réplica de PostgreSQL.
- Realice una copia de seguridad y restauración de la base de datos PostgreSQL.
Para más información sobre cómo puede aprovechar AKS para las cargas de trabajo, consulte ¿Qué es Azure Kubernetes Service (AKS)?
Colaboradores
Microsoft se encarga del mantenimiento de este artículo. Los siguientes colaboradores lo escribieron originalmente:
- Ken Kilty | TPM de entidad de seguridad
- Russell de Pina | TPM de entidad de seguridad
- Adrian Joian | Ingeniero de clientes sénior
- Jenny Hayes | Desarrollador de contenido sénior
- Carol Smith | Desarrollador de contenido sénior
- Erin Schaffer | Desarrollador de contenido 2
- Adam Fabric | Ingeniero de clientes 2
Azure Kubernetes Service