Distribuera en PostgreSQL-databas med hög tillgänglighet i Azure Kubernetes Service (AKS)

I den här artikeln distribuerar du en PostgreSQL-databas med hög tillgänglighet på AKS.

Important

Programvara med öppen källkod nämns i AKS-dokumentationen och exempel. Programvara som du distribuerar undantas från AKS-serviceavtal, begränsad garanti och Azure Support. När du använder teknik med öppen källkod tillsammans med AKS kan du läsa supportalternativen som är tillgängliga från respektive community och projektunderhållare för att utveckla en plan.

Microsoft tar ansvar för att skapa de paket med öppen källkod som vi distribuerar på AKS. Det ansvaret omfattar att ha fullständigt ägarskap för bygg-, genomsöknings-, signerings-, validerings- och snabbkorrigeringsprocessen, tillsammans med kontroll över binärfilerna i containeravbildningar. Mer information finns i Sårbarhetshantering för AKS - och AKS-stödtäckning.

Skapa hemlighet för bootstrap-appanvändare

  1. Generera en hemlighet för att verifiera PostgreSQL-distributionen genom interaktiv inloggning för en bootstrap-appanvändare med hjälp av kubectl create secret kommandot .

Important

Microsoft rekommenderar att du använder det säkraste tillgängliga autentiseringsflödet. Det autentiseringsflöde som beskrivs i den här proceduren kräver en hög grad av förtroende för programmet och medför risker som inte finns i andra flöden. Du bör bara använda det här flödet när andra säkrare flöden, till exempel hanterade identiteter, inte är livskraftiga.

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. Kontrollera att hemligheten har skapats med kommandot kubectl get .

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

Ange miljövariabler för PostgreSQL-klustret

  • Distribuera en ConfigMap för att konfigurera CNPG-operatorn med hjälp av följande kubectl apply kommando. Dessa värden ersätter den äldre ENABLE_AZURE_PVC_UPDATES växlingsknappen, som inte längre krävs, och hjälper till att växla uppgraderingar och påskynda replikåteranslutningar. Innan du distribuerar den här konfigurationen till produktion kontrollerar du att alla befintliga DRAIN_TAINTS inställningar som du förlitar dig på förblir kompatibla med din Azure-miljö.

    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
    

Installera Prometheus PodMonitors

Prometheus skrapar CNPG med hjälp av inspelningsreglerna som lagras i CNPG GitHub-exempel-lagringsplatsen. Eftersom den operatorhanterade PodMonitor är på väg att utfasas, skapar och hanterar du PodMonitor-resursen själv för att anpassa den till din övervakningsstack.

  1. Lägg till Prometheus Community Helm-lagringsplatsen med kommandot helm repo add .

    helm repo add prometheus-community \
        https://prometheus-community.github.io/helm-charts
    
  2. Uppgradera Prometheus Community Helm-repositoryt och installera det på det primära klustret med kommandot helm upgrade och flaggan --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. Skapa en PodMonitor för klustret. CNPG-teamet har gjort den operatör-hanterade PodMonitor inaktuell, så att du nu hanterar det direkt.

    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
    

Skapa en federerad autentiseringsuppgift

I det här avsnittet skapar du en federerad identitetsautentiseringsuppgift för PostgreSQL-säkerhetskopiering så att CNPG kan använda AKS-arbetsbelastningsidentitet för att autentisera till lagringskontots mål för säkerhetskopior. CNPG-operatorn skapar ett Kubernetes-tjänstkonto med samma namn som klustret med namnet som används i CNPG-klusterdistributionsmanifestet.

  1. Hämta OIDC-utfärdarens URL för klustret med kommandot 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. Skapa en federerad identitetsautentiseringsuppgift med kommandot 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
    

Distribuera ett PostgreSQL-kluster med hög tillgänglighet

I det här avsnittet distribuerar du ett PostgreSQL-kluster med hög tillgänglighet med hjälp av den anpassade resursdefinitionen för CNPG-kluster (CRD).

