Partager via


Déployer une base de données PostgreSQL hautement disponible sur Azure Kubernetes Service (AKS)

Dans cet article, vous déployez une base de données PostgreSQL à haute disponibilité sur AKS.

Important

Les logiciels open source sont mentionnés dans la documentation et les exemples AKS. Les logiciels que vous déployez sont exclus des contrats de niveau de service AKS, de la garantie limitée et du support Azure. Quand vous utilisez une technologie open source avec AKS, consultez les options de support disponibles auprès des communautés et responsables de projet respectifs pour élaborer un plan.

Microsoft assume la responsabilité de la génération des packages open source que nous déployons sur AKS. Cette responsabilité comprend la maîtrise totale des processus de génération, d’analyse, de signature, de validation et de correction, ainsi que le contrôle des fichiers binaires dans les images conteneur. Pour plus d’informations, consultez Gestion des vulnérabilités pour AKS et Couverture du support AKS.

Créer un secret pour un utilisateur d’application d’amorçage

  1. Générez un secret pour valider le déploiement PostgreSQL par connexion interactive pour un utilisateur d’application d’amorçage en utilisant la commande kubectl create secret.

Important

Microsoft vous recommande d’utiliser le flux d’authentification le plus sécurisé disponible. Le flux d’authentification décrit dans cette procédure nécessite un degré élevé de confiance dans l’application et comporte des risques qui ne sont pas présents dans d’autres flux. Utilisez ce flux seulement si d’autres flux plus sécurisés, tels que les identités managées, ne sont pas viables.

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
  1. Vérifiez que le secret a été créé avec succès en utilisant la commande kubectl get.

    kubectl get secret db-user-pass --namespace $PG_NAMESPACE --context $AKS_PRIMARY_CLUSTER_NAME
    

Définir des variables d’environnement pour le cluster PostgreSQL

  • Déployez un ConfigMap pour configurer l’opérateur CNPG à l’aide de la commande suivante kubectl apply . Ces valeurs remplacent la bascule ENABLE_AZURE_PVC_UPDATES héritée qui n’est plus nécessaire et permettent d’échelonner les mises à niveau et d’accélérer la reconnexion des réplicas. Avant de déployer cette configuration en production, vérifiez que tous les paramètres existants sur lesquels DRAIN_TAINTS vous vous appuyez restent compatibles avec votre environnement Azure.

    cat <<EOF | kubectl apply --context $AKS_PRIMARY_CLUSTER_NAME -n $PG_NAMESPACE -f -
    apiVersion: v1
    kind: ConfigMap
    metadata:
        name: cnpg-controller-manager-config
    data:
        CLUSTERS_ROLLOUT_DELAY: '120'
        STANDBY_TCP_USER_TIMEOUT: '10'
    EOF
    

Installer Prometheus PodMonitors

Prometheus interroge CNPG à l’aide des règles d’enregistrement stockées dans le dépôt GitHub de CNPG. Étant donné que le PodMonitor, géré par l’opérateur, est déconseillé, créez et gérez la ressource PodMonitor vous-même afin que vous puissiez l’adapter à votre pile de surveillance.

  1. Ajoutez le dépôt Helm de la communauté Prometheus en utilisant la commande helm repo add.

    helm repo add prometheus-community \
        https://prometheus-community.github.io/helm-charts
    
  2. Mettez à niveau le référentiel Helm de la communauté Prometheus et installez-le sur le cluster principal en utilisant la commande helm upgrade avec l’indicateur --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
    
  3. Créez un PodMonitor pour le cluster. L’équipe CNPG met en désuétude le PodMonitor géré par l’opérateur, vous devez donc maintenant le gérer directement :

    cat <<EOF | kubectl apply --context $AKS_PRIMARY_CLUSTER_NAME --namespace $PG_NAMESPACE -f -
    apiVersion: monitoring.coreos.com/v1
    kind: PodMonitor
    metadata:
      name: $PG_PRIMARY_CLUSTER_NAME
      namespace: ${PG_NAMESPACE}
      labels:
        cnpg.io/cluster: ${PG_PRIMARY_CLUSTER_NAME}
    spec:
      selector:
        matchLabels:
          cnpg.io/cluster: ${PG_PRIMARY_CLUSTER_NAME}
      podMetricsEndpoints:
        - port: metrics
    EOF
    

