跳转到内容

PostgreSQL on Kubernetes 面试题

30 道题
分类
数据库
题目数
30 道
已阅读 0 / 30 题
1 PostgreSQL on Kubernetes 的 Operator 生态总览

答案:

PostgreSQL on Kubernetes 由四款主流 Operator 构成生态,分别代表不同的架构理念与设计哲学。

Operator维护方GitHub Stars核心架构许可证
CloudNativePGEDB10k+Kubernetes Native OperatorApache 2.0
StackGresOnGres2k+All-in-One 平台AGPL v3
Zalando Postgres OperatorZalando5k+Spilo + Patroni + etcdMIT
Crunchy Data PGOCrunchy Data4k+Kubernetes Native OperatorApache 2.0

设计哲学对比:

graph TD
    subgraph CloudNativePG
        A1["纯 Kubernetes 原生设计"]
        A2["无外部依赖(无 Patroni/etcd)"]
        A3["Instance Manager 直接管理 PG"]
        A4["PVC 直接挂载,无 Operator 层"]
    end
    subgraph Zalando
        B1["Spilo 镜像封装 Patroni"]
        B2["依赖 etcd 作为 DCS"]
        B3["成熟的 HA 方案(Patroni)"]
        B4["需要 Operator + ConfigMap"]
    end

选型依据:

场景推荐 Operator
纯 Kubernetes 环境,追求原生体验CloudNativePG
需要完整平台体验(连接池 / 备份 / 监控一体化)StackGres
已有 etcd 基础设施,偏好 Patroni HAZalando
Red Hat OpenShift 环境Crunchy Data PGO
最小外部依赖,快速部署CloudNativePG
2 CloudNativePG 的架构与核心设计理念

答案:

CloudNativePG 以 Kubernetes 原生资源模型管理 PostgreSQL 集群,摒弃传统 DBA 工具链的外部依赖,将 PostgreSQL 生命周期完全融入 Kubernetes 控制循环。

核心架构:

graph TD
    K8sAPI["Kubernetes API Server"]
    K8sAPI -->|"Watch"| Controller["CloudNativePG Controller Manager"]
    Controller --> ClusterCtl["Cluster Controller"]
    Controller --> BackupCtl["Backup Controller"]
    Controller --> ScheduledCtl["ScheduledBackup Controller"]
    Controller -->|"管理"| PGPod["PostgreSQL Pod"]
    PGPod --> IM["Instance Manager"]
    IM --> Lifecycle["Lifecycle Manager"]
    IM --> WAL["WAL Archiver"]
    IM --> BackupMgr["Backup Manager"]
    PGPod --> PGEngine["PostgreSQL 16/17(Primary/Standby)"]
    PGPod --> PVC["~~~ PVC(PGDATA + WAL)~~~"]

设计理念:

原则说明
No External Dependencies不依赖 Patroni / etcd / Stolon,Operator 直接管理 PostgreSQL 进程
Instance Manager每个 Pod 内运行 sidecar 进程,负责生命周期、WAL 归档、备份
Declarative State通过 Cluster CRD 声明期望状态,Controller 驱动调和
PVC SeparationPGDATA 和 WAL 分别挂载独立 PVC,实现 I/O 隔离
Native Kubernetes RBAC通过 ServiceAccount 管理云存储凭证,不依赖 Secret 硬编码
Immutable Infrastructure配置变更通过 Pod 重建实现,遵循不可变基础设施原则

Instance Manager 职责:

Instance Manager 是每个 PostgreSQL Pod 中的关键组件,负责:PostgreSQL 进程生命周期管理(启动 / 停止 / 信号处理)、WAL 归档到 S3/GCS/Azure Blob、Streaming Replication 主备切换、备份调度与执行、Prometheus 指标暴露。

3 CloudNativePG 的 Cluster CRD 详解

答案:

Cluster CRD 是 CloudNativePG 的核心资源,完整定义 PostgreSQL 集群的拓扑、配置、存储、备份策略。

apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
  name: pg-production
spec:
  # 实例数量 (Primary + Standby)
  instances: 3

  # PostgreSQL 镜像与版本
  imageName: ghcr.io/cloudnative-pg/postgresql:16.4

  # Primary Pod 调度策略
  primaryUpdateStrategy: unsupervised

  # 存储配置
  storage:
    size: 100Gi
    storageClass: premium-rwo

  # WAL 独立存储
  walStorage:
    size: 20Gi
    storageClass: premium-rwo

  # PostgreSQL 参数
  postgresql:
    parameters:
      shared_buffers: "4GB"
      max_connections: "500"
      pg_stat_statements.max: "10000"
      log_min_duration_statement: "1s"

  # 用于初始化数据库的引用
  bootstrap:
    initdb:
      database: appdb
      owner: appuser
      secret:
        name: pg-credentials

  # 监控
  monitoring:
    enablePodMonitor: true

  # 备份
  backup:
    barmanObjectStore:
      destinationPath: s3://pg-backups/production
      endpointURL: https://s3.cn-north-1.amazonaws.com.cn
      s3Credentials:
        accessKeyId:
          name: s3-credentials
          key: access_key_id
        secretAccessKey:
          name: s3-credentials
          key: secret_access_key
      wal:
        compression: gzip
        encryption: AES256
      retentionPolicy: "30d"

关键字段说明:

字段说明建议值
instances期望的实例总数生产环境 >= 3
primaryUpdateStrategyPrimary 切换策略unsupervised(推荐)/ supervised
storage.sizePGDATA 卷大小根据数据量预估 + 30% 余量
walStorage.sizeWAL 卷大小max_wal_size * 3 计算
bootstrap初始化数据源initdb / recovery / pg_basebackup
postgresql.parametersPostgreSQL 配置参数映射 postgresql.conf
backup.barmanObjectStore备份目标配置兼容 Barman Cloud 的对象存储
enableSuperuserAccess是否启用 superuser生产环境设为 false
logLevelPostgreSQL 日志级别默认 info,调试用 debug5
affinityPod 亲和性 / 反亲和性强制跨节点 / 跨可用区分布
4 CloudNativePG 的 WAL 归档与 Point-In-Time Recovery

答案:

CloudNativePG 的 Instance Manager 持续将 WAL 段归档到对象存储,支持基于时间点或 WAL 位置的 PITR 恢复。

WAL 归档流程:

sequenceDiagram
    participant PG as PostgreSQL Process
    participant IM as Instance Manager
    participant OS as Object Storage

    PG->>PG: 生成 WAL 段(16MB default)
    PG->>IM: archive_command
    IM->>IM: 压缩 + 加密
    IM->>OS: 上传 WAL 段
    OS-->>IM: 确认写入
    IM-->>PG: 归档成功
    Note over PG,OS: .partial WAL(每 5min 或达到 10MB 时)
    PG->>IM: partial upload
    IM->>OS: 上传 .partial

PITR 恢复配置:

apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
  name: pg-restored
spec:
  instances: 3
  storage:
    size: 100Gi

  bootstrap:
    recovery:
      source: pg-production-backup-20250801
      # 恢复到指定时间点
      recoveryTarget:
        targetTime: "2025-08-01T14:30:00+08:00"
        # 或在恢复后自动提升为 Primary
        exclusive: false

      # 也可以恢复到指定事务
      # recoveryTarget:
      #   targetXID: "12345678"

  externalClusters:
    - name: pg-production-backup-20250801
      barmanObjectStore:
        destinationPath: s3://pg-backups/production
        endpointURL: https://s3.cn-north-1.amazonaws.com.cn
        s3Credentials:
          accessKeyId:
            name: s3-credentials
            key: access_key_id
          secretAccessKey:
            name: s3-credentials
            key: secret_access_key

WAL 归档关键参数:

参数说明生产建议
wal.compressionWAL 段压缩算法gzip(兼顾速度与比例)
wal.encryptionWAL 段加密算法AES256
wal.maxParallel并发上传线程数4
wal.encryptionPassphrase加密密钥的 Secret 引用独立 Secret
retentionPolicy备份保留策略30d"COUNT 7"

PITR 执行时机:

  • 人为误操作数据(DROP TABLE / DELETE 无 WHERE / UPDATE 错误)
  • 重大版本升级前的回滚保障
  • 数据一致性校验失败
  • 灾难恢复演练
5 CloudNativePG 的 Backup CRD 与 S3/GCS 备份

答案:

CloudNativePG 通过 Backup CRD 和 ScheduledBackup CRD 管理全量备份,底层基于 Barman Cloud 实现,支持 S3 / GCS / Azure Blob Storage。

Backup CRD 定义:

apiVersion: postgresql.cnpg.io/v1
kind: Backup
metadata:
  name: pg-manual-backup-20250801
spec:
  cluster:
    name: pg-production
  # 备份方法:barmanObjectStore 或 volumeSnapshot
  method: barmanObjectStore
  # barmanObjectStore 配置继承自 Cluster CRD

ScheduledBackup CRD:

apiVersion: postgresql.cnpg.io/v1
kind: ScheduledBackup
metadata:
  name: pg-daily-backup
spec:
  # Cron 表达式
  schedule: "0 2 * * *"
  # 是否立即执行一次
  immediate: true
  # 挂起调度
  suspend: false
  cluster:
    name: pg-production
  # 备份保留策略(覆盖 Cluster 级别设置)
  backupOwnerReference: self

备份存储后端配置矩阵:

# S3 兼容存储
s3Credentials:
  accessKeyId:
    name: s3-credentials
    key: access_key_id
  secretAccessKey:
    name: s3-credentials
    key: secret_access_key
  region:
    name: s3-credentials
    key: region
# Google Cloud Storage
googleCredentials:
  applicationCredentials:
    name: gcs-credentials
    key: credentials.json
# Azure Blob Storage
azureCredentials:
  connectionString:
    name: azure-credentials
    key: connection_string
  storageAccount:
    name: azure-credentials
    key: storage_account

备份方法对比:

方法原理适用场景恢复方式
barmanObjectStorepg_basebackup 的热备上传到对象存储常规生产备份PITR 恢复(支持时间点)
volumeSnapshot基于 CSI 快照K8s 同集群快速恢复快照克隆(不支持 PITR)

备份验证策略:

验证方法说明
自动验证Operator 验证备份文件完整性与可恢复性
定期恢复演练通过 bootstrap.recovery 从备份创建新集群
备份监控Prometheus 指标 cnpg_backup_status 监控备份成功率
6 CloudNativePG 的自动故障转移与 Leader 选举

答案:

CloudNativePG 不依赖 Patroni 或 etcd,直接在 Operator 层与 Instance Manager 之间协同完成故障检测与 Leader 切换。

故障检测与切换流程:

时间线:T+0s ~ T+50s