Crd-parametrar för kluster

I följande tabell beskrivs de nyckelegenskaper som anges i YAML-distributionsmanifestet för kluster-CRD:

Property Definition
imageName Pekar på containeravbildningen CloudNativePG operand. Använd ghcr.io/cloudnative-pg/postgresql:18-system-trixie med den grundläggande säkerhetskopieringsintegrering som visas i den här guiden eller växla till 18-standard-trixie när du använder Plugin-programmet Barman Cloud.
inheritedMetadata Specifikt för CNPG-operatorn. CNPG-operatorn tillämpar metadata på alla objekt som är relaterade till klustret.
annotations Innehåller den DNS-etikett som krävs när klusterslutpunkterna exponeras och aktiverar alpha.cnpg.io/failoverQuorum för kvorumbaserad felövergång.
labels: azure.workload.identity/use: "true" Anger att AKS ska mata in arbetsbelastningsidentitetsberoenden i poddarna som är värdar för PostgreSQL-klusterinstanserna.
topologySpreadConstraints Kräv olika zoner och olika noder med etiketten "workload=postgres".
resources Konfigurerar en QoS-klass (Quality of Service) för Guaranteed. I en produktionsmiljö är dessa värden viktiga för att maximera användningen av den underliggande virtuella nodddatorn och varierar beroende på vilken Azure VM SKU som används.
probes Ersätter den äldre startDelay konfigurationen. Start- och beredskapskontroller för direktuppspelning hjälper till att säkerställa att replikerna är i god hälsa innan de används för att hantera trafik.
smartShutdownTimeout Möjliggör att långvariga transaktioner kan slutföras smidigt under uppdateringar i stället för att använda aggressiva stoppfördröjningar.
bootstrap Specifikt för CNPG-operatorn. Initieras med en tom appdatabas.
storage Definierar inställningarna för PersistentVolume för databasen. Med Azure-hanterade diskar behåller den förenklade syntaxen data och WAL på samma 64-GiB-volym, vilket ger bättre dataflödesnivåer på hanterade diskar. Justera om du behöver separata WAL-volymer.
postgresql.synchronous Ersätter minSyncReplicas/maxSyncReplicas och låter dig ange synkront replikeringsbeteende med hjälp av det nyare schemat.
postgresql.parameters Specifikt för CNPG-operatorn. Maps-inställningar för postgresql.conf, pg_hba.confoch pg_ident.conf. Exemplet betonar standardvärden för observerbarhet och WAL-kvarhållning som passar AKS-arbetsbelastningsidentitetsscenariot, men som bör justeras efter varje särskild arbetsbelastning.
serviceAccountTemplate Innehåller mallen som behövs för att generera tjänstkontona och mappar AKS-federerade identitetsautentiseringsuppgifter till UAMI för att aktivera AKS-arbetsbelastningsidentitetsautentisering från poddarna som är värd för PostgreSQL-instanserna till externa Azure-resurser.
barmanObjectStore Specifikt för CNPG-operatorn. Konfigurerar barman-cloud-verktygssviten med AKS arbetsbelastningsidentitet för autentisering mot Azure Blob Storage-objektlagret.

Om du vill isolera PostgreSQL-arbetsbelastningar ytterligare kan du lägga till en taint (till exempel node-role.kubernetes.io/postgres=:NoSchedule) till dina dataplansnoder och ersätta exemplet nodeSelector/tolerations med de värden som rekommenderas av CloudNativePG. Om du använder den här metoden kan du märka noderna därefter och bekräfta att AKS autoskalningspolicyerna matchar din topologi.

Prestandaparametrar för PostgreSQL

PostgreSQL-prestanda är starkt beroende av klustrets underliggande resurser och arbetsbelastning. Följande tabell innehåller grundläggande vägledning för ett kluster med tre noder som körs på Standard D4s v3-noder (16-GiB-minne). Behandla dessa värden som en startpunkt och justera dem när du förstår din arbetsbelastningsprofil:

Property Rekommenderat värde Definition
wal_compression lz4 Komprimerar helsidesskrivningar skrivna i WAL-fil med angiven metod
max_wal_size 6 GB Anger den WAL-storlek som utlöser en kontrollpunkt
checkpoint_timeout 15 minuter Anger den maximala tiden mellan automatiska WAL-kontrollpunkter
checkpoint_completion_target 0,9 Fördelar kontrollpunktsarbete över kontrollpunktsfönstret
checkpoint_flush_after 2 MB Antal sidor varefter tidigare utförda skrivningar rensas till disk
wal_writer_flush_after 2 MB Mängden WAL som skrivs ut av WAL-skrivaren och som utlöser en tömning
min_wal_size 2 GB Anger den minsta storleken för att krympa WAL till
max_slot_wal_keep_size 10 GB Övre gräns för WAL kvar för replikeringsplatser för tjänster
shared_buffers 4 GB Anger antalet buffertar för delat minne som används av servern (25% nodminne i det här exemplet)
effective_cache_size 12 GB Anger planerarens antagande om den totala storleken på datacachen
work_mem 1/256-del av nodminnet Anger det maximala minne som ska användas för frågearbetsytor
maintenance_work_mem 6.25% av nodminne Anger det maximala minne som ska användas för underhållsåtgärder
autovacuum_vacuum_cost_limit 2400 Vakuumkostnadsbelopp som är tillgängligt före tupplur, för autovacuum
random_page_cost 1.1 Anger planerarens uppskattning av kostnaden för en icke-sekventiellt hämtad disksida
effective_io_concurrency 64 Anger hur många samtidiga begäranden diskundersystemet kan hantera effektivt
maintenance_io_concurrency 64 En variant av "effective_io_concurrency" som används för underhållsarbete

Implementera PostgreSQL

  1. Distribuera PostgreSQL-klustret med kluster-CRD med hjälp av kubectl apply kommandot .

    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
    

Anmärkning

Exempelmanifestet använder avbildningen ghcr.io/cloudnative-pg/postgresql:18-system-trixie eftersom den fungerar med den grundläggande Barman Cloud-integreringen som visas senare. När du är redo att växla till Barman Cloud-plugin, uppdatera spec.imageName till ghcr.io/cloudnative-pg/postgresql:18-standard-trixie och följ konfigurationsguiden innan du distribuerar om klustret.

Important

pg_hba Exempelposten tillåter icke-TLS-åtkomst. Om du behåller den här konfigurationen dokumenterar du säkerhetskonsekvenserna för ditt team och föredrar krypterade anslutningar där det är möjligt.

  1. Kontrollera att det primära PostgreSQL-klustret har skapats med kommandot kubectl get . CNPG-kluster-CRD angav tre instanser, som kan verifieras genom att visa poddar som körs när varje instans har tagits upp och anslutits för replikering. Ha tålamod eftersom det kan ta lite tid för alla tre instanserna att komma online och ansluta till klustret.

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

    Exempel på utdata

    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

Om du använder lokal NVMe med Azure Container Storage och en podd fortfarande är i init-tillstånd med ett multi-attach-fel söker podden fortfarande efter volymen på en förlorad nod. När podden börjar köras anger den ett CrashLoopBackOff tillstånd eftersom CNPG skapar en ny replik på en ny nod utan data och inte kan hitta pgdata katalogen. Lös problemet genom att förstöra den berörda instansen och skapa en ny. Kör följande kommando:

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

Verifiera att Prometheus PodMonitor körs

Den manuellt skapade PodMonitor kopplar kube-prometheus-stack-scrape-konfigurationen till de CNPG-poddar som du distribuerade tidigare.

Verifiera att PodMonitor körs med kommandot kubectl get .

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

Exempel på utdata

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