Créer des informations d’identification fédérées

Dans cette section, vous créez un jeu d’identifiants d’identité fédérée pour la sauvegarde PostgreSQL, pour permettre à CNPG d’utiliser l’identité de charge de travail AKS pour s’authentifier auprès de la destination du compte de stockage des sauvegardes. L’opérateur CNPG crée un compte de service Kubernetes portant le même nom que le cluster nommé utilisé dans le manifeste de déploiement du cluster CNPG.

  1. Obtenez l’URL de l’émetteur OIDC du cluster en utilisant la commande 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)"
    
  2. Créez des informations d’identification d’une identité fédérée à l’aide de la commande 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
    

Déployer un cluster PostgreSQL à haute disponibilité

Dans cette section, vous déployez un cluster PostgreSQL à haute disponibilité en utilisant la définition de ressource personnalisée (CRD) du cluster CNPG.

Paramètres CRD du cluster

Le tableau suivant présente les propriétés clés définies dans le manifeste de déploiement YAML pour la CRD de cluster :

Property Definition
imageName Pointe vers l’image conteneur d’opérande CloudNativePG. Utilisez ghcr.io/cloudnative-pg/postgresql:18-system-trixie avec l'intégration de sauvegarde in-core indiquée dans ce guide, ou passez à 18-standard-trixie lorsque vous adoptez le plugin Barman Cloud.
inheritedMetadata Spécifique à l’opérateur CNPG. L’opérateur CNPG applique les métadonnées à chaque objet lié au cluster.
annotations Inclut l’étiquette DNS requise pour l’exposition de points de terminaison de cluster et active alpha.cnpg.io/failoverQuorum pour le basculement basé sur le quorum.
labels: azure.workload.identity/use: "true" Indique qu’AKS doit injecter des dépendances d’identité de charge de travail dans les pods hébergeant les instances de cluster PostgreSQL.
topologySpreadConstraints Exiger différentes zones et différents nœuds avec l’étiquette "workload=postgres".
resources Configure une classe Qualité de service (QoS) Garantie. Dans un environnement de production, ces valeurs sont essentielles pour optimiser l’utilisation de la machine virtuelle de nœud sous-jacente et varient en fonction de la référence SKU de la machine virtuelle Azure utilisée.
probes Remplace la configuration héritée startDelay . Les probes readiness et de préparation de la diffusion en continu permettent de vérifier que les réplicas sont sains avant de servir le trafic.
smartShutdownTimeout Permet aux transactions longues de se terminer normalement pendant les mises à jour au lieu d’utiliser des délais d’arrêt agressifs.
bootstrap Spécifique à l’opérateur CNPG. Initialise avec une base de données d’application vide.
storage Définit les paramètres PersistentVolume de la base de données. Avec les disques managés Azure, la syntaxe simplifiée conserve les données et WAL sur le même volume de 64 Gio, ce qui offre de meilleurs niveaux de débit sur les disques managés. Ajustez si vous avez besoin de volumes WAL distincts.
postgresql.synchronous minSyncReplicas / maxSyncReplicas Remplace et vous permet de spécifier le comportement de réplication synchrone à l’aide du schéma plus récent.
postgresql.parameters Spécifique à l’opérateur CNPG. Mappe les paramètres pour postgresql.conf, pg_hba.confet pg_ident.conf. L’exemple met l’accent sur l’observabilité et les valeurs par défaut de rétention WAL qui conviennent au scénario d’identité de la charge de travail AKS, mais qui doivent être paramétrées par charge de travail.
serviceAccountTemplate Contient le modèle nécessaire pour générer les comptes de service et mappe les identifiants d’identité fédérée AKS à l’UAMI pour activer l’authentification d’identité de charge de travail AKS depuis les pods hébergeant les instances PostgreSQL vers des ressources Azure externes.
barmanObjectStore Spécifique à l’opérateur CNPG. Configure la suite d’outils barman-cloud à l’aide de l’identité de charge de travail AKS pour l’authentification auprès du magasin d’objets Stockage Blob Azure.

