2. Kubernetes Operator部署云原生数据库集群

Kubernetes Operator部署云原生数据库集群 学习卡片

Operator 部署三副本集群的核心对象与约束

本案例使用 CloudNativePG Operator 在 Kubernetes 上部署一个三副本 PostgreSQL 集群。Operator 通过自定义资源(CR)声明集群期望状态,由控制器自动创建 StatefulSet、Service、Secret 和 PVC,并持续调谐至就绪。部署前需要明确三类约束:存储类(StorageClass)决定 PVC 的供应方式与访问模式;资源限额(requests/limits)决定调度可行性与稳定性;反亲和性(podAntiAffinity)决定三个副本是否分散到不同节点。

声明层(用户提交) Cluster CR instances: 3 / storageClass / resources affinity 配置 podAntiAffinity: required Operator 控制层 Reconcile 调谐循环 创建 StatefulSet / Service 生成 Secret / PVC 模板 Kubernetes 资源 StatefulSet: cluster-1 Headless Service + RW Service Secret: app / superuser watch apply 三副本 Pod 分布与反亲和性约束 Node-1 (zone-a) cluster-1-0 Primary · 2C4G · 20Gi 不可再调度同标签 Pod (required 反亲和) Node-2 (zone-b) cluster-1-1 Standby · 2C4G · 20Gi 不可再调度同标签 Pod (required 反亲和) Node-3 (zone-c) cluster-1-2 Standby · 2C4G · 20Gi 不可再调度同标签 Pod (required 反亲和) WAL 流复制 WAL 流复制 就绪验证检查点 3/3 Pod Running kubectl get pods -l cnpg.io/cluster Cluster phase: Healthy kubectl get cluster 1 Primary + 2 Standby kubectl get pods -o wide PVC 全部 Bound kubectl get pvc

部署清单与关键字段

以下 Cluster CR 声明了三副本、存储类、资源限额和硬性反亲和性。字段值需与集群实际节点标签匹配,否则 Pod 会因无法满足反亲和而 Pending。

apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
  name: cluster-1
  namespace: db-prod
spec:
  instances: 3
  imageName: ghcr.io/cloudnative-pg/postgresql:16.3
  storage:
    size: 20Gi
    storageClass: csi-ssd-replicated
  resources:
    requests:
      cpu: "2"
      memory: "4Gi"
    limits:
      cpu: "2"
      memory: "4Gi"
  affinity:
    enablePodAntiAffinity: true
    topologyKey: kubernetes.io/hostname
    podAntiAffinityType: required
  postgresql:
    parameters:
      max_connections: "200"
      shared_buffers: "1GB"

部署与验证操作

  1. 确认存储类存在且支持 ReadWriteOnce:kubectl get storageclass csi-ssd-replicated。
  2. 确认节点带有 kubernetes.io/hostname 标签且至少 3 个可调度节点:kubectl get nodes -L kubernetes.io/hostname。
  3. 应用 CR:kubectl apply -f cluster-1.yaml。
  4. 观察 Pod 调度与就绪:kubectl get pods -n db-prod -l cnpg.io/cluster=cluster-1 -o wide -w。
  5. 检查集群阶段:kubectl get cluster cluster-1 -n db-prod,期望 phase: Cluster in healthy state。
  6. 确认 PVC 绑定:kubectl get pvc -n db-prod,三个 PVC 均应为 Bound。
  7. 确认主备角色:kubectl get pods -n db-prod -l cnpg.io/cluster=cluster-1 -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.metadata.labels.cnpg\.io/instanceRole}{"\n"}{end}',应输出 1 个 primary 和 2 个 replica。
若 Pod 长时间 Pending,优先检查:节点数是否少于 3、节点标签是否与 topologyKey 一致、资源 requests 是否超过节点可分配量、StorageClass 是否支持动态供应。反亲和类型为 required 时,任一条件不满足都会导致调度失败。
资源 limits 与 requests 设为相等可避免 CPU 节流和内存超卖导致的 OOMKill;生产环境不建议将 limits 设得远高于 requests,否则节点资源核算会失真。

结果判读与常见异常

观察项期望结果异常含义
Pod 数量与状态3 个 Running,且分布在 3 个不同节点少于 3 个或集中在同节点 → 反亲和未生效或节点不足
Cluster phaseCluster in healthy stateUnhealthy / Setting up → 副本未完成流复制或探针未通过
PVC 状态3 个 BoundPending → StorageClass 供应失败或容量不足
实例角色1 primary + 2 replica多 primary → 脑裂或 Operator 选主异常