Operator (Controller)              Instance Manager (Primary Pod)     Standby Pods
       │                                       │                          │
  T+0  │  Liveness Probe 探测 Primary           │                          │
       │───────────────────────────────────────►│                          │
       │◄─────────── 无响应 ────────────────────│                          │
       │                                       │                          │
  T+5  │  确认 Primary 不健康                    │                          │
       │                                       │                          │
  T+10 │  查询 Standby 复制状态                  │                          │
       │────────────────────────────────────────────────────────────────►│
       │◄─── LSN 位置 + 复制延迟 ─────────────────────────────────────────│
       │                                       │                          │
  T+15 │  选择 LSN 最超前的 Standby              │                          │
       │                                       │                          │
  T+20 │  发起 pg_ctl promote ───────────────────────────────────────────►│
       │                                       │              Promote     │
  T+25 │  更新 Pod Label                         │                          │
       │  role: primary → standby                │                          │
       │  role: standby → primary                │              role:      │
       │                                       │              primary     │
  T+30 │  更新 Service Endpoint                  │                          │
       │  -rw → 新 Primary                       │                          │
       │                                       │                          │
  T+35 │  其他 Standby 重新连接新 Primary          │                          │
       │────────────────────────────────────────────────────────────────►│
       │                                       │◄── streaming repl ────────│
  T+40 │  旧 Primary 重启为 Standby               │                          │
       │                                       │                          │
  T+50 │  集群恢复完整状态                         │                          │

选举策略:

策略说明
Best-Effort 切换选择 LSN 最高、延迟最小的 Standby
同步复制优先级优先选择 synchronous_standby_names 中的 Standby
Failover 限制failoverDelay 控制两次切换的最小间隔
PrimaryUpdateStrategyunsupervised:自动切换;supervised:需手动确认

不可用时间的控制参数:

参数说明默认值
startDelay启动延迟等待3600s
stopDelaySmart Shutdown 超时1800s
smartStopTimeoutFast Shutdown 前等待
failoverDelay两次 Failover 最小间隔0s
switchoverDelay计划内切换后允许下次切换的延迟0s
replicationSlots.highAvailability.enabled启用高可用复制槽true

Readiness Probe 与 Liveness Probe 策略:

spec:
  postgresql:
    parameters:
      # Liveness: 检查 PG 进程是否存活
      # Readiness: 检查 PG 是否接受连接
      # 生产环境建议在 init 阶段放宽探针
      pg_ctl_timeout: "3600"
7 CloudNativePG 的 Read-Only Replica 扩展

答案:

CloudNativePG 基于 PostgreSQL Physical Streaming Replication 实现只读副本,通过 Service 自动路由读写分离流量。

读写分离架构:

graph TD
    subgraph K8s["Kubernetes Service"]
        RW["pg-cluster-rw<br/>(读写 Service)<br/>--> Primary Pod"]
        RO["pg-cluster-ro<br/>(只读 Service)<br/>--> Standby Pods"]
    end
    
    RW -->|"路由"| Primary["Primary<br/>(Read/Write)"]
    RO -->|"路由"| Standby["Standby-1 / Standby-2<br/>(Read-Only)"]
    
    Primary -->|"Streaming Replication"| Standby

Service 自动生成规则:

Service 名称类型路由目标
<cluster>-rwClusterIPPrimary Pod(标签 role=primary
<cluster>-roClusterIPStandby Pods(标签 role=replica
<cluster>-rClusterIP所有 Pod(Primary + Standby)
<cluster>-anyClusterIP任意 Pod

扩缩容操作:

# 从 3 实例扩展至 5 实例
kubectl patch cluster pg-production \
  --type merge -p '{"spec":{"instances":5}}'

# 查看实例状态
kubectl get cluster pg-production -o jsonpath='{.status.instancesStatus}'
# Cluster CRD 扩缩容配置
spec:
  instances: 5  # 从 3 修改为 5

  # 控制 Rolling Update 期间不可用实例上限
  maxParallelWalSender: 4

复制延迟控制:

参数说明建议值
max_slot_wal_keep_size复制槽可保留的 WAL 最大值-1(直至磁盘满)
wal_keep_size为 Standby 保留的 WAL 最小值0(改用 replication slot)
hot_standby_feedbackStandby 反馈长事务信息on
max_standby_streaming_delayStandby 允许的最大复制延迟30s

双服务读写分离应用接入:

# 应用配置示例
spring:
  datasource:
    write:
      url: jdbc:postgresql://pg-production-rw:5432/appdb
    read:
      url: jdbc:postgresql://pg-production-ro:5432/appdb
8 CloudNativePG 的 Rolling Update 与在线升级

答案:

CloudNativePG 通过 Rolling Update 策略实现 PostgreSQL 的在线升级,确保更新过程中始终有 Primary 实例接受写入请求。

Rolling Update 流程:

graph LR
    subgraph S1["Step 1: 升级 Standby(C)"]
        PA1["Primary(A)<br/>v16.2"]
        SB1["Standby(B)<br/>v16.2"]
        SC1["Standby(C)<br/>v16.4 (升级)"]
    end
    
    subgraph S2["Step 2: 升级 Standby(B)"]
        PA2["Primary(A)<br/>v16.2"]
        SB2["Standby(B)<br/>v16.4 (升级)"]
        SC2["Standby(C)<br/>v16.4"]
    end
    
    subgraph S3["Step 3: Switchover"]
        SA3["Standby(A)<br/>v16.2 (降级)"]
        PB3["Primary(B)<br/>v16.4 (提升)"]
        SC3["Standby(C)<br/>v16.4"]
    end
    
    subgraph S4["Step 4: 升级旧 Primary(A)"]
        SA4["Standby(A)<br/>v16.4 (升级)"]
        PB4["Primary(B)<br/>v16.4"]
        SC4["Standby(C)<br/>v16.4"]
    end
    
    S1 --> S2 --> S3 --> S4

更新触发方式:

# 方式一:修改 imageName 触发 Rolling Update
spec:
  imageName: ghcr.io/cloudnative-pg/postgresql:16.4  # 从 16.2 升级

# 方式二:更新 PostgreSQL 参数
spec:
  postgresql:
    parameters:
      shared_buffers: "8GB"  # 参数变更重启时滚动更新

# 方式三:更新 Operator 版本支持新特性

控制更新策略:

参数说明默认值
primaryUpdateStrategyunsupervised:自动完成 Switchover;supervised:需手动发起unsupervised
primaryUpdateMethodrestart:重启 Primary 更新;switchover:先切换再更新switchover
maxParallelWalSender并行 WAL Sender 数量上限
smartShutdownTimeoutSmart Shutdown 超时

小版本 vs 大版本升级:

升级类型方法说明
小版本(16.2 → 16.4)修改 imageName 自动 Rolling UpdateOperator 自动执行
大版本(15 → 16)pg_upgrade 模式需配置 bootstrap.pg_upgrade
9 CloudNativePG 的 Physical Streaming Replication

答案:

CloudNativePG 基于 PostgreSQL 物理流复制实现主备数据同步,支持异步与同步复制两种模式。

复制架构:

graph LR
    subgraph Primary["Primary Pod"]
        PG1["PostgreSQL Primary"]
        Writer["WAL Writer"]
        Sender1["WAL Sender"]
        Sender2["WAL Sender"]
        PVC1["~~~ WAL PVC ~~~"]
    end
    
    subgraph Standby["Standby Pod"]
        PG2["PostgreSQL Standby"]
        Receiver["WAL Receiver"]
        Applier["WAL Apply"]
        Startup["Startup Process"]
        PVC2["~~~ WAL PVC ~~~"]
    end
    
    Writer -->|"Write"| Sender1
    Writer -->|"Write"| Sender2
    Sender1 -->|"TCP 5432"| Receiver
    Sender2 -->|"TCP 5432"| Applier
    Receiver --> Applier
    Applier --> Startup

同步复制配置:

spec:
  instances: 3
  postgresql:
    parameters:
      # 同步复制:至少 1 个 Standby 确认 WAL 写入
      synchronous_standby_names: "ANY 1 (*)"
    # 同步模式
    synchronous:
      # 同步实例数量
      numberOfInstances: 1
      # 是否启用同步复制
      enabled: true
      # 当同步 Standby 不可用时,降低同步约束
      # 防止写入阻塞导致整个集群不可用

复制模式对比:

模式synchronous_standby_names数据安全性写入延迟容灾能力
异步可能丢失 WAL 未同步的事务依赖 WAL 归档恢复
同步(1 Standby)ANY 1 (*)至少 1 个 Standby 确认1 个 AZ 故障数据不丢
同步(2 Standby)ANY 2 (*)至少 2 个 Standby 确认2 个 AZ 故障数据不丢
同步(指定 Standby)FIRST 1 (standby-1)指定 Standby 必须确认特定 Standby 异常阻塞写入

复制延迟监测:

-- 查询复制延迟(字节)
SELECT
  application_name,
  pg_wal_lsn_diff(sent_lsn, write_lsn) AS write_lag_bytes,
  pg_wal_lsn_diff(write_lsn, flush_lsn) AS flush_lag_bytes,
  pg_wal_lsn_diff(flush_lsn, replay_lsn) AS replay_lag_bytes,
  pg_wal_lsn_diff(pg_current_wal_lsn(), replay_lsn) AS total_lag_bytes
FROM pg_stat_replication;
10 CloudNativePG 的 PVC 扩展与存储管理

答案:

CloudNativePG 将 PGDATA 和 WAL 分离到独立 PVC,通过 Kubernetes 存储抽象实现动态扩容、快照备份与灾难恢复。

存储架构:

graph TD
    subgraph Pod["PostgreSQL Pod"]
        PGDATA["PGDATA<br/>/var/lib/postgresql/data"]
        PGWAL["PG_WAL<br/>/var/lib/postgresql/wal"]
    end
    
    PGDATA -->|"目录"| Base["base/ (数据文件)"]
    PGDATA -->|"符号链接"| WalLink["pg_wal/"]
    PGDATA -->|"目录"| Stat["pg_stat/ (统计信息)"]
    
    PGDATA --> PVC1["PVC: pgdata-cluster-n<br/>StorageClass: premium-rwo"]
    
    PGWAL -->|"目录"| Archive["archive_status/"]
    PGWAL -->|"文件"| WALFiles["*.wal"]
    
    PGWAL --> PVC2["PVC: wal-cluster-n<br/>StorageClass: premium-rwo"]

PVC 扩容:

spec:
  storage:
    size: 200Gi  # 从 100Gi 扩容至 200Gi
    storageClass: premium-rwo
    # 扩容策略
    resizeInUseVolumes: true  # 允许在线扩容(需 CSI 驱动支持)

  walStorage:
    size: 50Gi   # WAL 独立扩容
    storageClass: premium-rwo

StorageClass 选择策略:

场景StorageClass特点
高性能 OLTPpremium-rwo (SSD/NVMe)低延迟 IOPS,适合 PGDATA
WAL 分离premium-rwo (SSD)WAL 顺序写,独立磁盘避免争抢
低成本归档standard-rwo (HDD)归档数据,成本优先
快速恢复CSI 快照(snapshot.storage.k8s.ioVolumeSnapshot 秒级克隆
跨 AZ 复制CSI 同步复制卷3 AZ 数据同步

存储扩容流程:

1. 修改 Cluster CRD storage.size
2. Operator 更新 StatefulSet volumeClaimTemplate
3. 对于已存在的 PVC:
   - Controller Expand:CSI 驱动增加卷容量
   - Node Expand:kubelet 调整文件系统大小
   - Operator 发送 SIGHUP 给 PG 进程(如果配置了 online resize)
4. 对于新 Pod:直接创建新容量 PVC

VolumeSnapshot 快速恢复:

# 从快照恢复集群
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
  name: pg-from-snapshot
spec:
  storage:
    size: 100Gi
  bootstrap:
    initdb:
      import:
        type: snapshot
        snapshot:
          name: pg-data-snapshot-20250801

存储容量告警:

spec:
  storage:
    size: 100Gi
  # 当存储使用率达到阈值告警
  # Operator 通过 Prometheus 指标暴露存储状态
11 StackGres 的架构与 All-in-One 理念

答案:

StackGres 是 OnGres 开发的企业级 PostgreSQL 平台 Operator,提供数据库、连接池、备份、监控、日志的一体化方案。

All-in-One 架构:

graph TD
    subgraph Operator["StackGres Operator"]
        SGCluster["SGCluster Controller"]
        SGDistributed["SGDistributed Logs Ctl"]
        SGScript["SGScript Controller"]
    end
    
    Operator -->|"管理"| ClusterPod["StackGres Cluster Pod"]
    
    subgraph ClusterPod["StackGres Cluster Pod"]
        subgraph Patroni["Container: patroni"]
            PGCore["PostgreSQL Engine (custom build)"]
            PatroniHA["Patroni HA Manager"]
            Extensions["内建扩展 (150+ extensions)"]
        end
        
        subgraph Envoy["Container: envoy (Sidecar)"]
            Pool["连接池"]
            Traffic["流量管理"]
        end
        
        subgraph Util["Container: postgres-util"]
            Backup["pgBackRest / WAL-G 备份"]
            Exporter["postgres_exporter"]
            Fluent["fluent-bit (日志采集)"]
        end
        
        PVC["~~~ PVC ~~~"]
    end

核心 CRD 一览:

CRD职责
SGCluster定义 PostgreSQL 集群的拓扑与配置
SGInstanceProfileCPU / 内存资源配置模板
SGPostgresConfigPostgreSQL 参数配置模板
SGPoolingConfigPgBouncer 连接池配置
SGBackupConfig备份策略与保留策略配置
SGDistributedLogs分布式日志采集与查询
SGScriptSQL 脚本管理与执行
SGDbOps数据库运维操作(Vacuum / Repack / Benchmark)

SGCluster 示例:

apiVersion: stackgres.io/v1
kind: SGCluster
metadata:
  name: pg-production
spec:
  instances: 3
  postgres:
    version: "16.2"
    flavor: "babelfish"  # 可选:babelfish / postgresql
  pods:
    persistentVolume:
      size: 100Gi
      storageClass: premium-rwo
  sgInstanceProfile: profile-production
  configurations:
    sgPostgresConfig: pgconfig-oltp
    sgPoolingConfig: poolconfig-default
    sgBackupConfig: backupconfig-daily
  distributedLogs:
    retention: 7d
    maxQueueSize: 100MB
  prometheusAutobind: true
12 StackGres 的 Envoy Sidecar 连接池

答案:

StackGres 在每个 PostgreSQL Pod 中以 Envoy Sidecar 容器提供连接池,实现应用到数据库的透明连接管理,无需额外部署 PgBouncer 实例。

Envoy Sidecar 架构:

graph LR
    subgraph App["Application Pod"]
        App2["Application<br/>jdbc:postgresql://cluster:5432"]
    end
    
    subgraph SGPod["StackGres Cluster Pod"]
        subgraph Envoy2["Container: envoy"]
            Filter["PostgreSQL Filter<br/>- 连接池<br/>- 查询路由<br/>- TLS 终止"]
        end
        
        subgraph Patroni2["Container: patroni"]
            PG2["PostgreSQL<br/>(localhost:5432)"]
        end
        
        Filter -->|"转发"| PG2
    end
    
    App2 -->|"TCP 5432"| Filter

Envoy 与 PgBouncer 对比:

维度Envoy Sidecar (StackGres)PgBouncer (独立部署)
部署模型Sidecar,与 PG 同 Pod独立 Pod 或 Server
配置管理SGPoolingConfig CRDConfigMap 或配置文件
连接模式Transaction PoolingSession / Transaction / Statement
负载均衡内建支持依赖 Service
TLSEnvoy 原生 TLSPgBouncer 需额外配置
监控Prometheus 指标通过 exporter 暴露
查询路由基于 SQL 前缀路由不直接支持

SGPoolingConfig 配置:

apiVersion: stackgres.io/v1
kind: SGPoolingConfig
metadata:
  name: poolconfig-production
spec:
  pgBouncerPgbouncerIni:
    pgbouncer:
      pool_mode: transaction
      max_client_conn: 1000
      default_pool_size: 50
      reserve_pool_size: 10
      reserve_pool_timeout: 5.0
      max_db_connections: 200
      max_user_connections: 50
      server_idle_timeout: 600
      query_wait_timeout: 60
      client_idle_timeout: 0
      stats_period: 60

连接池关键参数说明:

参数说明建议值
pool_mode连接池模式transaction(推荐)
max_client_conn最大客户端连接数1000
default_pool_size每用户 / 每数据库连接池大小25~50
reserve_pool_size预留连接数5~10
server_idle_timeout服务端空闲连接超时600s
13 StackGres 的 Babelfish / Patroni / PgBouncer 集成

答案:

StackGres 在基础镜像中预置了 Babelfish(SQL Server 兼容层)、Patroni(HA 管理)和 PgBouncer(连接池),实现开箱即用的企业级功能集成。

集成架构:

graph TD
    subgraph Image["StackGres Custom PostgreSQL Image"]
        subgraph Engine["PostgreSQL Engine"]
            Babelfish["Babelfish (SQL Server)"]
            Ext150["150+ Extensions (预装)"]
            Plugins["TimescaleDB / PostGIS / etc"]
        end
        
        subgraph Patroni3["Patroni"]
            LeaderElection["Leader 选举"]
            AutoFailover["自动 Failover"]
            DCS["DCS 集成"]
            RestAPI["REST API"]
        end
        
        subgraph PgBouncer["PgBouncer"]
            Pool2["连接池"]
            QueryRoute["查询路由"]
            RateLimit["限流"]
        end
    end

Babelfish 集成:

Babelfish 是 AWS 开源的 SQL Server 协议兼容层,使 PostgreSQL 能够接受 TDS 协议连接,运行 SQL Server 的 T-SQL 语法。

apiVersion: stackgres.io/v1
kind: SGCluster
metadata:
  name: pg-babelfish
spec:
  postgres:
    version: "16.2"
    flavor: "babelfish"  # 启用 Babelfish
  instances: 3

Babelfish 启用后,PostgreSQL 可同时接受 PostgreSQL Wire Protocol(端口 5432)和 TDS Protocol(端口 1433)连接,实现 SQL Server 应用的无改造迁移。

Patroni 集成:

StackGres 使用 Patroni 进行 HA 管理,Patroni 通过 Kubernetes API 作为 DCS(而非 etcd),避免引入外部依赖。

graph TD
    subgraph Patroni4["Patroni"]
        DCS2["DCS: Kubernetes Endpoints/ConfigMap"]
        LeaderLock["Leader Lock: ConfigMap"]
        MemberRegistry["Member Registry: Endpoints"]
        Config2["Configuration: ConfigMap"]
        
        RestAPI2["REST API: http://localhost:8008"]
        GetLeader["GET /leader"]
        GetReplica["GET /replica"]
        PostSwitchover["POST /switchover"]
        PostRestart["POST /restart"]
    end
    
    DCS2 --> LeaderLock
    DCS2 --> MemberRegistry
    DCS2 --> Config2
    
    RestAPI2 --> GetLeader
    RestAPI2 --> GetReplica
    RestAPI2 --> PostSwitchover
    RestAPI2 --> PostRestart

PgBouncer 集成:

PgBouncer 以 Sidecar 形式部署,通过 SGPoolingConfig 声明式配置,支持与 Patroni 协同——Failover 后 PgBouncer 自动重新连接到新的 Primary。

三者协同工作流程:

  1. 连接建立:客户端连接至 PgBouncer 端口,PgBouncer 复用数据库连接至 Patroni 管理的 PostgreSQL 实例。
  2. 故障切换:Patroni 检测 Primary 故障并触发 Leader 选举,PgBouncer 检测到连接断开后查询 Patroni REST API 获取新 Primary 地址并重连。
  3. 读写路由:通过 PgBouncer 配置将读请求路由至 Standby,写请求路由至 Primary(需应用侧配合)。
14 StackGres 的垂直 / 水平扩缩容

答案:

StackGres 通过 SGInstanceProfile 和 SGCluster.instances 分别管理垂直与水平扩缩容,支持在线调整与计划内变更。

垂直扩缩容(CPU / Memory):

apiVersion: stackgres.io/v1
kind: SGInstanceProfile
metadata:
  name: profile-production
spec:
  cpu: "8"
  memory: 32Gi
# 修改 SGInstanceProfile 后,Operator 按 Rolling Update 方式
# 逐个 Pod 重建,使用新资源配置
kubectl patch sginstanceprofile profile-production \
  --type merge -p '{"spec":{"cpu":"16","memory":"64Gi"}}'

水平扩缩容(Instance 数量):

apiVersion: stackgres.io/v1
kind: SGCluster
metadata:
  name: pg-production
spec:
  instances: 5  # 从 3 增至 5

扩缩容操作分类:

操作类型CRD 字段执行方式服务中断
CPU/Memory 扩容SGInstanceProfileRolling Update(逐个 Pod 重建)无(用 ReadOnly Service 路由)
磁盘扩容SGCluster.pods.persistentVolume.size在线扩容(需 CSI 支持)
实例增加SGCluster.instances创建新 Pod,自动加入集群
实例减少SGCluster.instances删除 Pod仅当删除 Primary 时有短暂中断

仅扩容不重建:

StackGres 支持通过 SGDbOps 资源执行指定实例的扩缩容,控制执行时间窗口:

apiVersion: stackgres.io/v1
kind: SGDbOps
metadata:
  name: restart-instance-2
spec:
  op: restart
  sgCluster: pg-production
  maxRetries: 1
  timeout: 3600
  # 仅操作指定 Pod
  pods:
    - pg-production-2

Scheduling 控制:

spec:
  sgInstanceProfile: profile-production
  pods:
    scheduling:
      nodeSelector:
        node-type: database
      tolerations:
        - key: "database"
          operator: "Equal"
          value: "true"
          effect: "NoSchedule"
      nodeAffinity:
        preferredDuringSchedulingIgnoredDuringExecution:
          - weight: 100
            preference:
              matchExpressions:
                - key: topology.kubernetes.io/zone
                  operator: In
                  values:
                    - zone-a
                    - zone-b
15 Zalando Postgres Operator 的架构

答案:

Zalando Postgres Operator 由 Zalando 开发维护,基于 Spilo 镜像与 Patroni HA 方案,依赖 etcd 作为分布式协调服务。

整体架构:

graph TD
    K8sAPI["Kubernetes API Server"]
    
    K8sAPI -->|"Watch postgresql CRD"| Operator["Zalando Postgres Operator"]
    
    subgraph Operator["Zalando Postgres Operator"]
        Sync["Sync Controller"]
        Connection["Connection Pooler"]
        Rolling["Rolling Update Manager"]
    end
    
    Operator -->|"创建 StatefulSet / Service / Secret"| SpiloPod["Spilo Pod"]
    
    subgraph SpiloPod["Spilo Pod (PostgreSQL)"]
        subgraph Patroni5["Patroni"]
            HA_Manager["HA Manager"]
            RestAPI3["REST API"]
            CallbackScript["Callback Script"]
        end
        
        subgraph PG["PostgreSQL"]
            PrimaryStandby["Primary / Standby"]
            Basebackup["pg_basebackup"]
            WALArch["WAL-E / WAL-G 归档"]
        end
        
        subgraph Etcd["etcd Cluster (独立部署或通过 Operator 集成)"]
            LeaderLock2["Leader 锁"]
            ConfigStore["配置存储"]
            MemberDiscovery["成员发现"]
        end
    end
    
    Patroni5 -->|"DCS Connection"| Etcd

核心组件职责:

组件职责
Operator监听 PostgreSQL CRD,创建/更新/删除 StatefulSet、Service、ConfigMap、Secret
Spilo封装 Patroni + PostgreSQL 的 Docker 镜像,内建备份工具链
PatroniHA 管理器:Leader 选举、自动 Failover、配置管理、REST API
etcd分布式协调后端(DCS),存储集群状态、Leader 锁、配置
WAL-E / WAL-GWAL 归档与备份工具,将 WAL 和 Base Backup 上传至 S3 / GCS

PostgreSQL CRD 示例:

apiVersion: "acid.zalan.do/v1"
kind: postgresql
metadata:
  name: pg-production
spec:
  teamId: "sre"
  numberOfInstances: 3
  postgresql:
    version: "16"
    parameters:
      shared_buffers: "4GB"
      max_connections: "500"
  volume:
    size: 100Gi
    storageClass: premium-rwo
  patroni:
    ttl: 30
    loop_wait: 10
    retry_timeout: 10
  resources:
    requests:
      cpu: 4
      memory: 8Gi
    limits:
      cpu: 8
      memory: 16Gi
16 Zalando Operator 的 Spilo 镜像与 Patroni 集成

答案:

Spilo 是 Zalando 维护的 PostgreSQL Docker 镜像,将 Patroni、PostgreSQL 核心、备份工具链、监控 exporter 等打包为一体。

Spilo 镜像分层结构:

graph TD
    subgraph Spilo["Spilo Docker Image"]
        subgraph AppLayer["Application Layer"]
            Patroni6["Patroni (HA Manager)"]
            WALG2["WAL-G (Backup & WAL Archive)"]
            PgBackRest["pgBackRest (可选)"]
            PgExporter["postgres_exporter"]
            PgBouncer2["PgBouncer (可选)"]
            Configure["configure_spilo.py (启动脚本)"]
        end
        
        subgraph EngineLayer["PostgreSQL Engine"]
            PG16["PostgreSQL 12/13/14/15/16/17"]
            Contrib["贡献扩展 (Contrib Extensions)"]
            PL["PL/Python / PL/Perl / PL/Tcl"]
            Plugins2["TimescaleDB / PostGIS / pg_cron"]
        end
        
        subgraph BaseLayer["Base OS Layer"]
            OS["Ubuntu / Debian"]
            Python["Python 3.x"]
        end
    end
    
    AppLayer --> EngineLayer --> BaseLayer

Patroni 启动流程:

configure_spilo.py (启动入口)
       ├── 1. 检测角色(Primary / Standby)
       │      ├── 已有数据目录 → Standby
       │      └── 无数据目录 → 检查 DCS 是否有 Leader
       │             ├── 有 Leader → pg_basebackup 拉取数据
       │             └── 无 Leader → initdb 初始化
       ├── 2. 配置 Patroni
       │      ├── 注入 postgresql 参数
       │      ├── 设定 DCS 连接(etcd / Kubernetes / ZooKeeper)
       │      └── 设定 REST API 监听
       ├── 3. 启动 Patroni
       │      └── Patroni 管理 PostgreSQL 进程生命周期
       └── 4. Patroni 守护循环
              ├── 每 loop_wait 秒检查 PostgreSQL 健康
              ├── 通过 DCS 维护 Leader 锁
              └── Leader 故障时触发 Failover

Spilo 环境变量配置:

环境变量说明示例值
SCOPE集群名称pg-production
PGVERSIONPostgreSQL 主版本16
WAL_S3_BUCKETWAL 归档 S3 桶s3://pg-wal-archive
WAL_GCS_BUCKETWAL 归档 GCS 桶gs://pg-wal-archive
BACKUP_SCHEDULE备份 Cron 表达式00 02 * * *
BACKUP_NUM_TO_RETAIN备份保留数量7
USE_PA16是否使用 pgAudit 1.6true

Patroni REST API 端点:

端点方法说明
/leaderGET返回当前 Leader 信息
/replicaGET返回 Standby 延迟信息
/switchoverPOST计划内主备切换
/restartPOST重启 PostgreSQL
/reinitializePOST重新初始化 Standby
/patroniGETPatroni 状态信息
/historyGET切换历史记录
17 Zalando Operator 的 etcd 作为 DCS

答案:

Zalando Postgres Operator 依赖 etcd 作为分布式一致性存储(DCS),存储集群 Leader 锁、配置和成员信息。

etcd 在 HA 架构中的作用:

graph TD
    subgraph Etcd2["etcd Cluster"]
        Root["/service/scope/"]
        
        Root --> Leader2["leader - Leader 锁(TTL 续约)"]
        Root --> Members["members/ - 成员注册与状态"]
        Members --> Member0["member-0"]
        Members --> Member1["member-1"]
        
        Root --> Config3["config/ - 集群配置"]
        Config3 --> PGParams["postgresql.parameters"]
        Config3 --> LoopWait["patroni.loop_wait"]
        
        Root --> Init["initialize - 初始化标记"]
        Root --> History["history - 切换历史"]
        Root --> Optime["optime/ - 最近 Leader 墙钟时间"]
        Optime --> LeaderTime["leader"]
    end

Leader 选举与 Lock 机制:

时间线:Patroni 守护循环

T+0s   Standby: GET /service/scope/leader → 存在(Primary-0)
T+1s   Primary-0: PUT /service/scope/leader (renew TTL=30s)

--- Primary-0 故障 ---

T+30s  租约过期,Leader Key 自动删除
T+31s  Standby-1: GET /service/scope/leader → 不存在
T+32s  Standby-1: PUT /service/scope/leader (CAS, value=Standby-1)
        → 写入成功 → Standby-1 提升为 Primary
T+33s  Standby-2: PUT /service/scope/leader (CAS)
        → 写入失败(已被 Standby-1 持有)
T+34s  Standby-1: pg_ctl promote → 完成提升

etcd 部署模式:

模式说明适用场景
独立 etcd Cluster专用 etcd 集群,3/5 节点多 PostgreSQL 集群共享,生产推荐
K8s 内嵌 etcd使用 K8s API Server 的 etcdPoC / 开发环境
Operator 管理 etcdZalando Operator 自带 etcd Operator简化部署
ZooKeeper / ConsulPatroni 同样支持已有基础设施

etcd DCS vs Kubernetes DCS(CloudNativePG):

维度etcd DCSKubernetes DCS
额外组件需独立部署 etcd(3~5 节点)无(利用 K8s API)
故障域依赖 etcd 可用性依赖 K8s API Server 可用性
Leader 锁etcd Key TTL + CASConfigMap / Endpoints
配置管理etcd Key/ValueConfigMap / Secret
运维复杂度需管理 etcd 集群无额外运维
适用规模大规模(数百 PG 集群共享 etcd)小到中规模
18 PostgreSQL 在 K8s 上的备份策略

答案:

PostgreSQL on Kubernetes 的备份体系由物理备份、WAL 归档和快照三种方式组成,分别适用于不同恢复目标。

备份工具对比:

工具备份类型存储后端恢复能力Operator 集成
WAL-G物理 + WALS3 / GCS / Azure / Swift / FSPITR(任意时间点)Zalando / StackGres
pgBackRest物理 + WALS3 / GCS / Azure / NFS / POSIXPITR + 增量 / 差异备份CloudNativePG / StackGres(Barman Cloud)
Barman Cloud物理 + WALS3 / GCS / AzurePITR(barmanObjectStore)CloudNativePG 原生支持
pg_basebackup物理全量POSIX / tar / 流全量恢复基础工具
Volume Snapshot块级别快照CSI Snapshot快照点恢复CloudNativePG(VolumeSnapshot)

WAL-G 备份流程:

graph TD
    Start["pg_backup_start() 标记开始"]
    
    Start --> FullBackup["全量备份<br/>- pg_basebackup<br/>- 或 tar 打包"]
    FullBackup --> Push["WAL-G push<br/>上传至对象存储"]
    
    Start --> Stop["pg_backup_stop() 标记结束"]
    Stop --> WalPush["WAL-G wal-push<br/>增量 WAL 上传"]
    
    Push --> Stop
    
    NoteRight["Note: archive_command 持续推送 WAL<br/>→ WalPush"]

CloudNativePG 备份配置:

# 全量备份 + WAL 归档
spec:
  backup:
    barmanObjectStore:
      destinationPath: s3://pg-backups/production
      endpointURL: https://s3.cn-north-1.amazonaws.com.cn
      s3Credentials:
        accessKeyId:
          name: s3-credentials
          key: access_key_id
        secretAccessKey:
          name: s3-credentials
          key: secret_access_key
      wal:
        compression: gzip
        encryption: AES256
      data:
        compression: gzip
        encryption: AES256
        # 立即执行一次 Checkpoint 保证一致性
        immediateCheckpoint: false
      retentionPolicy: "30d"

备份策略金字塔:

graph TD
    L1["异地灾备<br/>跨区域备份<br/>S3/GCS 跨区域复制<br/>每周 1 次 / 保留 3 个月"]
    L2["快照<br/>Volume Snapshot<br/>每天 1 次 / 保留 7 天"]
    L3["全量 + WAL<br/>barmanObjectStore / WAL-G<br/>PITR 恢复<br/>每天全量 + 持续 WAL / 保留 30 天"]
    
    L1 --> L2 --> L3

备份验证闭环:

验证步骤频率自动化方式
备份文件完整性校验每次备份后Operator 自动验证
恢复至临时集群每周bootstrap.recovery / CronJob
PITR 恢复测试每月指定时间点恢复至测试集群
数据一致性校验恢复后pg_checksums / amcheck
19 PostgreSQL 的复制槽(Replication Slot)管理

答案:

Replication Slot 是 PostgreSQL 保证 Standby 不丢失 WAL 的机制,在 Kubernetes 动态环境中需特别关注 WAL 堆积和 Failover 后的槽位处理。

复制槽类型:

类型用途创建方式
Physical SlotStreaming Replicationpg_create_physical_replication_slot()
Logical Slot逻辑复制 / CDCpg_create_logical_replication_slot()
Temporary Slot临时 Base Backuppg_basebackup -S(用完即删)

复制槽生命周期与 WAL 保留:

Primary 上的 WAL 保留行为:

有活跃 Replication Slot
  WAL 保留到所有 Slot 的 restart_lsn 之后
  → 风险:Standby 长时间宕机导致 Primary WAL 堆积磁盘满

无 Replication Slot
  WAL 保留受 wal_keep_size 限制
  → 风险:Standby 延迟超过 wal_keep_size 后无法追上,需重新 pg_basebackup

CloudNativePG 复制槽管理:

spec:
  replicationSlots:
    # 启用高可用复制槽(每个 Standby 自动创建)
    highAvailability:
      enabled: true
      # Slot 前缀
      slotPrefix: _cnpg_
    # 当 Standby 被删除时自动清理对应 Slot
    synchronizeReplicas: true
    # 更新间隔
    updateInterval: 30

WAL 堆积的预防措施:

参数说明建议值
max_slot_wal_keep_size单个 Slot 可保留的 WAL 最大大小-1(不限制,靠监控兜底)
wal_keep_size为所有 Standby 保留的 WAL 总量0(使用 Slot 管理)
max_wal_size自动 Checkpoint 时 WAL 总量上限4GB(避免单个 WAL 段堆积)
archive_timeout强制 WAL 段切换间隔300s(5min)

监控与告警:

-- 监控复制槽 WAL 延迟
SELECT
  slot_name,
  active,
  pg_wal_lsn_diff(pg_current_wal_lsn(), restart_lsn) AS retention_bytes,
  pg_size_pretty(pg_wal_lsn_diff(pg_current_wal_lsn(), restart_lsn)) AS retention_pretty
FROM pg_replication_slots
WHERE NOT temporary;

Failover 后的 Slot 清理流程:

1. 旧 Primary 故障
2. 新 Primary 提升(Standby 上的 Slot 变为可用)
3. 旧 Primary 恢复为 Standby
4. 新 Primary 创建与新 Standby 对应的 Slot
5. 旧 Primary 上的旧 Slot 通过 synchronizeReplicas: true 自动清理
20 PostgreSQL 的 Vacuum 与 AutoVacuum 在 K8s 下的调优

答案:

Vacuum 是 PostgreSQL MVCC 机制的核心维护操作,在容器化环境需要针对资源限制、I/O 节流和调度策略进行专门调优。

MVCC 与 Vacuum 机制回顾:

graph TD
    Update["UPDATE 操作"]
    
    Update --> OldTuple["旧版本元组 (Dead Tuple)<br/>标记为无效"]
    Update --> NewTuple["新版本元组 (Live Tuple)<br/>新插入"]
    
    OldTuple --> Vacuum["VACUUM: 回收 Dead Tuple 空间"]
    NewTuple --> Vacuum
    
    Vacuum --> FSM["更新 FSM (空闲空间映射)"]
    Vacuum --> VM["更新 VM (可见性映射)"]
    Vacuum --> Freeze["冻结事务 ID (防止回卷)"]

AutoVacuum 核心参数:

# postgresql.conf / Cluster CRD parameters
autovacuum = on

# 触发阈值
autovacuum_vacuum_threshold = 50               # 最小 Dead Tuple 数
autovacuum_vacuum_scale_factor = 0.1           # 表大小的 10% Dead Tuple
autovacuum_analyze_threshold = 50
autovacuum_analyze_scale_factor = 0.05

# 成本限制(I/O 节流)
autovacuum_vacuum_cost_delay = 2ms             # 每次 Cost 到达后暂停
autovacuum_vacuum_cost_limit = 200             # 每次暂停前的 Cost 上限

# Worker 并发
autovacuum_max_workers = 5                     # 最大同时运行的 Worker 数

# 大表优化
autovacuum_vacuum_insert_threshold = 1000      # Insert-Only 表触发阈值
autovacuum_vacuum_insert_scale_factor = 0.1    # Insert-Only 表触发比例

K8s 环境下的特殊考量:

问题原因解决方案
VACUUM 被 OOM Killmaintenance_work_mem 过高 + K8s memory limitmaintenance_work_mem <= memory limit 的 25%
I/O 争抢导致延迟VACUUM 产生大量 I/O,与其他查询竞争降低 cost_limit,提高 cost_delay
长事务阻塞 VACUUM存在未提交事务,VACUUM 无法回收旧版本监控 oldest xminidle_in_transaction_session_timeout = 300s
Insert-Only 表膨胀默认 VACUUM 只由 UPDATE/DELETE 触发PG13+ 设置 autovacuum_vacuum_insert_threshold
容器重启 VACUUM 中断重启后 Autovacuum 重新调度设置 autovacuum_naptime = 30s 缩短调度间隔

K8s 环境下 Containerd / Docker 的特殊问题:

OverlayFS 等容器存储驱动可能导致大量 VACUUM FULL 操作性能下降。建议:

  • PGDATA 挂载 PVC 而非容器层,避免 Copy-on-Write 开销
  • 使用 local-ssd 或高性能 CSI 驱动减少 I/O 放大
  • 避免在容器镜像层存储数据库文件

Autovacuum 监控 SQL:

-- 查看表膨胀比例
SELECT
  schemaname || '.' || relname AS table_name,
  n_dead_tup,
  n_live_tup,
  round(n_dead_tup * 100.0 / NULLIF(n_live_tup + n_dead_tup, 0), 2) AS dead_ratio,
  last_vacuum,
  last_autovacuum
FROM pg_stat_user_tables
WHERE n_dead_tup > 1000
ORDER BY n_dead_tup DESC
LIMIT 20;
21 PostgreSQL 的连接池配置(PgBouncer / Odyssey)

答案:

PostgreSQL 采用进程模型(每连接一个 Backend Process),在微服务和云原生架构中必须引入连接池来缓解连接数压力。

连接池架构位置:

graph TD
    subgraph Apps["Application Pods (100+ instances)"]
        App1["App-1"]
        App2["App-2"]
        App3["App-N"]
    end
    
    Apps -->|"大量短连接"| PgBouncer3["PgBouncer Pod<br/>(Connection Pool)<br/>Sidecar 或独立 Pod<br/><br/>Client Pool: 1000<br/>Server Pool: 50"]
    
    PgBouncer3 -->|"少量长连接"| PG3["PostgreSQL Pod<br/>max_connections: 200"]

PgBouncer vs Odyssey 对比:

维度PgBouncerOdyssey
开发语言CC
连接模式Session / Transaction / StatementTransaction
多线程单线程(多进程)多线程
TLS支持,需编译选项内建支持,性能更好
SCRAM 认证支持支持
查询路由不支持支持(根据 SQL 规则路由到读/写)
事务池限流不支持支持(per-user / per-database)
存储后端文件文件 + PostgreSQL(集中管理)
性能极轻量,适合高并发更强扩展性,适合复杂路由

PgBouncer 核心配置:

[databases]
* = host=localhost port=5432

[pgbouncer]
listen_addr = 0.0.0.0
listen_port = 6432
auth_type = scram-sha-256
auth_file = /etc/pgbouncer/userlist.txt

# 连接池模式
pool_mode = transaction

# 连接数控制
max_client_conn = 1000
default_pool_size = 25
min_pool_size = 5
reserve_pool_size = 10
reserve_pool_timeout = 5.0
max_db_connections = 0
max_user_connections = 0

# 超时与生命周期
server_idle_timeout = 600
server_lifetime = 3600
server_connect_timeout = 15
client_idle_timeout = 0
query_wait_timeout = 60
query_timeout = 0
idle_transaction_timeout = 0

# 管理
admin_users = admin
stats_users = stats
stats_period = 60

K8s 部署模式对比:

模式优点缺点
Sidecar(与 App 同 Pod)低延迟,无额外网络跳,服务发现简单池化收益分散,每 Pod 独立维护连接池
DaemonSet每节点一个,资源开销固定应用需配置 Node IP
独立 Service池化效果好,统一管理额外网络跳,需高可用
StackGres Envoy与 PG Pod Sidecar,零额外运维仅 StackGres 生态

连接池模式选择:

模式行为适用场景
session一个客户端连接对应一个服务端连接,持续整个会话需要 SET / LISTEN / 游标等会话状态
transaction仅在事务期间占用服务端连接无状态短连接,推荐
statement仅在单条语句期间占用连接极端场景,不支持多语句事务
22 PostgreSQL 的监控与 Prometheus

答案:

PostgreSQL on Kubernetes 通过 postgres_exporter 或 CloudNativePG / StackGres 内建指标暴露,将运行指标接入 Prometheus 体系。

监控架构:

graph TD
    subgraph Stack["Prometheus Stack"]
        Prometheus["Prometheus<br/>(Scrape + TSDB)"]
        Grafana["Grafana<br/>(Dashboard + Alert)"]
        Prometheus --> Grafana
    end
    
    Prometheus -->|"Scrape /metrics"| Exporter2["postgres_exporter<br/>:9187/metrics<br/>Sidecar 容器"]
    
    Exporter2 -->|"SQL Query"| PG4["PostgreSQL"]
    
    subgraph PG4["PostgreSQL"]
        PgStatStatements["pg_stat_statements"]
        PgStatActivity["pg_stat_activity"]
        PgStatReplication["pg_stat_replication"]
    end

CloudNativePG 原生 Prometheus 集成:

spec:
  monitoring:
    enablePodMonitor: true
    # 自定义 PodMonitor 标签
    podMonitor:
      labels:
        app: prometheus
      additionalLabels:
        team: sre

CloudNativePG Instance Manager 内建 Prometheus 端点:

  • 端口 9187,路径 /metrics
  • 暴露 PostgreSQL 运行指标、备份状态、复制延迟

StackGres Prometheus 集成:

spec:
  prometheusAutobind: true

StackGres 自动创建 PodMonitor,并预置 Grafana Dashboard。

关键监控指标:

指标类别关键指标阈值建议
连接pg_stat_activity count> 80% max_connections 告警
复制延迟pg_stat_replication replay_lag> 30s 告警
长事务pg_stat_activity xact_start> 5min 告警
锁等待pg_locks granted=false> 10s 告警
慢查询pg_stat_statements mean_exec_time> 1s 告警
Dead Tuplepg_stat_user_tables n_dead_tup> 10M 或 > 20% 告警
WAL 堆积pg_replication_slots restart_lsn> max_wal_size 告警
磁盘使用cnpg_pgdata_size / PVC> 80% 告警

pg_stat_statements 配置:

spec:
  postgresql:
    parameters:
      shared_preload_libraries: "pg_stat_statements"
      pg_stat_statements.track: "all"
      pg_stat_statements.max: "10000"
      pg_stat_statements.track_utility: "off"

核心 PromQL 告警规则:

# 连接数告警
- alert: HighConnections
  expr: |
    pg_stat_database_numbackends{datname="appdb"}
    / on(instance) group_left
    pg_settings_max_connections * 100 > 80    
  for: 5m

# 复制延迟告警
- alert: ReplicationLag
  expr: pg_stat_replication_replay_lag_bytes > 104857600  # 100MB
  for: 2m

# 长事务告警
- alert: LongRunningTransaction
  expr: pg_stat_activity_max_tx_duration_seconds > 300
  for: 1m
23 PostgreSQL 的 pgAudit 审计配置

答案:

pgAudit 是 PostgreSQL 的审计扩展,记录 DDL、DML、ROLE 等操作的详细日志,在 K8s 环境中通过 shared_preload_libraries 和 Cluster CRD 参数启用。

pgAudit 架构:

graph TD
    Query["查询执行"]
    
    Query --> PgAudit["pgAudit Extension"]
    
    subgraph PgAudit["pgAudit Extension"]
        EventFilter["Event Class Filter<br/>READ/WRITE/ROLE/DDL"]
        ObjectFilter["Object Filter<br/>table/role/schema..."]
        AuditWriter["Audit Log Writer<br/>(csvlog / syslog)"]
        
        EventFilter --> ObjectFilter --> AuditWriter
    end
    
    AuditWriter --> LogOutput["log_statement / log_destination"]

CloudNativePG 中的 pgAudit 配置:

spec:
  postgresql:
    parameters:
      # 预加载 pgAudit
      shared_preload_libraries: "pg_stat_statements, pgaudit"

      # 审计配置
      pgaudit.log: "write, ddl, role"
      pgaudit.log_catalog: "off"
      pgaudit.log_level: "log"
      pgaudit.log_parameter: "on"
      pgaudit.log_relation: "on"
      pgaudit.log_rows: "off"
      pgaudit.log_statement_once: "off"

      # 角色级审计
      pgaudit.role: "auditor"

      # 日志输出
      log_destination: "csvlog"
      logging_collector: "on"
      log_directory: "pg_log"
      log_filename: "postgresql-%a.log"
      log_rotation_age: "1d"
      log_rotation_size: "0"

pgAudit 日志分类:

审计范围生产配置
readSELECT / COPY TO按需启用(量大,可能影响性能)
writeINSERT / UPDATE / DELETE / COPY FROM / TRUNCATE始终启用
function函数调用和 DO 块按需启用
roleGRANT / REVOKE / CREATE/ALTER/DROP ROLE始终启用
ddl除 ROLE 外的所有 DDL始终启用
miscDISCARD / FETCH / CHECKPOINT 等按需启用
misc_setSET 命令按需启用

审计日志采集架构(K8s 环境):

graph TD
    PA["pgAudit"]
    CSV["csvlog → /var/lib/postgresql/data/pg_log/"]
    PVC["PVC (PGDATA)"]
    Sidecar["Sidecar: fluent-bit / filebeat"]
    Tail["tail pg_log/*.csv"]
    Parse["解析 CSV → JSON"]
    Backend["Elasticsearch / Loki / Kafka"]
    PA --> CSV --> PVC
    CSV --> Sidecar --> Tail --> Parse --> Backend

审计日志集中采集(Loki + Promtail):

# Promtail DaemonSet 或 Sidecar 采集 PostgreSQL 日志
scrape_configs:
  - job_name: postgresql-audit
    kubernetes_sd_configs:
      - role: pod
    relabel_configs:
      - source_labels: [__meta_kubernetes_pod_label_cnpg_io_cluster]
        action: keep
        regex: pg-production
    pipeline_stages:
      - regex:
          expression: '^(?P<audit_type>AUDIT):.*STATEMENT:(?P<statement>.*)'
      - labels:
          audit_type:
24 PostgreSQL 的逻辑复制与 CDC

答案:

PostgreSQL 逻辑复制(Logical Replication)基于发布 / 订阅模型,以表为单位选择性同步数据变更,是实现 CDC 的核心机制。

物理复制 vs 逻辑复制:

维度Physical ReplicationLogical Replication
复制粒度整个实例(块级别)表级别(行级别)
DDL 同步自动同步不同步
跨版本复制不可跨大版本可跨版本
写入能力Standby 为只读订阅端可写
复制协议WAL StreamingLogical Decoding + WAL Sender
使用场景HA / 读写分离 / 灾备CDC / 数据迁移 / 大版本升级

逻辑复制架构:

graph LR
    subgraph Publisher[Publisher 源端]
        A[WAL Decoder<br/>pgoutput]
        B[Publication<br/>- orders<br/>- payments]
        A --> B
        Slot1[Logical Replication Slot<br/>orders_slot] -.-> A
    end
    subgraph Subscriber[Subscriber 目标端]
        C[Logical Replay Worker]
        D[Subscription<br/>- orders_sub<br/>CONNECTION ...]
        C --> D
        Slot2[Logical Replication Slot<br/>目标端内部] -.-> C
    end
    A -->|TCP 5432| C

发布与订阅配置:

-- 源端:创建发布
CREATE PUBLICATION orders_pub FOR TABLE orders, payments
  WITH (publish = 'insert,update,delete');

-- 目标端:创建订阅
CREATE SUBSCRIPTION orders_sub
  CONNECTION 'host=pg-source-rw dbname=appdb user=replicator password=xxx'
  PUBLICATION orders_pub
  WITH (
    copy_data = true,
    create_slot = true,
    enabled = true,
    synchronous_commit = 'off'
  );

CloudNativePG 下的逻辑复制部署:

逻辑复制部署在 Kubernetes 上可创建独立的 Cluster 实例,通过发布 / 订阅实现跨集群数据同步,或用作大版本升级的中间跳板。

# 源集群(Publisher)
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
  name: pg-source
spec:
  instances: 3
  postgresql:
    parameters:
      wal_level: "logical"
      max_replication_slots: "10"
      max_wal_senders: "10"

# 目标集群(Subscriber)
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
  name: pg-target
spec:
  instances: 3
  postgresql:
    parameters:
      wal_level: "logical"
      max_replication_slots: "10"
      max_logical_replication_workers: "8"
      max_worker_processes: "16"

CDC 工具链对比:

工具原理输出格式适用场景
DebeziumKafka Connect + pgoutputKafka / JSON / Avro实时数据管道
pg_recvlogical原生逻辑解码客户端自定义轻量 CDC
WAL2JSONLogical Decoding 插件,输出 JSONJSONDebezium 后端
pglogical扩展插件,兼容 9.4+向下兼容逻辑复制旧版本迁移

逻辑复制注意事项:

问题说明解决
Sequence 不同步逻辑复制不复制 Sequence迁移后手动更新 setval()
DDL 变更ALTER TABLE 不会传播需在两端分别执行
Large Object不支持避免使用或单独迁移
冲突检测订阅端写入可能与复制数据冲突设置订阅为 origin=none
复制槽膨胀订阅端断连导致 WAL 堆积监控 pg_replication_slots
25 PostgreSQL 的多租户隔离方案

答案:

PostgreSQL on Kubernetes 提供从数据库级到集群级的多层次多租户隔离方案。

隔离方案对比:

graph TD
    subgraph L0[Level 0: Schema 隔离]
        PG0[PostgreSQL Instance]
        PG0 --> TA[tenant_a]
        PG0 --> TB[tenant_b]
    end
    subgraph L1[Level 1: Database 隔离]
        PG1[PostgreSQL Instance]
        PG1 --> DA[db_tenant_a]
        PG1 --> DB[db_tenant_b]
    end
    subgraph L2[Level 2: Cluster 隔离]
        CA[Cluster A<br/>namespace-A]
        CB[Cluster B<br/>namespace-B]
    end
    subgraph L3[Level 3: Operator / Node 隔离]
        OA[Operator-A<br/>NodeGroup-A]
        OB[Operator-B<br/>NodeGroup-B]
    end
    L0 --> L1 --> L2 --> L3
Level方案隔离度成本
0Schema 隔离最低最低
1Database 隔离
2Cluster 隔离
3Operator/Node 隔离最高最高

各方案详细对比:

维度Schema 隔离Database 隔离Cluster 隔离Operator/Node 隔离
资源隔离部分(pg_stat_database)完全(CPU/Memory/IO)物理级别
连接隔离中等(每 Database 连接数)完全独立连接池物理级别
安全隔离低(跨 Schema 查询可绕过)中等(跨 Database 不能直接访问)高(独立网络策略)物理级别
性能隔离低(共享 Buffer Pool)中等(共享 shared_buffers)高(独立 Buffer Pool)完全隔离
备份粒度全实例Database 级别(pg_dump)Cluster 级别Cluster 级别
故障爆炸半径整个实例整个实例单个集群最小
运维成本
适用于内部工具 / 开发环境小型 SaaS生产环境 SaaS金融 / 安全合规

CloudNativePG 多租户部署最佳实践:

# 生产环境:每租户一个 Cluster(Namespace 隔离)
apiVersion: v1
kind: Namespace
metadata:
  name: tenant-acme-db
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
  name: pg-acme
  namespace: tenant-acme-db
spec:
  instances: 3
  storage:
    size: 50Gi
    storageClass: premium-rwo
  postgresql:
    parameters:
      shared_buffers: "2GB"
      max_connections: "200"
  resources:
    requests:
      cpu: "2"
      memory: 4Gi
    limits:
      cpu: "4"
      memory: 8Gi

资源配额与限制策略:

# Namespace 级别 ResourceQuota
apiVersion: v1
kind: ResourceQuota
metadata:
  name: tenant-acme-quota
  namespace: tenant-acme-db
spec:
  hard:
    requests.cpu: "8"
    requests.memory: 32Gi
    requests.storage: 500Gi
    persistentvolumeclaims: "5"
26 PostgreSQL 的跨可用区 / 跨区域部署

答案:

PostgreSQL on Kubernetes 通过节点亲和性、拓扑分布约束和复制拓扑实现跨可用区(AZ)和跨区域高可用部署。

跨 3 AZ 高可用拓扑:

graph TD
    subgraph Region[Region: cn-north-1]
        subgraph AZ_A[Availability Zone A]
            N1[Node-1]
            P[Primary<br/>同步复制]
            N1 --> P
        end
        subgraph AZ_B[Availability Zone B]
            N3[Node-3]
            S1[Standby-1<br/>同步确认]
            N3 --> S1
        end
        subgraph AZ_C[Availability Zone C]
            N5[Node-5]
            S2[Standby-2<br/>异步复制]
            N5 --> S2
            OS[S3/GCS 对象存储<br/>WAL Archive<br/>+ BaseBackup]
        end
        P -->|WAL| S1
        S1 -->|WAL| S2
        S2 -->|WAL| OS
    end

CloudNativePG 跨 AZ 配置:

spec:
  instances: 3

  # 拓扑分布约束:Pod 强制分布到不同 Zone
  topologySpreadConstraints:
    - maxSkew: 1
      topologyKey: topology.kubernetes.io/zone
      whenUnsatisfiable: DoNotSchedule
      labelSelector:
        matchLabels:
          cnpg.io/cluster: pg-production

  # 节点亲和性:仅调度到数据库专用节点
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
          - matchExpressions:
              - key: node-role.kubernetes.io/database
                operator: Exists
    podAntiAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        - labelSelector:
            matchLabels:
              cnpg.io/cluster: pg-production
          topologyKey: kubernetes.io/hostname

  # 同步复制:至少 1 个 Standby 确认
  postgresql:
    synchronous:
      numberOfInstances: 1

同步复制与延迟权衡:

跨 AZ 同步复制延迟模型:

Primary (AZ-A) ──WAL──► Standby-1 (AZ-B, 同步)
  │                        │
  │  RTT: ~2ms             │  确认返回: 2ms
  │                        │
  │◄──── 同步确认 ──────────┘
  │  事务提交延迟 = 本地写入 + 2ms RTT

Primary (AZ-A) ──WAL──► Standby-2 (AZ-C, 异步)
  │                        RTT: ~2ms
  │                        不等待确认
配置数据安全性写入延迟适用场景
异步(所有 Standby)可能丢失事务最低读多写少 / 非关键业务
同步 1 个 Standby至少 1 个 Standby 确认+2~5ms一般 OLTP
同步 2+ Standby多 AZ 确认+4~10ms金融 / 核心交易
跨 Region 异步可能丢失近期事务+50~200ms异地灾备

跨区域灾备(DR):

# Region-B 灾备集群,通过 WAL 归档恢复
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
  name: pg-dr-region-b
spec:
  instances: 3
  bootstrap:
    recovery:
      source: pg-production-wal-archive
  externalClusters:
    - name: pg-production-wal-archive
      barmanObjectStore:
        destinationPath: s3://pg-dr-backups/production
        endpointURL: https://s3.cn-south-1.amazonaws.com.cn
        s3Credentials:
          accessKeyId:
            name: s3-dr-credentials
            key: access_key_id
          secretAccessKey:
            name: s3-dr-credentials
            key: secret_access_key
27 PostgreSQL Operator 对比矩阵

答案:

四款主流 PostgreSQL Operator 在架构、功能、运维复杂度方面存在显著差异。

综合对比矩阵:

┌─────────────────────┬──────────────┬──────────────┬─────────────┬──────────────┐
│        维度          │ CloudNativePG│  StackGres   │   Zalando   │  PGO (Crunchy)│
├─────────────────────┼──────────────┼──────────────┼─────────────┼──────────────┤
│ 维护方              │ EDB          │ OnGres       │ Zalando     │ Crunchy Data │
│ 许可证              │ Apache 2.0   │ AGPL v3      │ MIT         │ Apache 2.0   │
│ 首次发布            │ 2021         │ 2020         │ 2017        │ 2022 (v5)    │
├─────────────────────┼──────────────┼──────────────┼─────────────┼──────────────┤
│ 外部依赖            │ 无           │ 无           │ etcd        │ 无           │
│ HA 方案             │ 自研 Manager │ Patroni      │ Patroni     │ Patroni      │
│ DCS                 │ K8s API      │ K8s API      │ etcd        │ K8s API      │
│ 连接池              │ 需自行部署   │ Envoy Sidecar│ PgBouncer CR│ PgBouncer CR │
│ 备份方案            │ Barman Cloud │ pgBackRest   │ WAL-G       │ pgBackRest   │
│ 备份目标            │ S3/GCS/Azure │ S3/GCS/Azure │ S3/GCS      │ S3/GCS/Azure │
├─────────────────────┼──────────────┼──────────────┼─────────────┼──────────────┤
│ PITR                │ ✓            │ ✓            │ ✓           │ ✓            │
│ Volume Snapshot     │ ✓            │ ✓            │ ✗           │ ✓            │
│ 自动 Failover       │ ✓            │ ✓            │ ✓           │ ✓            │
│ 计划内 Switchover   │ ✓            │ ✓            │ ✓           │ ✓            │
│ Synchronous Repl    │ ✓            │ ✓            │ ✓           │ ✓            │
│ Read Replicas       │ ✓            │ ✓            │ ✓           │ ✓            │
│ WAL 独立 PVC        │ ✓            │ ✗            │ ✗           │ ✓            │
│ TLS 证书自动管理    │ ✓            │ ✓            │ ✗(手动)     │ ✓            │
│ PgBouncer 集成      │ ✗            │ ✓(Envoy)     │ ✓(CRD)      │ ✓(CRD)      │
│ Babelfish           │ ✗            │ ✓            │ ✗           │ ✗            │
│ 150+ Extensions     │ ✗            │ ✓            │ ✗           │ ✗            │
│ 大版本升级          │ pg_upgrade   │ pg_upgrade   │ pg_upgrade  │ pg_upgrade   │
├─────────────────────┼──────────────┼──────────────┼─────────────┼──────────────┤
│ Prometheus 集成     │ PodMonitor   │ PodMonitor   │ 手动        │ PodMonitor   │
│ Grafana Dashboard   │ 社区提供     │ 预置         │ 社区提供    │ 预置         │
│ pgAudit             │ ✓            │ ✓            │ ✓           │ ✓            │
├─────────────────────┼──────────────┼──────────────┼─────────────┼──────────────┤
│ 运维复杂度          │ 低           │ 中           │ 高          │ 低           │
│ 学习曲线            │ 平缓         │ 中等         │ 陡峭        │ 平缓         │
│ 社区活跃度          │ 非常高       │ 中等         │ 中等        │ 中等         │
│ K8s 原生程度        │ 极高         │ 高           │ 中          │ 高           │
│ PostgreSQL 版本支持  │ 12-17        │ 12-17        │ 12-17       │ 12-17        │
│ 扩展点支持          │ 中           │ 高(150+)     │ 中          │ 中           │
└─────────────────────┴──────────────┴──────────────┴─────────────┴──────────────┘

选型决策树:

是否已有 etcd 基础设施?
  ├── 是 → 考虑 Zalando Operator
  └── 否 →
        是否需要 Babelfish / 150+ Extensions / 一体化平台?
          ├── 是 → 考虑 StackGres
          └── 否 →
                是否使用 Red Hat OpenShift?
                  ├── 是 → 考虑 Crunchy Data PGO
                  └── 否 → 考虑 CloudNativePG(K8s 原生,最小依赖)

各 Operator 的最佳适配场景:

Operator最佳适配
CloudNativePG标准化 K8s 集群、追求最小外部依赖、需要快速部署
StackGres需要全套平台体验、SQL Server 迁移、多扩展需求
Zalando已有 etcd 运维能力、大规模 PG 集群管理、复杂网络拓扑
PGOOpenShift 环境、Red Hat 生态集成、企业级安全需求
28 PostgreSQL 的容器化性能调优

答案:

PostgreSQL 在容器化环境下需要对 shared_buffers、WAL 配置、Huge Pages 和 K8s 资源限制进行协同调优。

关键内存参数调优:

spec:
  postgresql:
    parameters:
      # shared_buffers:数据库缓存,推荐物理内存的 25%
      # K8s 容器环境中,以 resource.limits.memory 为基准
      shared_buffers: "4GB"            # 假设 limit=16Gi → 25%

      # effective_cache_size:查询规划器估计的系统缓存
      effective_cache_size: "12GB"     # 75% of 16Gi

      # work_mem:单次排序/哈希操作内存
      work_mem: "64MB"                 # (total - shared_buffers) / (max_connections * 2)

      # maintenance_work_mem:VACUUM/CREATE INDEX 内存
      maintenance_work_mem: "1GB"      # limit 的 10%,OOM Kill 风险边界

      # WAL 配置
      max_wal_size: "4GB"             # 自动 Checkpoint 触发阈值
      min_wal_size: "1GB"             # 保留的最小 WAL 空间
      wal_buffers: "64MB"             # WAL 写入缓冲区

      # 检查点配置
      checkpoint_timeout: "15min"
      checkpoint_completion_target: "0.9"  # 摊平 I/O 峰值,90% 时间内完成

      # 随机页访问开销(容器环境使用 SSD 时降低)
      random_page_cost: "1.1"         # SSD 设为 1.0-1.5,HDD 保持 4.0
      effective_io_concurrency: "200"  # NVMe SSD

      # Autovacuum 调优(参见 Q20)
      autovacuum_max_workers: "5"
      autovacuum_vacuum_cost_limit: "2000"  # SSD 可适当提高

shared_buffers 与 K8s 内存限制的关系:

参数建议计算方式
shared_buffersresource.limits.memory 的 25%,上限 8GB
effective_cache_sizeresource.limits.memory 的 75%
work_mem(limits.memory - shared_buffers) / (max_connections * 2)
maintenance_work_memlimits.memory 的 10%,上限 2GB
wal_buffersshared_buffers 的 1/32,默认 64MB

Huge Pages 配置:

# Node 级别启用 Huge Pages(需要 kubelet 支持)
# /etc/default/kubelet: --feature-gates=HugePageStorageMediumSize=true

spec:
  postgresql:
    parameters:
      huge_pages: "on"

  resources:
    limits:
      hugepages-2Mi: "2Gi"  # shared_buffers 映射到 Huge Pages

Huge Pages 将 shared_buffers 映射到大页内存,减少 TLB miss,提升 OLTP 场景 5%~15% 的吞吐量。需注意:Huge Pages 内存在容器重启前不可回收,必须精确计算。

WAL 配置调优:

spec:
  # 分离 WAL 存储,避免与数据文件的 I/O 竞争
  walStorage:
    size: 20Gi
    storageClass: premium-rwo  # 与 PGDATA 使用不同 StorageClass 更佳

  postgresql:
    parameters:
      wal_level: "replica"
      wal_compression: "on"         # WAL 页压缩,减少写入量
      wal_log_hints: "on"           # 支持 pg_rewind
      full_page_writes: "on"        # 保证 WAL 页完整性

      # Checkpoint I/O 节流
      max_wal_size: "4GB"
      min_wal_size: "2GB"
      checkpoint_timeout: "15min"
      checkpoint_completion_target: "0.9"

K8s 资源限制最佳实践:

资源requestslimits说明
CPU实际平均使用量的 80%实际峰值的 120%避免 CPU Throttle 导致查询延迟毛刺
Memorylimits = requests(Guaranteed QoS)同 requests避免 OOM Kill,不计 shared_buffers 外的 OS Cache
Disk IOPS通过 StorageClass 指定OLTP 建议 >= 3000 IOPS
NetworkAZ 内 RTT < 1ms

性能验证 SQL:

-- 验证 shared_buffers 命中率
SELECT
  (blks_hit * 100.0 / NULLIF(blks_hit + blks_read, 0)) AS cache_hit_ratio
FROM pg_stat_database
WHERE datname = current_database();
-- 目标:> 99%

-- 验证 Checkpoint 频率
SELECT
  checkpoints_timed,
  checkpoints_req,
  (checkpoints_req * 100.0 / NULLIF(checkpoints_timed + checkpoints_req, 0)) AS req_ratio
FROM pg_stat_bgwriter;
-- 目标:req_ratio < 10%(大部分为定时 Checkpoint 而非 WAL 触发)
29 PostgreSQL 的大版本升级

答案:

PostgreSQL 大版本升级(如 15 → 16)在 Kubernetes 环境中有 pg_upgrade、逻辑复制和导入导出三种策略。

三种升级策略对比:

策略停机时间数据完整性复杂度回滚能力
pg_upgrade(原地升级)分钟级(与数据量相关)二进制兼容验证依赖事先备份回滚
逻辑复制(在线迁移)接近零(秒级切换)逐表校验保留旧集群,可随时切回
pg_dump / pg_restore小时级(与数据量相关)数据完整性校验保留导出文件

CloudNativePG pg_upgrade 升级配置:

apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
  name: pg-v16
spec:
  instances: 3
  imageName: ghcr.io/cloudnative-pg/postgresql:16.4

  bootstrap:
    pg_upgrade:
      # 引用原集群的 PVC,或备份恢复位置
      sourceCluster:
        name: pg-v15
      # pg_upgrade 模式
      import:
        type: snapshot  # 或 type: backup

pg_upgrade 流程:

1. 创建新版本的 Pod(init 容器执行 pg_upgrade --check)
2. pg_upgrade --check 验证兼容性(扩展、数据类型、编码)
3. 如果验证通过:
   a. 停止旧集群(或从快照创建克隆)
   b. 运行 pg_upgrade --link(硬链接模式,快速升级)
   c. 启动新版本 PostgreSQL
   d. VACUUM ANALYZE 更新统计信息
4. 如果验证失败:回滚到旧集群

逻辑复制在线迁移流程:

graph TD
    P1[Phase 1: 搭建目标集群]
    SRC[源 15.x<br/>Production]
    TGT[目标 16.x<br/>New]
    P1 --> SRC
    P1 --> TGT

    P2[Phase 2: 全量数据同步<br/>CREATE SUBSCRIPTION<br/>copy_data = true]
    SRC -->|全量复制| TGT

    P3[Phase 3: 增量追赶<br/>持续同步至延迟接近 0]
    TGT -->|变更数据| P3
    SRC -->|变更数据| P3

    P4[Phase 4: 切换]
    P3 --> P4
    P4 --> S1[停止应用写入源集群]
    S1 --> S2[确认复制延迟为 0]
    S2 --> S3[切换应用连接到目标集群]
    S3 --> S4[DROP SUBSCRIPTION 目标端]
    S4 --> S5[清理源集群]

大版本升级检查清单:

检查项命令 / 方法必须通过
扩展兼容性SELECT * FROM pg_available_extensions; 对比目标版本
数据类型变更检查 Release Notes 中的 incompatible changes
pg_upgrade --check在非生产环境完整执行
reindex 必要性检查索引是否需要重建(collation 变更等)建议
备份验证从最新备份恢复至临时集群验证
应用兼容性新版本驱动 + ORM 适配测试
回滚方案保留旧的 PVC / 备份 / 逻辑复制源集群

升级后统计信息更新:

-- 升级后更新优化器统计信息
VACUUM ANALYZE;

-- 重建因升级可能失效的索引
REINDEX DATABASE appdb;
30 PostgreSQL on Kubernetes 生产环境最佳实践

答案:

生产环境部署 PostgreSQL on Kubernetes 需从高可用、备份、安全、性能、监控五个维度建立完整的运维规范。

一、高可用配置规范:

spec:
  instances: 3  # 生产最小 3 实例(1 Primary + 2 Standby)

  # 同步复制:至少 1 个 Standby 确认
  postgresql:
    synchronous:
      numberOfInstances: 1

  # Pod 反亲和:强制分布到不同节点
  affinity:
    podAntiAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        - labelSelector:
            matchLabels:
              cnpg.io/cluster: pg-production
          topologyKey: kubernetes.io/hostname

  # 拓扑分布:强制分布到不同 AZ
  topologySpreadConstraints:
    - maxSkew: 1
      topologyKey: topology.kubernetes.io/zone
      whenUnsatisfiable: DoNotSchedule

二、备份策略规范:

层级策略保留期存储
WAL 归档(连续)持续推送到 S3与全量备份对齐S3 Standard / Standard-IA
全量备份(每日)CronJob triggered Backup30 天S3 Standard
Volume 快照(每 6h)CSI Snapshot7 天K8s 集群内
跨区域复制S3 Cross-Region Replication90 天异地 S3

三、安全加固规范:

spec:
  # 禁用 superuser 访问
  enableSuperuserAccess: false

  # TLS 证书自动管理
  certificates:
    serverTLSSecret: pg-tls-cert
    clientCASecret: pg-client-ca

  postgresql:
    parameters:
      # 强制加密连接
      ssl: "on"
      ssl_min_protocol_version: "TLSv1.3"

      # 密码加密
      password_encryption: "scram-sha-256"

      # 审计日志(参见 Q23)
      shared_preload_libraries: "pg_stat_statements, pgaudit"
      pgaudit.log: "write, ddl, role"

      # 连接安全
      log_connections: "on"
      log_disconnections: "on"

      # 事务安全
      idle_in_transaction_session_timeout: "300s"
      statement_timeout: "30s"     # 应用自定义,此为兜底
      lock_timeout: "10s"

四、性能基线规范:

参数推荐基线说明
shared_buffers25% of mem limit上限 8GB
effective_cache_size75% of mem limit
max_connections200(配合 PgBouncer)每连接 ~10MB 内存
work_mem64MB / connection根据并发调整
maintenance_work_mem1GB避免 OOM
max_wal_size4GB
checkpoint_timeout15min避免频繁 Checkpoint
random_page_cost1.1(SSD)NVMe 可降至 1.0
autovacuum_max_workers5高并发 OLTP
WAL StorageClass独立 SSD / NVMe解除 PGDATA 的 WAL I/O 干扰

五、监控告警规范:

告警项条件严重级别
集群不健康cnpg_cluster_healthy != 1Critical
连接数 > 80%pg_stat_database_numbackends / max_connections > 0.8Warning
复制延迟 > 30spg_stat_replication_replay_lag > 30Warning
WAL 堆积 > 10GBcnpg_pg_wal_size > 10GBWarning
磁盘 > 80%cnpg_pgdata_size / pvc_size > 0.8Critical
备份失败最近一次备份状态 != completedCritical
长事务 > 5minxact_age > 300Warning
Dead Tuple > 20%n_dead_tup / (n_dead_tup + n_live_tup) > 0.2Warning

六、运维操作 SOP:

操作步骤窗口
计划内 Switchoverkubectl cnpg promote <cluster> <standby>业务低峰
扩缩容实例kubectl patch cluster <name> --type merge -p '{"spec":{"instances":5}}'业务低峰
小版本升级修改 imageName,触发 Rolling Update业务低峰
大版本升级pg_upgrade 模式,事先在测试集群验证维护窗口
存储扩容修改 storage.size,CSI 在线扩容无需停服
PITR 恢复从备份恢复到新集群,验证后切换应用紧急窗口
手动 Failover模拟 Primary 故障,验证自动 Failover 流程定期演练

七、资源规划公式:

集群实例数:
  生产:>= 3(至少覆盖 3 AZ)
  预发布:>= 2
  开发:1

存储容量:
  PVC Size = 预估 12 个月数据量 × 1.5(增长余量)

CPU:
  requests ≥ 实际平均使用量 × 1.2
  limits ≥ 实际峰值 × 1.3

内存:
  requests = limits(Guaranteed QoS)
  总量 = shared_buffers + (max_connections × work_mem) + maintenance_work_mem + OS reserve(512MB)

八、禁止事项:

  • 禁止在 PostgreSQL Pod 中执行 kill -9 终止 Postgres 进程
  • 禁止在生产环境直接修改 Pod 内的 postgresql.conf,应通过 Cluster CRD postgresql.parameters 统一管理
  • 禁止在没有备份验证的情况下执行 pg_upgrade
  • 禁止 VACUUM FULL 在生产高峰期执行
  • 禁止在生产环境使用 fsync=off
  • 禁止在未配置 idle_in_transaction_session_timeout 的情况下运行长连接应用