共用方式為


在 Azure Kubernetes Service 上部署高可用性 PostgreSQL 資料庫 (AKS)

在本文中,您會在 AKS 上部署高可用性 PostgreSQL 資料庫。

Important

整個 AKS 文件和範例都會提及開放原始碼的軟體。 您部署的軟體會從 AKS 服務等級協定、有限保固和 Azure 支援 中排除。 當您搭配 AKS 使用開放原始碼技術時,請參閱個別社群和專案維護人員所提供的支援選項,以開發計畫。

Microsoft負責建置我們在 AKS 上部署的開放原始碼套件。 該責任包括擁有組建、掃描、簽署、驗證和 Hotfix 程式的完整擁有權,以及控制容器映像中的二進位檔。 如需詳細資訊,請參閱 AKS 弱點管理AKS 支援涵蓋範圍

建立啟動程序應用程式使用者的秘密

  1. 使用 kubectl create secret 命令,產生密鑰,以透過引導應用程式使用者的互動式登入來驗證 PostgreSQL 部署。

Important

Microsoft 建議您使用最安全的可用驗證流程。 此程序中所述的驗證流程需要對應用程式的高度信任,並具有其他流程中不存在的風險。 只有在其他更安全的流程,例如受控識別無法使用時,才應該使用此流程。

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. 使用 kubectl get 命令驗證密碼已成功建立。

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

設定 PostgreSQL 叢集的環境變數

  • 使用下列 kubectl apply 命令部署 ConfigMap 以設定 CNPG 運算子。 這些值會取代不再需要的舊版 ENABLE_AZURE_PVC_UPDATES 切換,並協助分散升級及加快複本重新連線。 將此設定推出生產環境之前,請驗證您所依賴的任何現有 DRAIN_TAINTS 設定是否與 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
    

安裝 Prometheus PodMonitors

Prometheus 會使用儲存在 CNPG GitHub 範例存放庫中的記錄規則來抓取 CNPG。 由於操作員管理的 PodMonitor 已被取代,因此請自行建立和管理 PodMonitor 資源,以便根據您的監控堆疊進行量身打造。

  1. 使用 helm repo add 命令新增 Prometheus Community Helm 存放庫。

    helm repo add prometheus-community \
        https://prometheus-community.github.io/helm-charts
    
  2. 升級 Prometheus Community Helm 存放庫,並使用具有 helm upgrade 旗標的 --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. 為叢集建立 PodMonitor。 CNPG 團隊正在取代操作員管理的 PodMonitor,因此您現在可以直接管理它:

    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
    

建立聯邦認證

在本節中,您會建立 PostgreSQL 備份的同盟身分識別認證,以允許 CNPG 使用 AKS 工作負載身分識別向儲存體帳戶目的地進行驗證以進行備份。 CNPG 操作員會建立 Kubernetes 服務帳戶,其名稱與 CNPG 叢集部署指令清單中使用的叢集名稱相同。

  1. 使用 az aks show 命令取得叢集的 OIDC 簽發者 URL。

    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. 使用 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
    

部署高可用性 PostgreSQL 叢集

在本節中,您會使用 CNPG 叢集自訂資源定義 (CRD) 部署高可用性 PostgreSQL 叢集。

叢集 CRD 參數

下表概述叢集 CRD 之 YAML 部署指令清單中設定的主要屬性:

Property Definition
imageName 指向 CloudNativePG 運算元容器映像。 ghcr.io/cloudnative-pg/postgresql:18-system-trixie與本指南中顯示的核心備份整合一起使用,或在您採用 Barman Cloud 外掛程式時切換到18-standard-trixie
inheritedMetadata 特定於 CNPG 運算子。 CNPG 運算子會將中繼資料 (metadata) 套用至與叢集相關的每個物件。
annotations 包含在公開叢集端點時所需的 DNS 標籤,並啟用 alpha.cnpg.io/failoverQuorum (英文) 以支援仲裁型容錯移轉。
labels: azure.workload.identity/use: "true" 指出 AKS 應該將工作負載身分識別相依性插入裝載 PostgreSQL 叢集執行個體的 Pod 中。
topologySpreadConstraints 需要具有標籤 "workload=postgres" 的不同區域和不同節點。
resources 將服務品質 (QoS) 類別設定為有保證。 在生產環境中,這些值是最大化基礎節點 VM 使用量的關鍵,而且會根據所使用的 Azure VM SKU 而有所不同。
probes 取代舊版 startDelay 組態。 串流啟動及就緒探查有助於確保複本在開始提供流量之前狀況良好。
smartShutdownTimeout 允許長時間執行的交易在更新期間正常完成,而不是使用強制停止延遲。
bootstrap 特定於 CNPG 運算子。 使用空的應用程式資料庫初始化。
storage 定義資料庫的 PersistentVolume 設定。 使用 Azure 受控磁碟時,簡化的語法會將資料和 WAL 保留在相同的 64 GiB 磁碟區上,這會在受控磁碟上提供更好的輸送量層。 如果您需要單獨的WAL卷,請進行調整。
postgresql.synchronous 取代 minSyncReplicas/maxSyncReplicas 並允許您使用較新的結構描述指定同步複寫行為。
postgresql.parameters 特定於 CNPG 運算子。 對應 postgresql.confpg_hba.confpg_ident.conf 的設定。 此範例強調了可檢視性以及適合 AKS 工作負載身分識別案例的 WAL 保留預設值,但應根據實際工作負載進行調整。
serviceAccountTemplate 包含產生服務帳戶並將 AKS 同盟身分識別認證對應至 UAMI 所需的範本,以啟用從裝載 PostgreSQL 執行個體的 Pod 到外部 Azure 資源的 AKS 工作負載身分識別驗證。
barmanObjectStore 特定於 CNPG 運算子。 使用 AKS 工作負載身分識別來設定 barman-cloud 工具套件,以向 Azure Blob 儲存體物件存放區進行驗證。

若要進一步隔離 PostgreSQL 工作負載,您可以將污點 (例如 node-role.kubernetes.io/postgres=:NoSchedule) 新增至資料平面節點,並將範例 nodeSelector/tolerations 取代為 CloudNativePG 建議的值。 如果您採用此方法,請相應地標記節點,並確認 AKS 自動調整程式原則與您的拓撲一致。

PostgreSQL 效能參數

PostgreSQL 效能在很大程度上取決於叢集的基礎資源和工作負載。 下表提供在標準 D4s v3 節點 (16 GiB 記憶體) 上執行之三節點叢集的基準指引。 將這些值視為起點,並在瞭解工作負載設定檔後進行調整:

Property 建議值 Definition
wal_compression lz4 使用指定的方法壓縮以 WAL 檔案寫入的完整頁面寫入
max_wal_size 6 GB 設定觸發檢查點的 WAL 大小
checkpoint_timeout 15 分鐘 設定自動 WAL 檢查點之間的時間上限
checkpoint_completion_target 0.9 在檢查點時段內平衡檢查點的工作
checkpoint_flush_after 2 MB 要將先前所執行寫入排清到磁碟的最後分頁數
wal_writer_flush_after 2 MB 由觸發排清之 WAL 寫入器寫出的 WAL 數量
min_wal_size 2 GB 將WAL縮小的大小下限設定為
max_slot_wal_keep_size 10 GB WAL 可供服務複寫位置的上限
shared_buffers 4 GB 設定伺服器使用的共用記憶體緩衝區數目 (在此範例中為 25% 節點記憶體)
effective_cache_size 12 GB 設定規劃工具關於資料快取大小總計的假設
work_mem 節點記憶體的 1/256 設定要用於查詢工作區的最大記憶體
maintenance_work_mem 6.25% 的節點記憶體 設定要用於維護作業的最大記憶體
autovacuum_vacuum_cost_limit 2400 在 napping 之前可用的清理成本金額,適用於自動清理
random_page_cost 1.1 設定規劃工具對非循序擷取之磁碟分頁的成本估計值
effective_io_concurrency 64 設定磁碟子系統可有效率處理的同時要求數量
maintenance_io_concurrency 64 用於維護工作的 effective_io_concurrency 變化

部署 PostgreSQL

  1. 使用 kubectl apply 命令,使用叢集 CRD 部署 PostgreSQL 叢集。

    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
    

備註

此範例資訊清單會使用 ghcr.io/cloudnative-pg/postgresql:18-system-trixie 映像,因為它可與稍後顯示的核心內 Barman Cloud 整合搭配運作。 當您準備切換至 Barman Cloud 外掛程式時,請先將 spec.imageName 更新為 ghcr.io/cloudnative-pg/postgresql:18-standard-trixie,然後遵循 外掛程式組態指引,最後重新部署叢集。

Important

範例 pg_hba 項目允許非 TLS 存取。 如果您保留此設定,請記錄團隊的安全影響,並儘可能偏好加密連線。

  1. 使用 kubectl get 命令驗證已成功建立主要 PostgreSQL 叢集。 CNPG 叢集 CRD 指定三個執行個體,只要每個執行個體啟動並聯結複寫,即可檢視執行中的 Pod 來進行驗證。 請耐心等待,因為讓這三個實例全部上線並加入叢集可能需要一些時間。

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

    範例輸出

    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

