在本文中,您會在 AKS 上部署高可用性 PostgreSQL 資料庫。
- 如果您仍需要為此部署建立必要的基礎結構,請遵循建立基礎結構中的步驟,以在 AKS 上部署高可用性的 PostgreSQL 資料庫 進行設定,然後返回本文。
Important
整個 AKS 文件和範例都會提及開放原始碼的軟體。 您部署的軟體會從 AKS 服務等級協定、有限保固和 Azure 支援 中排除。 當您搭配 AKS 使用開放原始碼技術時,請參閱個別社群和專案維護人員所提供的支援選項,以開發計畫。
Microsoft負責建置我們在 AKS 上部署的開放原始碼套件。 該責任包括擁有組建、掃描、簽署、驗證和 Hotfix 程式的完整擁有權,以及控制容器映像中的二進位檔。 如需詳細資訊,請參閱 AKS 弱點管理和 AKS 支援涵蓋範圍。
建立啟動程序應用程式使用者的秘密
- 使用
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
使用
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 資源,以便根據您的監控堆疊進行量身打造。
使用
helm repo add命令新增 Prometheus Community Helm 存放庫。helm repo add prometheus-community \ https://prometheus-community.github.io/helm-charts升級 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為叢集建立 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 叢集部署指令清單中使用的叢集名稱相同。
使用
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)"使用
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.conf、pg_hba.conf 和 pg_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
使用
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 存取。 如果您保留此設定,請記錄團隊的安全影響,並儘可能偏好加密連線。
使用
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 入口網站來檢視計量。
選項 B - 受控 Grafana
或者,部署 Postgres 叢集和 Pod 監視器之後,您可以在部署指令碼所建立的受控 Grafana 執行個體上建立計量儀表板,以視覺化匯出至 Azure 監視器工作區的計量。 您可以透過 Azure 入口網站存取管理的 Grafana。 瀏覽至部署指令碼所建立的受控 Grafana 執行個體,並選取 [端點] 連結,如下所示:
選取 [端點] 鏈接會開啟新的瀏覽器視窗,您可以在 Managed Grafana 實例上建立儀錶板。 依照指示設定 Azure 監視器資料來源,然後您可以新增視覺效果,以利從 Postgres 叢集建立計量的儀表板。 設定數據源聯機之後,從主功能表選取 [數據源] 選項。 您應該會看到資料源連線的一組數據源選項,如下所示:
在 [Managed Prometheus] 選項上,選取建置儀錶板以開啟儀錶板編輯器的選項。 編輯器視窗開啟之後,選取 [新增視覺化] 選項,然後選取 [受管 Prometheus] 選項,以瀏覽 Postgres 叢集中的指標。 選取您要視覺化的計量之後,請選取 [執行查詢] 按鈕以擷取視覺效果的資料,如下所示:
選取 [儲存] 圖示,將面板新增至儀錶板。 您可以選取儀錶板編輯器中的 [新增] 按鈕,並重複此程式以可視化其他計量來新增其他面板。 新增計量視覺效果時,您應該會有如下所示的內容:
選取 [儲存] 圖示以儲存儀錶板。
後續步驟
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 審查本文件的早期草稿並提供技術改進。