Om du använder Azure Monitor för Managed Prometheus måste du lägga till ytterligare en poddövervakare med det anpassade gruppnamnet. Managed Prometheus hämtar inte de anpassade resursdefinitionerna (CRD) från Prometheus-communityn. Förutom gruppnamnet är CRD:erna samma. Med den designen kan poddövervakare för Managed Prometheus köras tillsammans med poddövervakare som använder communityns CRD. Om du inte använder Managed Prometheus kan du hoppa över det här avsnittet. Skapa en ny poddövervakare:

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

Kontrollera att poddövervakaren har skapats (observera skillnaden i gruppnamnet).

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

Alternativ A – Azure Monitor-arbetsyta

När du har distribuerat Postgres-klustret och poddövervakaren kan du visa måtten med hjälp av Azure-portalen på en Azure Monitor-arbetsyta.

Skärmbild som visar Postgres-klustermått på en Azure Monitor-arbetsyta i Azure-portalen.

Alternativ B – Hanterad Grafana

När du har distribuerat Postgres-klustret och poddövervakarna kan du också skapa en instrumentpanel för mått på den hanterade Grafana-instansen som skapats av distributionsskriptet för att visualisera de mått som exporteras till Azure Monitor-arbetsytan. Du kan komma åt Managed Grafana via Azure Portal. Gå till den hanterade Grafana-instansen som skapats av distributionsskriptet och välj länken Slutpunkt enligt följande:

Skärmbild av Postgres-klustermått i en Azure Managed Grafana-instans i Azure-portalen.

När du väljer slutpunktslänken öppnas ett nytt webbläsarfönster där du kan skapa instrumentpaneler på den hanterade Grafana-instansen. Genom att följa anvisningarna för att konfigurera en Azure Monitor-datakälla kan du sedan lägga till visualiseringar för att skapa en instrumentpanel med mått från Postgres-klustret. När du har konfigurerat anslutningen till datakällan går du till huvudmenyn och väljer alternativet Datakällor. Du bör se en uppsättning alternativ för anslutningen till datakällan som visas här:

Skärmbild som visar alternativ för Azure Monitor-datakälla i Azure-portalen.

Under alternativet Hanterad Prometheus väljer du att skapa en instrumentpanel för att öppna instrumentpanelsredigeraren. När redigeringsfönstret har öppnats väljer du alternativet Lägg till visualisering och väljer sedan alternativet Hanterad prometheus för att bläddra bland måtten från Postgres-klustret. När du har valt det mått som du vill visualisera väljer du knappen Kör frågor för att hämta data för visualiseringen enligt följande:

Skärmbild som visar en hanterad Prometheus-instrumentpanel med Postgres-klustermått.

Välj ikonen Spara för att lägga till panelen på instrumentpanelen. Du kan lägga till andra paneler genom att välja knappen Lägg till i instrumentpanelsredigeraren och upprepa den här processen för att visualisera andra mått. Om du lägger till måttvisualiseringarna bör du ha något som ser ut så här:

Skärmbild som visar en sparad hanterad Prometheus-instrumentpanel i Azure-portalen.

Välj ikonen Spara för att spara instrumentpanelen.


Nästa steg

Contributors

Microsoft uppdaterar den här artikeln. Följande deltagare skrev den ursprungligen:

  • Ken Kilty | Chef för TPM
  • Russell de Pina | Chef för TPM
  • Adrian Joian | Senior kundtekniker
  • Jenny Hayes | Senior innehållsutvecklare
  • Carol Smith | Senior innehållsutvecklare
  • Erin Schaffer | Innehållsutvecklare 2
  • Adam Sharif | Kundtekniker 2

Erkännande

Den här dokumentationen har utvecklats tillsammans med EnterpriseDB, underhållarna av CloudNativePG-operatören. Vi tackar Gabriele Bartolini för att ha granskat tidigare utkast till detta dokument och erbjudit tekniska förbättringar.