如果您使用本機 NVMe 搭配 Azure 容器儲存體,且 Pod 停留在 init 狀態並出現多重連結錯誤,則表示該 Pod 仍在遺失的節點上搜尋磁碟區。 當 Pod 開始運行之後,它將進入 CrashLoopBackOff 狀態,因為 CNPG 在沒有資料的新節點上建立了新的複本,而且 pgdata 目錄找不到。 若要解決此問題,請終結受影響的執行個體,然後啟動新的執行個體。 執行下列命令:

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

驗證 Prometheus PodMonitor 正在執行

手動建立的 PodMonitor 會將 kube-prometheus-stack 抓取配置與您先前部署的 CNPG Pod 綁定。

使用 kubectl get 命令驗證 PodMonitor 正在執行。

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

範例輸出

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

如果您正在使用 Azure Monitor 來管理 Prometheus,則必須使用自定義組名來新增另一個 Pod 監視器。 Managed Prometheus 不會從 Prometheus 社群中接收自定義資源定義(CRDs)。 除了群組名稱之外,CRD 都是相同的。 該設計可讓 Managed Prometheus 的 pod 監視器與使用社群 CRD 的 pod 監視器同時運行。 如果您未使用 Managed Prometheus,則可以略過本節。 建立新的 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

確認已建立 Pod 監視器 (請注意群組名稱的差異)。

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

選項 A - Azure 監視器工作區

部署 Postgres 叢集和網繭監視器之後,您可以使用 Azure 監視器工作區中的 Azure 入口網站來檢視計量。

顯示 Azure 入口網站中 Azure 監視器工作區中 Postgres 叢集計量的螢幕快照。

選項 B - 受控 Grafana

或者,部署 Postgres 叢集和 Pod 監視器之後,您可以在部署指令碼所建立的受控 Grafana 執行個體上建立計量儀表板,以視覺化匯出至 Azure 監視器工作區的計量。 您可以透過 Azure 入口網站存取管理的 Grafana。 瀏覽至部署指令碼所建立的受控 Grafana 執行個體,並選取 [端點] 連結,如下所示:

Azure 入口網站中 Azure 受控 Grafana 實例中的 Postgres 叢集計量螢幕快照。

選取 [端點] 鏈接會開啟新的瀏覽器視窗,您可以在 Managed Grafana 實例上建立儀錶板。 依照指示設定 Azure 監視器資料來源,然後您可以新增視覺效果,以利從 Postgres 叢集建立計量的儀表板。 設定數據源聯機之後,從主功能表選取 [數據源] 選項。 您應該會看到資料源連線的一組數據源選項,如下所示:

顯示 Azure 入口網站中 Azure 監視器數據源選項的螢幕快照。

在 [Managed Prometheus] 選項上,選取建置儀錶板以開啟儀錶板編輯器的選項。 編輯器視窗開啟之後,選取 [新增視覺化] 選項,然後選取 [受管 Prometheus] 選項,以瀏覽 Postgres 叢集中的指標。 選取您要視覺化的計量之後,請選取 [執行查詢] 按鈕以擷取視覺效果的資料,如下所示:

顯示具有 Postgres 叢集計量的受控 Prometheus 儀表板的螢幕擷取畫面。

選取 [儲存] 圖示,將面板新增至儀錶板。 您可以選取儀錶板編輯器中的 [新增] 按鈕,並重複此程式以可視化其他計量來新增其他面板。 新增計量視覺效果時,您應該會有如下所示的內容:

顯示 Azure 入口網站中已儲存的受控 Prometheus 儀表板的螢幕擷取畫面。

選取 [儲存] 圖示以儲存儀錶板。


後續步驟

Contributors

本文由 Microsoft 維護。 最初撰寫這篇文章的參與者如下:

  • Ken Kilty | 首席 TPM
  • Russell de Pina | 首席 TPM
  • Adrian Joian |資深客戶工程師
  • Jenny Hayes | 資深內容開發人員
  • Carol Smith | 資深內容開發人員
  • Erin Schaffer |內容開發人員 2
  • Adam Sharif |客戶工程師 2

通知

本文檔是與 CloudNativePG 運營商的維護者 EnterpriseDB 共同開發的。 我們感謝 Gabriele Bartolini 審查本文件的早期草稿並提供技術改進。