本指南介绍了如何使用 CloudNativePG 操作器在 Google Kubernetes Engine (GKE) 上部署 PostgreSQL 集群。
PostgreSQL 是一种开源对象关系型数据库,经过了数十年的积极开发,可确保稳定的客户端性能。它提供一系列功能,包括复制、时间点恢复、安全功能和扩展性。PostgreSQL 与主要操作系统兼容,并完全符合 ACID(原子性、一致性、隔离性、耐用性)标准。
本指南适用于有意在 GKE 上部署 Postgres 集群的平台管理员、云架构师和运营专家。在 GKE 中运行 Postgres(而不是使用 Cloud SQL)可以为经验丰富的数据库管理员提供更多灵活性和配置控制。
优势
CloudNativePG 是由 EBD 根据 Apache 2 许可开发的开源操作器。它为 PostgreSQL 部署引入了以下功能:
- 用于管理和配置 PostgreSQL 集群的声明式 Kubernetes 原生方法
- 使用卷快照或 Cloud Storage 进行备份管理
- 在传输过程中加密的 TLS 连接,能够使用自己的证书授权机构以及与 Certificate Manager 的集成来自动颁发和轮替 TLS 证书
- 次要 PostgreSQL 版本的滚动更新
- 使用 Kubernetes API 服务器维护 PostgreSQL 集群状态和故障切换以实现高可用性,无需其他工具
- 通过以 SQL 编写的用户定义的指标实现内置 Prometheus 导出器配置
设置环境
如需设置您的环境,请按以下步骤操作:
- 设置环境变量: - 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 集群。
您可以使用 Standard 或 Autopilot 集群安装操作器。
标准
下图显示了部署在三个不同可用区中的专用区域级 Standard 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 节点的 VPC 网络和专用子网
- 用于通过 NAT 访问互联网的路由器
- 专用 GKE 集群(在 us-central1区域中)
- 启用了自动扩缩的节点池(每个可用区一个到两个节点,每个可用区最少一个节点)
输出类似于以下内容:
...
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 节点的 VPC 网络和专用子网
- 用于通过 NAT 访问互联网的路由器
- 专用 GKE 集群(在 us-central1区域中)
- 具有日志记录和监控权限的 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 --location ${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 资源
- 包含用户凭证的 Secret,用于访问数据库以及在 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-clientPod 上运行- exec命令并登录- gke-pg-cluster-rwService:- 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-rwService 登录数据库以建立具有读写权限的连接:- 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-roService 登录数据库以验证只读权限。此 Service 允许查询数据,但限制任何写入操作:- 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 控制台中,前往 Metrics Explorer 页面: - 信息中心显示非零指标提取率。 
- 在选择一个指标中,输入 Prometheus Target(Prometheus 目标)。 
- 在活跃指标类别部分中,选择 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