Pour isoler davantage les charges de travail PostgreSQL, vous pouvez ajouter une teinte (par exemple node-role.kubernetes.io/postgres=:NoSchedule) à vos nœuds de plan de données et remplacer l’exemple nodeSelector/tolerations par les valeurs recommandées par CloudNativePG. Si vous effectuez cette approche, étiquetez les nœuds en conséquence et confirmez que les stratégies de mise à l’échelle automatique AKS s’alignent sur votre topologie.

Paramètres de performances PostgreSQL

Les performances postgreSQL dépendent fortement des ressources et de la charge de travail sous-jacentes de votre cluster. Le tableau suivant fournit des instructions de base pour un cluster à trois nœuds s’exécutant sur des nœuds Standard D4s v3 (mémoire de 16 Gio). Traitez ces valeurs comme un point de départ et ajustez-les une fois que vous comprenez votre profil de charge de travail :

Property Valeur recommandée Definition
wal_compression lz4 Compresse les écritures de page complète écrites dans le fichier WAL avec la méthode spécifiée
max_wal_size 6 Go Définit la taille WAL qui déclenche un point de contrôle
checkpoint_timeout Durée : 15 minutes Définit la durée maximale entre les points de contrôle WAL automatiques
checkpoint_completion_target 0.9 Équilibre le travail de point de contrôle dans toute la fenêtre de point de contrôle
checkpoint_flush_after 2 Mo Nombre de pages après lesquelles les écritures précédemment effectuées sont vidées sur le disque
wal_writer_flush_after 2 Mo Quantité de journal WAL écrite par l’écriture WAL qui déclenche un vidage
min_wal_size 2 Go Définit la taille minimale de réduction du WAL sur
max_slot_wal_keep_size 10 Go Limite supérieure pour les emplacements de réplication WAL restant à servir
shared_buffers 4 Go Définit le nombre de mémoires tampons de mémoire partagée utilisées par le serveur (25% de mémoire de nœud dans cet exemple)
effective_cache_size 12 Go Définit l’hypothèse du planificateur sur la taille totale des caches de données
work_mem 1/256e de mémoire de nœud Définit la mémoire maximale à utiliser pour les espaces de travail de requête
maintenance_work_mem 6,25 % de la mémoire du nœud Définit la mémoire maximale à utiliser pour les opérations de maintenance
autovacuum_vacuum_cost_limit 2400 Montant du coût du nettoyage disponible avant la mise en veille, pour le nettoyage automatique
random_page_cost 1.1 Définit l’estimation du coût d’une page de disque récupérée de manière non séquentielle par le planificateur
effective_io_concurrency 64 Définit le nombre de demandes simultanées que le sous-système de disque peut gérer efficacement
maintenance_io_concurrency 64 Variante de « effective_io_concurrency » utilisée pour le travail de maintenance

Déploiement de PostgreSQL

  1. Déployez le cluster PostgreSQL avec la CRD de cluster en utilisant la commande 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
      annotations:
        alpha.cnpg.io/failoverQuorum: "true"
    spec:
      imageName: ghcr.io/cloudnative-pg/postgresql:18-system-trixie
      inheritedMetadata:
        annotations:
          service.beta.kubernetes.io/azure-dns-label-name: $AKS_PRIMARY_CLUSTER_PG_DNSPREFIX
        labels:
          azure.workload.identity/use: "true"
    
      instances: 3
      smartShutdownTimeout: 30
    
      probes:
        startup:
          type: streaming
          maximumLag: 32Mi
          periodSeconds: 5
          timeoutSeconds: 3
          failureThreshold: 120
        readiness:
          type: streaming
          maximumLag: 0
          periodSeconds: 10
          failureThreshold: 6
    
      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:
        storageClass: $POSTGRES_STORAGE_CLASS
        size: 64Gi
    
      postgresql:
        synchronous:
          method: any
          number: 1
        parameters:
          wal_compression: lz4
          max_wal_size: 6GB
          max_slot_wal_keep_size: 10GB
          checkpoint_timeout: 15min
          checkpoint_completion_target: '0.9'
          checkpoint_flush_after: 2MB
          wal_writer_flush_after: 2MB
          min_wal_size: 2GB
          shared_buffers: 4GB
          effective_cache_size: 12GB
          work_mem: 62MB
          maintenance_work_mem: 1GB
          autovacuum_vacuum_cost_limit: "2400"
          random_page_cost: "1.1"
          effective_io_concurrency: "64"
          maintenance_io_concurrency: "64"
          log_checkpoints: 'on'
          log_lock_waits: 'on'
          log_min_duration_statement: '1000'
          log_statement: 'ddl'
          log_temp_files: '1024'
          log_autovacuum_min_duration: '1s'
          pg_stat_statements.max: '10000'
          pg_stat_statements.track: 'all'
          hot_standby_feedback: 'on'
        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
    

