本指南說明如何使用 CloudNativePG 運算子,在 Google Kubernetes Engine (GKE) 上部署 PostgreSQL 叢集。
PostgreSQL 是開放原始碼的物件關聯式資料庫,經過數十年的積極開發,可確保用戶端效能穩定。這項服務提供多種功能,包括複製、時間點復原、安全防護功能和擴充性。PostgreSQL 與主要作業系統相容,且完全符合 ACID (不可分割性、一致性、隔離性、耐用性) 標準。
本指南適用於有興趣在 GKE 上部署 Postgres 叢集的平台管理員、雲端架構師和營運專員。與使用 Cloud SQL 相比,在 GKE 中執行 Postgres 可為經驗豐富的資料庫管理員提供更多彈性和設定控制權。
優點
CloudNativePG 是由 EDB 根據 Apache 2 授權開發的開放原始碼運算子。為 PostgreSQL 部署作業帶來下列功能:
- 以 Kubernetes 原生的宣告式方式管理及設定 PostgreSQL 叢集
- 使用磁碟區快照或 Cloud Storage 管理備份
- 傳輸中加密 TLS 連線、使用自有憑證授權單位,以及與 Certificate Manager 整合,自動核發及輪替 TLS 憑證
- PostgreSQL 次要版本更新
- 使用 Kubernetes API 伺服器維護 PostgreSQL 叢集狀態和容錯移轉,以提供高可用性,不需額外工具
- 透過以 SQL 編寫的使用者定義指標,內建 Prometheus 匯出工具設定
目標
- 規劃及部署 Postgres 適用的 GKE 基礎架構
- 使用 Helm 部署及設定 CloudNativePG Postgres 運算子
- 部署 PostgreSQL 叢集
- 設定 PostgreSQL 驗證和可觀測性
部署架構
PostgreSQL 提供多種部署選項,從獨立資料庫伺服器到複寫的高可用性叢集都有。本教學課程的重點是將高可用性叢集部署至 GKE。
在這個部署作業中,PostgreSQL 叢集工作負載會分散在地區性 GKE 叢集內的多個可用區,確保高可用性和備援能力。詳情請參閱區域叢集。
下圖顯示在 GKE 叢集的多個節點和區域中執行的 Postgres 叢集:
預設設定包含一個主要 PostgreSQL 伺服器和兩個備份伺服器,一旦主要伺服器發生故障,備份伺服器就會接管,確保資料庫持續可用。
CloudNativePG 運算子資源會使用 GKE 叢集的獨立命名空間,以利資源隔離,並採用建議的微服務方法,也就是每個 PostgreSQL 叢集使用一個資料庫。資料庫和對應的使用者 (應用程式使用者) 會在代表叢集的 Kubernetes 自訂資源中定義。
討論資料庫時,儲存空間是不可或缺的元件。儲存空間必須有效率地運作、確保持續可用性,並保證資料一致性。因此,我們建議使用以 SSD 磁碟為基礎的
premium-rwo
儲存空間類別。設定 PostgreSQL 叢集的 Pod 時,CloudNativePG 運算子會視需要自動建立PersistentVolumeClaims
。
費用
在本文件中,您會使用 Google Cloud的下列計費元件:
如要根據預測用量估算費用,請使用 Pricing Calculator。
完成本文所述工作後,您可以刪除已建立的資源,避免繼續計費。詳情請參閱清除所用資源一節。
事前準備
Cloud Shell 已預先安裝本教學課程所需的軟體,包括 kubectl
、gcloud CLI、Helm 和 Terraform。如果您未使用 Cloud Shell,則必須安裝 gcloud CLI。
- Sign in to your Google Cloud account. If you're new to Google Cloud, create an account to evaluate how our products perform in real-world scenarios. New customers also get $300 in free credits to run, test, and deploy workloads.
-
Install the Google Cloud CLI.
-
If you're using an external identity provider (IdP), you must first sign in to the gcloud CLI with your federated identity.
-
To initialize the gcloud CLI, run the following command:
gcloud init
-
Create or select a Google Cloud project.
-
Create a Google Cloud project:
gcloud projects create PROJECT_ID
Replace
PROJECT_ID
with a name for the Google Cloud project you are creating. -
Select the Google Cloud project that you created:
gcloud config set project PROJECT_ID
Replace
PROJECT_ID
with your Google Cloud project name.
-
-
Make sure that billing is enabled for your Google Cloud project.
-
Enable the Compute Engine, IAM, GKE, Resource Manager APIs:
gcloud services enable compute.googleapis.com
iam.googleapis.com container.googleapis.com cloudresourcemanager.googleapis.com -
Install the Google Cloud CLI.
-
If you're using an external identity provider (IdP), you must first sign in to the gcloud CLI with your federated identity.
-
To initialize the gcloud CLI, run the following command:
gcloud init
-
Create or select a Google Cloud project.
-
Create a Google Cloud project:
gcloud projects create PROJECT_ID
Replace
PROJECT_ID
with a name for the Google Cloud project you are creating. -
Select the Google Cloud project that you created:
gcloud config set project PROJECT_ID
Replace
PROJECT_ID
with your Google Cloud project name.
-
-
Make sure that billing is enabled for your Google Cloud project.
-
Enable the Compute Engine, IAM, GKE, Resource Manager APIs:
gcloud services enable compute.googleapis.com
iam.googleapis.com container.googleapis.com cloudresourcemanager.googleapis.com -
Grant roles to your user account. Run the following command once for each of the following IAM roles:
roles/compute.securityAdmin, roles/compute.viewer, roles/container.clusterAdmin, roles/container.admin, roles/iam.serviceAccountAdmin, roles/iam.serviceAccountUser
gcloud projects add-iam-policy-binding PROJECT_ID --member="user:USER_IDENTIFIER" --role=ROLE
- Replace
PROJECT_ID
with your project ID. -
Replace
USER_IDENTIFIER
with the identifier for your user account. For example,user:myemail@example.com
. - Replace
ROLE
with each individual role.
- Replace
設定環境
如要設定環境,請按照下列步驟操作:
設定環境變數:
export PROJECT_ID=PROJECT_ID export KUBERNETES_CLUSTER_PREFIX=postgres export REGION=us-central1
將
PROJECT_ID
替換為您的 Google Cloud 專案 ID。複製 GitHub 存放區:
git clone https://github.com/GoogleCloudPlatform/kubernetes-engine-samples
變更為工作目錄:
cd kubernetes-engine-samples/databases/postgresql-cloudnativepg
建立叢集基礎架構
在本節中,您將執行 Terraform 指令碼,建立高可用性的私人地區 GKE 叢集。
您可以使用標準或 Autopilot 叢集安裝運算子。
標準
下圖顯示部署在三個不同可用區的私有區域標準 GKE 叢集:
如要部署這項基礎架構,請執行下列指令:
export GOOGLE_OAUTH_ACCESS_TOKEN=$(gcloud auth print-access-token)
terraform -chdir=terraform/gke-standard init
terraform -chdir=terraform/gke-standard apply \
-var project_id=${PROJECT_ID} \
-var region=${REGION} \
-var cluster_prefix=${KUBERNETES_CLUSTER_PREFIX}
系統顯示提示訊息時,請輸入 yes
。這個指令可能需要幾分鐘才能完成,且叢集會顯示就緒狀態。
Terraform 會建立下列資源:
- Kubernetes 節點的虛擬私有雲網路和私有子網路
- 透過 NAT 存取網際網路的路由器
us-central1
地區中的私人 GKE 叢集- 啟用自動調度的節點集區 (每個可用區一到兩個節點,每個可用區至少一個節點)
輸出結果會與下列內容相似:
...
Apply complete! Resources: 14 added, 0 changed, 0 destroyed.
...
Autopilot
下圖顯示私人區域 Autopilot GKE 叢集:
如要部署基礎架構,請執行下列指令:
export GOOGLE_OAUTH_ACCESS_TOKEN=$(gcloud auth print-access-token)
terraform -chdir=terraform/gke-autopilot init
terraform -chdir=terraform/gke-autopilot apply \
-var project_id=${PROJECT_ID} \
-var region=${REGION} \
-var cluster_prefix=${KUBERNETES_CLUSTER_PREFIX}
系統顯示提示訊息時,請輸入 yes
。這個指令可能需要幾分鐘才能完成,且叢集會顯示就緒狀態。
Terraform 會建立下列資源:
- Kubernetes 節點的虛擬私有雲網路和私有子網路
- 透過 NAT 存取網際網路的路由器
us-central1
地區中的私人 GKE 叢集- 具備記錄與監控權限的
ServiceAccount
- 使用 Google Cloud Managed Service for Prometheus 監控叢集
輸出結果會與下列內容相似:
...
Apply complete! Resources: 12 added, 0 changed, 0 destroyed.
...
連線至叢集
設定 kubectl
與叢集通訊:
gcloud container clusters get-credentials ${KUBERNETES_CLUSTER_PREFIX}-cluster --region ${REGION}
部署 CloudNativePG 運算子
使用 Helm 資訊套件將 CloudNativePG 部署至 Kubernetes 叢集:
新增 CloudNativePG 運算子 Helm 資訊套件存放區:
helm repo add cnpg https://cloudnative-pg.github.io/charts
使用 Helm 指令列工具部署 CloudNativePG 運算子:
helm upgrade --install cnpg \ --namespace cnpg-system \ --create-namespace \ cnpg/cloudnative-pg
輸出結果會與下列內容相似:
Release "cnpg" does not exist. Installing it now. NAME: cnpg LAST DEPLOYED: Fri Oct 13 13:52:36 2023 NAMESPACE: cnpg-system STATUS: deployed REVISION: 1 TEST SUITE: None ...
部署 Postgres
下列資訊清單說明 CloudNativePG 運算子的自訂資源所定義的 PostgreSQL 叢集:
這個資訊清單包含下列欄位:
spec.instances
:叢集 Pod 數量spec.primaryUpdateStrategy
:滾動式更新策略:Unsupervised
:在副本節點更新後,自動更新主要叢集節點Supervised
:主要叢集節點必須手動切換
spec.postgresql
:postgres.conf
檔案參數覆寫,例如 pg-hba 規則、LDAP,以及同步複本的必要條件。spec.storage
:儲存空間相關設定,例如儲存空間類別、磁碟區大小和預先寫入記錄設定。spec.bootstrap
:叢集中建立的初始資料庫參數、使用者憑證和資料庫還原選項spec.resources
:叢集 Pod 的要求和限制spec.affinity
:叢集工作負載的相依性和反相依性規則
建立基本 Postgres 叢集
建立命名空間:
kubectl create ns pg-ns
使用自訂資源建立 PostgreSQL 叢集:
kubectl apply -n pg-ns -f manifests/01-basic-cluster/postgreSQL_cluster.yaml
這個指令可能需要幾分鐘才能完成。
檢查叢集的狀態:
kubectl get cluster -n pg-ns --watch
請等待輸出內容顯示
Cluster in healthy state
狀態,再繼續下一個步驟。NAME AGE INSTANCES READY STATUS PRIMARY gke-pg-cluster 2m53s 3 3 Cluster in healthy state gke-pg-cluster-1
檢查資源
確認 GKE 已為叢集建立資源:
kubectl get cluster,pod,svc,pvc,pdb,secret,cm -n pg-ns
輸出結果會與下列內容相似:
NAME AGE INSTANCES READY STATUS PRIMARY
cluster.postgresql.cnpg.io/gke-pg-cluster 32m 3 3 Cluster in healthy state gke-pg-cluster-1
NAME READY STATUS RESTARTS AGE
pod/gke-pg-cluster-1 1/1 Running 0 31m
pod/gke-pg-cluster-2 1/1 Running 0 30m
pod/gke-pg-cluster-3 1/1 Running 0 29m
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/gke-pg-cluster-r ClusterIP 10.52.11.24 <none> 5432/TCP 32m
service/gke-pg-cluster-ro ClusterIP 10.52.9.233 <none> 5432/TCP 32m
service/gke-pg-cluster-rw ClusterIP 10.52.1.135 <none> 5432/TCP 32m
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
persistentvolumeclaim/gke-pg-cluster-1 Bound pvc-bbdd1cdd-bdd9-4e7c-8f8c-1a14a87e5329 2Gi RWO standard 32m
persistentvolumeclaim/gke-pg-cluster-2 Bound pvc-e7a8b4df-6a3e-43ce-beb0-b54ec1d24011 2Gi RWO standard 31m
persistentvolumeclaim/gke-pg-cluster-3 Bound pvc-dac7f931-6ac5-425f-ac61-0cfc55aae72f 2Gi RWO standard 30m
NAME MIN AVAILABLE MAX UNAVAILABLE ALLOWED DISRUPTIONS AGE
poddisruptionbudget.policy/gke-pg-cluster 1 N/A 1 32m
poddisruptionbudget.policy/gke-pg-cluster-primary 1 N/A 0 32m
NAME TYPE DATA AGE
secret/gke-pg-cluster-app kubernetes.io/basic-auth 3 32m
secret/gke-pg-cluster-ca Opaque 2 32m
secret/gke-pg-cluster-replication kubernetes.io/tls 2 32m
secret/gke-pg-cluster-server kubernetes.io/tls 2 32m
secret/gke-pg-cluster-superuser kubernetes.io/basic-auth 3 32m
NAME DATA AGE
configmap/cnpg-default-monitoring 1 32m
configmap/kube-root-ca.crt 1 135m
運算子會建立下列資源:
- 代表 PostgreSQL 叢集的叢集自訂資源,由運算子控管
- 具有對應永久磁碟區的 PersistentVolumeClaim 資源
- 密鑰,內含存取資料庫和 Postgres 節點間複寫作業的使用者憑證。
- 三個資料庫端點服務:
<name>-rw
、<name>-ro
和<name>-r
,可連線至叢集。詳情請參閱 PostgreSQL 架構。
向 Postgres 進行驗證
您可以連線至 PostgreSQL 資料庫,並透過運算子建立的不同服務端點檢查存取權。為此,您會使用額外的 Pod,其中包含 PostgreSQL 用戶端,以及以環境變數形式掛接的同步應用程式使用者憑證。
執行用戶端 Pod,與 Postgres 叢集互動:
kubectl apply -n pg-ns -f manifests/02-auth/pg-client.yaml
在
pg-client
Pod 上執行exec
指令,並登入gke-pg-cluster-rw
服務:kubectl wait --for=condition=Ready -n pg-ns pod/pg-client --timeout=300s kubectl exec -n pg-ns -i -t pg-client -- /bin/sh
使用
gke-pg-cluster-rw
服務登入資料庫,建立具有讀寫權限的連線:psql postgresql://$CLIENTUSERNAME:$CLIENTPASSWORD@gke-pg-cluster-rw.pg-ns/app
終端機開頭會顯示資料庫名稱:
app=>
建立資料表:
CREATE TABLE travel_agency_clients ( client VARCHAR ( 50 ) UNIQUE NOT NULL, address VARCHAR ( 50 ) UNIQUE NOT NULL, phone VARCHAR ( 50 ) UNIQUE NOT NULL);
將資料插入資料表:
INSERT INTO travel_agency_clients(client, address, phone) VALUES ('Tom', 'Warsaw', '+55555') RETURNING *;
查看您建立的資料:
SELECT * FROM travel_agency_clients ;
輸出結果會與下列內容相似:
client | address | phone --------+---------+--------- Tom | Warsaw | +55555 (1 row)
登出目前的資料庫工作階段:
exit
使用
gke-pg-cluster-ro
服務登入資料庫,確認唯讀存取權。這項服務允許查詢資料,但限制任何寫入作業:psql postgresql://$CLIENTUSERNAME:$CLIENTPASSWORD@gke-pg-cluster-ro.pg-ns/app
嘗試插入新資料:
INSERT INTO travel_agency_clients(client, address, phone) VALUES ('John', 'Paris', '+55555') RETURNING *;
輸出結果會與下列內容相似:
ERROR: cannot execute INSERT in a read-only transaction
嘗試讀取資料:
SELECT * FROM travel_agency_clients ;
輸出結果會與下列內容相似:
client | address | phone --------+---------+--------- Tom | Warsaw | +55555 (1 row)
登出目前的資料庫工作階段:
exit
退出 Pod shell:
exit
瞭解 Prometheus 如何收集 Postgres 叢集的指標
下圖顯示 Prometheus 指標的收集方式:
在圖表中,GKE 私人叢集包含:
- Postgres Pod,會收集路徑
/
和通訊埠9187
的指標 - 以 Prometheus 為基礎的收集器,可處理來自 Postgres Pod 的指標
- 將指標傳送至 Cloud Monitoring 的
PodMonitoring
資源
如要啟用從 Pod 收集指標的功能,請按照下列步驟操作:
建立
PodMonitoring
資源:kubectl apply -f manifests/03-observability/pod-monitoring.yaml -n pg-ns
前往 Google Cloud 控制台的「指標探索器」頁面:
資訊主頁顯示的指標擷取率不是零。
在「Select a metric」(選取指標) 中,輸入「Prometheus Target」(Prometheus 目標)。
在「Active Metric Categories」(使用中的指標類別) 專區中,選取「Cnpg」。
建立指標資訊主頁
如要將匯出的指標視覺化,請建立指標資訊主頁。
部署資訊主頁:
gcloud --project "${PROJECT_ID}" monitoring dashboards create --config-from-file manifests/03-observability/gcp-pg.json
前往 Google Cloud 控制台的「資訊主頁」頁面。
選取「PostgresQL Prometheus Overview」(PostgresQL Prometheus 總覽) 資訊主頁。
如要查看資訊主頁監控函式的方式,您可以重複使用「資料庫驗證」部分中的動作,並對資料庫套用讀取和寫入要求,然後在資訊主頁中查看收集到的指標視覺化資料。
連線至用戶端 Pod:
kubectl exec -n pg-ns -i -t pg-client -- /bin/sh
插入隨機資料:
psql postgresql://$CLIENTUSERNAME:$CLIENTPASSWORD@gke-pg-cluster-rw.pg-ns/app -c "CREATE TABLE test (id serial PRIMARY KEY, randomdata VARCHAR ( 50 ) NOT NULL);INSERT INTO test (randomdata) VALUES (generate_series(1, 1000));"
重新整理資訊主頁。圖表會更新為實際指標。
退出 Pod shell:
exit
清除所用資源
刪除專案
Delete a Google Cloud project:
gcloud projects delete PROJECT_ID
刪除個別資源
設定環境變數。
export PROJECT_ID=${PROJECT_ID} export KUBERNETES_CLUSTER_PREFIX=postgres export REGION=us-central1
執行
terraform destroy
指令:export GOOGLE_OAUTH_ACCESS_TOKEN=$(gcloud auth print-access-token) terraform -chdir=terraform/FOLDER destroy \ -var project_id=${PROJECT_ID} \ -var region=${REGION} \ -var cluster_prefix=${KUBERNETES_CLUSTER_PREFIX}
將
FOLDER
替換為gke-autopilot
或gke-standard
。系統顯示提示訊息時,請輸入
yes
。找出所有未連接的磁碟:
export disk_list=$(gcloud compute disks list --filter="-users:* AND labels.name=${KUBERNETES_CLUSTER_PREFIX}-cluster" --format "value[separator=|](name,zone)")
刪除磁碟:
for i in $disk_list; do disk_name=$(echo $i| cut -d'|' -f1) disk_zone=$(echo $i| cut -d'|' -f2|sed 's|.*/||') echo "Deleting $disk_name" gcloud compute disks delete $disk_name --zone $disk_zone --quiet done
後續步驟
- 探索 Google Cloud 的參考架構、圖表和最佳做法。 歡迎瀏覽我們的雲端架構中心。