Note

L’exemple de manifeste utilise l’image ghcr.io/cloudnative-pg/postgresql:18-system-trixie , car elle fonctionne avec l’intégration de Barman Cloud in-core présentée ultérieurement. Lorsque vous êtes prêt à basculer vers le plug-in Barman Cloud, mettez à spec.imageName jour ghcr.io/cloudnative-pg/postgresql:18-standard-trixie et suivez les instructions de configuration du plug-in avant de redéployer le cluster.

Important

L’exemple d’entrée pg_hba autorise l’accès non TLS. Si vous conservez cette configuration, documentez les implications de sécurité pour votre équipe et préférez les connexions chiffrées dans la mesure du possible.

  1. Vérifiez que le cluster PostgreSQL principal a été correctement créé en utilisant la commande kubectl get. La CRD de cluster CNPG a spécifié trois instances, ce qui peut être validé en consultant les pods en cours d’exécution une fois que chaque instance est générée et jointe pour la réplication. Soyez patient, car un certain temps peut être nécessaire pour que les trois instances soient en ligne et rejoignent le cluster.

    kubectl get pods --context $AKS_PRIMARY_CLUSTER_NAME --namespace $PG_NAMESPACE -l cnpg.io/cluster=$PG_PRIMARY_CLUSTER_NAME
    

    Exemple de sortie

    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
    

Important

Si vous utilisez NVMe local avec Stockage de conteneurs Azure et que votre pod reste dans l’état init avec une erreur de multi-attachement, il est probable qu’il recherche encore le volume sur un nœud perdu. Une fois le pod en cours de fonctionnement, il entre dans un CrashLoopBackOff état, car CNPG crée une nouvelle réplique sur un nouveau nœud sans données et ne trouve pas le répertoire pgdata. Pour résoudre ce problème, détruisez l’instance affectée et affichez-en une nouvelle. Exécutez la commande suivante:

kubectl cnpg destroy [cnpg-cluster-name] [instance-number]  

Valider que Prometheus PodMonitor est en cours d’exécution

PodMonitor créé manuellement lie la configuration de scraper kube-prometheus-stack aux pods CNPG déployés précédemment.

Vérifiez que PodMonitor est en cours d’exécution en utilisant la commande kubectl get.

kubectl --namespace $PG_NAMESPACE \
    --context $AKS_PRIMARY_CLUSTER_NAME \
    get podmonitors.monitoring.coreos.com \
    $PG_PRIMARY_CLUSTER_NAME \
    --output yaml

Exemple de sortie

kind: PodMonitor
metadata:
  labels:
    cnpg.io/cluster: pg-primary-cnpg-r8c7unrw
  name: pg-primary-cnpg-r8c7unrw
  namespace: cnpg-database
spec:
  podMetricsEndpoints:
  - port: metrics
  selector:
    matchLabels:
      cnpg.io/cluster: pg-primary-cnpg-r8c7unrw

Si vous utilisez Azure Monitor pour Prometheus managé, vous devez ajouter un autre moniteur de pod à l’aide du nom de groupe personnalisé. Managed Prometheus ne récupère pas les définitions de ressources personnalisées (CRD) de la communauté Prometheus. Outre le nom du groupe, les CRD sont identiques. Cette conception permet aux moniteurs de pods pour Managed Prometheus de fonctionner en parallèle des moniteurs de pods utilisant le CRD de la communauté. Si vous n’utilisez pas Managed Prometheus, vous pouvez ignorer cette section. Créez un moniteur 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

Vérifiez que le moniteur de pod est créé (notez la différence dans le nom de groupe).

kubectl --namespace $PG_NAMESPACE \
    --context $AKS_PRIMARY_CLUSTER_NAME \
    get podmonitors.azmonitoring.coreos.com \
    -l cnpg.io/cluster=$PG_PRIMARY_CLUSTER_NAME \
    -o yaml

Option A - Espace de travail Azure Monitor

Après avoir déployé le cluster Postgres et le moniteur de pod, vous pouvez afficher les métriques à l’aide du portail Azure dans un espace de travail Azure Monitor.

Capture d’écran montrant les métriques de cluster Postgres dans un espace de travail Azure Monitor dans le portail Azure.

Option B : Managed Grafana

Vous pouvez, après avoir déployé le cluster Postgres et les moniteurs de pod, créer un tableau de bord des indicateurs sur l’instance Managed Grafana créée par le script de déploiement pour visualiser les métriques exportées vers l’espace de travail Azure Monitor. Vous pouvez accéder à Managed Grafana via le Portail Azure. Accédez à l’instance Managed Grafana créée par le script de déploiement et sélectionnez le lien Point de terminaison, comme indiqué ici :

Capture d’écran des métriques de cluster Postgres dans une instance Azure Managed Grafana dans le portail Azure.

La sélection du lien Point de terminaison ouvre une nouvelle fenêtre de navigateur dans laquelle vous pouvez créer des tableaux de bord sur l’instance Managed Grafana. En suivant les instructions pour configurer une source de données Azure Monitor, vous pouvez ensuite ajouter des visualisations pour créer un tableau de bord de métriques depuis le cluster Postgres. Après avoir configuré la connexion de source de données, dans le menu principal, sélectionnez l’option Sources de données. Vous devez voir un ensemble d’options de source de données pour la connexion à la source de données, comme indiqué ici :

Capture d’écran montrant les options de source de données Azure Monitor dans le portail Azure.

Dans l’option Prometheus gérée, sélectionnez l’option permettant de générer un tableau de bord pour ouvrir l’éditeur de tableau de bord. Une fois la fenêtre de l’éditeur ouverte, sélectionnez l’option Ajouter une visualisation, puis sélectionnez l’option Prometheus gérée pour parcourir les métriques à partir du cluster Postgres. Après avoir sélectionné la métrique que vous souhaitez visualiser, sélectionnez le bouton Exécuter des requêtes pour extraire les données de la visualisation, comme indiqué ici :

Capture d’écran montrant un tableau de bord Prometheus managé avec les métriques de cluster Postgres.

Sélectionnez l’icône Enregistrer pour ajouter le panneau à votre tableau de bord. Vous pouvez ajouter d’autres panneaux en sélectionnant le bouton Ajouter dans l’éditeur de tableau de bord et en répétant ce processus pour visualiser d’autres métriques. L’ajout des visualisations de métriques doit ressembler à ceci :

Capture d’écran montrant un tableau de bord Prometheus managé enregistré dans le portail Azure.

Sélectionnez l’icône Enregistrer pour enregistrer votre tableau de bord.


Étapes suivantes

Contributors

La gestion de cet article est sous la responsabilité de Microsoft. Les contributeurs suivants ont rédigé sa version d’origine :

  • Ken Kitty | Responsable de programme technique en chef
  • Russell de Pina | Responsable de programme technique en chef
  • Adrian Joian | Ingénieur client senior
  • Jenny Hayes | Développeuse de contenu confirmée
  • Carol Smith | Développeuse de contenu confirmée
  • Erin Schaffer | Développeuse de contenu 2
  • Adam Sharif | Ingénieur client 2

Accusé de réception

Cette documentation a été développée conjointement avec EnterpriseDB, les mainteneurs de l’opérateur CloudNativePG. Nous remercions Gabriele Bartolini d’avoir examiné les brouillons précédents de ce document et d’offrir des améliorations techniques.