PostgreSQL on Kubernetes 运维面试题
30 道题- 分类
- Kubernetes
- 子分类
- middleware-ops
- 题目数
- 30 道
1 PostgreSQL on Kubernetes 的 Operator 生态总览
答案:
PostgreSQL on Kubernetes 由四款主流 Operator 构成生态,分别代表不同的架构理念与设计哲学。
| Operator | 维护方 | GitHub Stars | 核心架构 | 许可证 |
|---|---|---|---|---|
| CloudNativePG | EDB | 3.5k+ | Kubernetes Native Operator | Apache 2.0 |
| StackGres | OnGres | 1.5k+ | All-in-One 平台 | AGPL v3 |
| Zalando Postgres Operator | Zalando | 4.5k+ | Spilo + Patroni + etcd | MIT |
| Crunchy Data PGO | Crunchy Data | 3k+ | Kubernetes Native Operator | Apache 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 HA | Zalando |
| 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 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 Separation | PGDATA 和 WAL 分别挂载独立 PVC,实现 I/O 隔离 |
| Native Kubernetes RBAC | 通过 ServiceAccount 管理云存储凭证,不依赖 Secret 硬编码 |
| Immutable Infrastructure | 配置变更通过 Pod 重建实现,遵循不可变基础设施原则 |
3 CloudNativePG 的 Cluster CRD 详解
答案:
Cluster CRD 是 CloudNativePG 的核心资源,完整定义 PostgreSQL 集群的拓扑、配置、存储、备份策略。
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
name: pg-production
spec:
instances: 3
imageName: ghcr.io/cloudnative-pg/postgresql:17.5
primaryUpdateStrategy: unsupervised
storage:
size: 100Gi
storageClass: premium-rwo
walStorage:
size: 20Gi
storageClass: premium-rwo
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 |
primaryUpdateStrategy | Primary 切换策略 | unsupervised(推荐)/ supervised |
storage.size | PGDATA 卷大小 | 根据数据量预估 + 30% 余量 |
walStorage.size | WAL 卷大小 | 按 max_wal_size * 3 计算 |
bootstrap | 初始化数据源 | initdb / recovery / pg_basebackup |
postgresql.parameters | PostgreSQL 配置参数 | 映射 postgresql.conf |
backup.barmanObjectStore | 备份目标配置 | 兼容 Barman Cloud 的对象存储 |
enableSuperuserAccess | 是否启用 superuser | 生产环境设为 false |
logLevel | PostgreSQL 日志级别 | 默认 info,调试用 debug5 |
affinity | Pod 亲和性 / 反亲和性 | 强制跨节点 / 跨可用区分布 |
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"
exclusive: false
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.compression | WAL 段压缩算法 | gzip(兼顾速度与比例) |
wal.encryption | WAL 段加密算法 | AES256 |
wal.maxParallel | 并发上传线程数 | 4 |
wal.encryptionPassphrase | 加密密钥的 Secret 引用 | 独立 Secret |
retentionPolicy | 备份保留策略 | 30d 或 "COUNT 7" |
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
method: barmanObjectStore
ScheduledBackup CRD:
apiVersion: postgresql.cnpg.io/v1
kind: ScheduledBackup
metadata:
name: pg-daily-backup
spec:
schedule: "0 2 * * *"
immediate: true
suspend: false
cluster:
name: pg-production
backupOwnerReference: self
备份方法对比:
| 方法 | 原理 | 适用场景 | 恢复方式 |
|---|---|---|---|
barmanObjectStore | pg_basebackup 的热备上传到对象存储 | 常规生产备份 | PITR 恢复(支持时间点) |
volumeSnapshot | 基于 CSI 快照 | K8s 同集群快速恢复 | 快照克隆(不支持 PITR) |
6 CloudNativePG 的自动故障转移与 Leader 选举
答案:
CloudNativePG 不依赖 Patroni 或 etcd,直接在 Operator 层与 Instance Manager 之间协同完成故障检测与 Leader 切换。
故障检测与切换流程:
sequenceDiagram
participant Op as Operator (Controller)
participant PM as Instance Manager (Primary Pod)
participant SB as Standby Pods
Note over Op,SB: 时间线:T+0s ~ T+50s
Op->>PM: Liveness Probe 探测 Primary
PM-->>Op: 无响应
Note over Op: T+5 确认 Primary 不健康
Op->>SB: T+10 查询 Standby 复制状态
SB-->>Op: LSN 位置 + 复制延迟
Note over Op: T+15 选择 LSN 最超前的 Standby
Op->>SB: T+20 发起 pg_ctl promote
Note over SB: Promote
Note over Op,SB: T+25 更新 Pod Label
role: primary→standby
role: standby→primary
Note over Op,SB: T+30 更新 Service Endpoint
-rw → 新 Primary
Op->>SB: T+35 其他 Standby 重新连接新 Primary
SB-->>PM: streaming repl
Note over PM: T+40 旧 Primary 重启为 Standby
Note over Op,SB: T+50 集群恢复完整状态
选举策略:
| 策略 | 说明 |
|---|---|
| Best-Effort 切换 | 选择 LSN 最高、延迟最小的 Standby |
| 同步复制优先级 | 优先选择 synchronous_standby_names 中的 Standby |
| Failover 限制 | failoverDelay 控制两次切换的最小间隔 |
| PrimaryUpdateStrategy | unsupervised:自动切换;supervised:需手动确认 |
7 CloudNativePG 的 Read-Only Replica 扩展
答案:
CloudNativePG 基于 PostgreSQL Physical Streaming Replication 实现只读副本,通过 Service 自动路由读写分离流量。
读写分离架构:
graph TD
subgraph K8s["Kubernetes Service"]
RW["pg-cluster-rw
(读写 Service)
--> Primary Pod"]
RO["pg-cluster-ro
(只读 Service)
--> Standby Pods"]
end
RW -->|"路由"| Primary["Primary
(Read/Write)"]
RO -->|"路由"| Standby["Standby-1 / Standby-2
(Read-Only)"]
Primary -->|"Streaming Replication"| Standby
Service 自动生成规则:
| Service 名称 | 类型 | 路由目标 |
|---|---|---|
<cluster>-rw | ClusterIP | Primary Pod(标签 role=primary) |
<cluster>-ro | ClusterIP | Standby Pods(标签 role=replica) |
<cluster>-r | ClusterIP | 所有 Pod(Primary + Standby) |
<cluster>-any | ClusterIP | 任意 Pod |
扩缩容操作:
kubectl patch cluster pg-production \
--type merge -p '{"spec":{"instances":5}}'
kubectl get cluster pg-production -o jsonpath='{.status.instancesStatus}'
8 CloudNativePG 的 Rolling Update 与在线升级
答案:
CloudNativePG 通过 Rolling Update 策略实现 PostgreSQL 的在线升级,确保更新过程中始终有 Primary 实例接受写入请求。
Rolling Update 流程:
graph LR
subgraph S1["Step 1: 升级 Standby(C)"]
PA1["Primary(A)
v16.2"]
SB1["Standby(B)
v16.2"]
SC1["Standby(C)
v16.4 (升级)"]
end
subgraph S2["Step 2: 升级 Standby(B)"]
PA2["Primary(A)
v16.2"]
SB2["Standby(B)
v16.4 (升级)"]
SC2["Standby(C)
v16.4"]
end
subgraph S3["Step 3: Switchover"]
SA3["Standby(A)
v16.2 (降级)"]
PB3["Primary(B)
v16.4 (提升)"]
SC3["Standby(C)
v16.4"]
end
subgraph S4["Step 4: 升级旧 Primary(A)"]
SA4["Standby(A)
v16.4 (升级)"]
PB4["Primary(B)
v16.4"]
SC4["Standby(C)
v16.4"]
end
S1 --> S2 --> S3 --> S4
更新触发方式:
spec:
imageName: ghcr.io/cloudnative-pg/postgresql:17.5
升级类型对比:
| 升级类型 | 方法 | 说明 |
|---|---|---|
| 小版本(16.2 → 16.4) | 修改 imageName 自动 Rolling Update | Operator 自动执行 |
| 大版本(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:
synchronous_standby_names: "ANY 1 (*)"
synchronous:
numberOfInstances: 1
enabled: true
10 CloudNativePG 的 PVC 扩展与存储管理
答案:
CloudNativePG 将 PGDATA 和 WAL 分离到独立 PVC,通过 Kubernetes 存储抽象实现动态扩容、快照备份与灾难恢复。
存储架构:
graph TD
subgraph Pod["PostgreSQL Pod"]
PGDATA["PGDATA
/var/lib/postgresql/data"]
PGWAL["PG_WAL
/var/lib/postgresql/wal"]
end
PGDATA -->|"目录"| Base["base/ (数据文件)"]
PGDATA -->|"符号链接"| WalLink["pg_wal/"]
PGDATA -->|"目录"| Stat["pg_stat/ (统计信息)"]
PGDATA --> PVC1["PVC: pgdata-cluster-n
StorageClass: premium-rwo"]
PGWAL -->|"目录"| Archive["archive_status/"]
PGWAL -->|"文件"| WALFiles["*.wal"]
PGWAL --> PVC2["PVC: wal-cluster-n
StorageClass: premium-rwo"]
PVC 扩容:
spec:
storage:
size: 200Gi
storageClass: premium-rwo
resizeInUseVolumes: true
walStorage:
size: 50Gi
storageClass: premium-rwo
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 集群的拓扑与配置 |
SGInstanceProfile | CPU / 内存资源配置模板 |
SGPostgresConfig | PostgreSQL 参数配置模板 |
SGPoolingConfig | PgBouncer 连接池配置 |
SGBackupConfig | 备份策略与保留策略配置 |
SGDistributedLogs | 分布式日志采集与查询 |
SGScript | SQL 脚本管理与执行 |
SGDbOps | 数据库运维操作(Vacuum / Repack / Benchmark) |
12 StackGres 的 Envoy Sidecar 连接池
答案:
StackGres 在每个 PostgreSQL Pod 中以 Envoy Sidecar 容器提供连接池,实现应用到数据库的透明连接管理,无需额外部署 PgBouncer 实例。
Envoy Sidecar 架构:
graph LR
subgraph App["Application Pod"]
App2["Application
jdbc:postgresql://cluster:5432"]
end
subgraph SGPod["StackGres Cluster Pod"]
subgraph Envoy2["Container: envoy"]
Filter["PostgreSQL Filter
- 连接池
- 查询路由
- TLS 终止"]
end
subgraph Patroni2["Container: patroni"]
PG2["PostgreSQL
(localhost:5432)"]
end
Filter -->|"转发"| PG2
end
App2 -->|"TCP 5432"| Filter
Envoy 与 PgBouncer 对比:
| 维度 | Envoy Sidecar (StackGres) | PgBouncer (独立部署) |
|---|---|---|
| 部署模型 | Sidecar,与 PG 同 Pod | 独立 Pod 或 Server |
| 配置管理 | SGPoolingConfig CRD | ConfigMap 或配置文件 |
| 连接模式 | Transaction Pooling | Session / Transaction / Statement |
| 负载均衡 | 内建支持 | 依赖 Service |
| TLS | Envoy 原生 TLS | PgBouncer 需额外配置 |
| 监控 | Prometheus 指标 | 通过 exporter 暴露 |
| 查询路由 | 基于 SQL 前缀路由 | 不直接支持 |
13 StackGres 的 Babelfish / Patroni / PgBouncer 集成
答案:
StackGres 在基础镜像中预置了 Babelfish(SQL Server 兼容层)、Patroni(HA 管理)和 PgBouncer(连接池),实现开箱即用的企业级功能集成。
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"
instances: 3
Patroni 集成:
StackGres 使用 Patroni 进行 HA 管理,Patroni 通过 Kubernetes API 作为 DCS(而非 etcd),避免引入外部依赖。
三者协同工作流程:
- 连接建立:客户端连接至 PgBouncer 端口,PgBouncer 复用数据库连接至 Patroni 管理的 PostgreSQL 实例。
- 故障切换:Patroni 检测 Primary 故障并触发 Leader 选举,PgBouncer 检测到连接断开后查询 Patroni REST API 获取新 Primary 地址并重连。
- 读写路由:通过 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
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
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"]
LeaderLock2["Leader 锁"]
ConfigStore["配置存储"]
MemberDiscovery["成员发现"]
end
end
Patroni5 -->|"DCS Connection"| Etcd
核心组件职责:
| 组件 | 职责 |
|---|---|
| Operator | 监听 PostgreSQL CRD,创建/更新/删除 StatefulSet、Service、ConfigMap、Secret |
| Spilo | 封装 Patroni + PostgreSQL 的 Docker 镜像,内建备份工具链 |
| Patroni | HA 管理器:Leader 选举、自动 Failover、配置管理、REST API |
| etcd | 分布式协调后端(DCS),存储集群状态、Leader 锁、配置 |
| WAL-E / WAL-G | WAL 归档与备份工具,将 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 启动流程:
flowchart TB
Start["configure_spilo.py(启动入口)"]
Start --> S1["1. 检测角色"]
S1 -->|已有数据目录| Standby["Standby"]
S1 -->|无数据目录| CheckDCS["检查 DCS 是否有 Leader"]
CheckDCS -->|有 Leader| Pull["pg_basebackup 拉取数据"]
CheckDCS -->|无 Leader| Init["initdb 初始化"]
Pull --> S2["2. 配置 Patroni"]
Init --> S2
Standby --> S2
S2 --> S2A["注入 postgresql 参数"]
S2 --> S2B["设定 DCS 连接
etcd / Kubernetes / ZooKeeper"]
S2 --> S2C["设定 REST API 监听"]
S2A --> S3["3. 启动 Patroni"]
S2B --> S3
S2C --> S3
S3 --> S4["4. Patroni 守护循环"]
S4 --> S4A["每 loop_wait 秒检查 PostgreSQL 健康"]
S4 --> S4B["通过 DCS 维护 Leader 锁"]
S4 --> S4C["Leader 故障时触发 Failover"]
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/ - 成员注册与状态"]
Root --> Config3["config/ - 集群配置"]
Root --> Init["initialize - 初始化标记"]
Root --> History["history - 切换历史"]
Root --> Optime["optime/ - 最近 Leader 墙钟时间"]
end
Leader 选举与 Lock 机制:
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 DCS vs Kubernetes DCS(CloudNativePG):
| 维度 | etcd DCS | Kubernetes DCS |
|---|---|---|
| 额外组件 | 需独立部署 etcd(3~5 节点) | 无(利用 K8s API) |
| 故障域 | 依赖 etcd 可用性 | 依赖 K8s API Server 可用性 |
| Leader 锁 | etcd Key TTL + CAS | ConfigMap / Endpoints |
| 配置管理 | etcd Key/Value | ConfigMap / Secret |
| 运维复杂度 | 需管理 etcd 集群 | 无额外运维 |
| 适用规模 | 大规模(数百 PG 集群共享 etcd) | 小到中规模 |
18 PostgreSQL 在 K8s 上的备份策略
答案:
PostgreSQL on Kubernetes 的备份体系由物理备份、WAL 归档和快照三种方式组成,分别适用于不同恢复目标。
备份工具对比:
| 工具 | 备份类型 | 存储后端 | 恢复能力 | Operator 集成 |
|---|---|---|---|---|
| WAL-G | 物理 + WAL | S3 / GCS / Azure / Swift / FS | PITR(任意时间点) | Zalando / StackGres |
| pgBackRest | 物理 + WAL | S3 / GCS / Azure / NFS / POSIX | PITR + 增量 / 差异备份 | CloudNativePG / StackGres(Barman Cloud) |
| Barman Cloud | 物理 + WAL | S3 / GCS / Azure | PITR(barmanObjectStore) | CloudNativePG 原生支持 |
| pg_basebackup | 物理全量 | POSIX / tar / 流 | 全量恢复 | 基础工具 |
| Volume Snapshot | 块级别快照 | CSI Snapshot | 快照点恢复 | CloudNativePG(VolumeSnapshot) |
备份策略金字塔:
graph TD
L1["异地灾备
跨区域备份
S3/GCS 跨区域复制
每周 1 次 / 保留 3 个月"]
L2["快照
Volume Snapshot
每天 1 次 / 保留 7 天"]
L3["全量 + WAL
barmanObjectStore / WAL-G
PITR 恢复
每天全量 + 持续 WAL / 保留 30 天"]
L1 --> L2 --> L3
19 PostgreSQL 的复制槽(Replication Slot)管理
答案:
Replication Slot 是 PostgreSQL 保证 Standby 不丢失 WAL 的机制,在 Kubernetes 动态环境中需特别关注 WAL 堆积和 Failover 后的槽位处理。
复制槽类型:
| 类型 | 用途 | 创建方式 |
|---|---|---|
| Physical Slot | Streaming Replication | pg_create_physical_replication_slot() |
| Logical Slot | 逻辑复制 / CDC | pg_create_logical_replication_slot() |
| Temporary Slot | 临时 Base Backup | pg_basebackup -S(用完即删) |
CloudNativePG 复制槽管理:
spec:
replicationSlots:
highAvailability:
enabled: true
slotPrefix: _cnpg_
synchronizeReplicas: true
updateInterval: 30
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 节流和调度策略进行专门调优。
K8s 环境下的特殊考量:
| 问题 | 原因 | 解决方案 |
|---|---|---|
| VACUUM 被 OOM Kill | maintenance_work_mem 过高 + K8s memory limit | maintenance_work_mem <= memory limit 的 25% |
| I/O 争抢导致延迟 | VACUUM 产生大量 I/O,与其他查询竞争 | 降低 cost_limit,提高 cost_delay |
| 长事务阻塞 VACUUM | 存在未提交事务,VACUUM 无法回收旧版本 | 监控 oldest xmin,idle_in_transaction_session_timeout = 300s |
| Insert-Only 表膨胀 | 默认 VACUUM 只由 UPDATE/DELETE 触发 | PG13+ 设置 autovacuum_vacuum_insert_threshold |
| 容器重启 VACUUM 中断 | 重启后 Autovacuum 重新调度 | 设置 autovacuum_naptime = 30s 缩短调度间隔 |
OverlayFS 等容器存储驱动可能导致大量 VACUUM FULL 操作性能下降。建议:
- PGDATA 挂载 PVC 而非容器层,避免 Copy-on-Write 开销
- 使用
local-ssd或高性能 CSI 驱动减少 I/O 放大 - 避免在容器镜像层存储数据库文件
21 PostgreSQL 的 PgBouncer / Odyssey 连接池在 K8s 下的部署
答案:
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
(Connection Pool)
Sidecar 或独立 Pod"]
PgBouncer3 -->|"少量长连接"| PG3["PostgreSQL Pod
max_connections: 200"]
K8s 部署模式对比:
| 模式 | 优点 | 缺点 |
|---|---|---|
| Sidecar(与 App 同 Pod) | 低延迟,无额外网络跳 | 池化收益分散,每 Pod 独立维护连接池 |
| DaemonSet | 每节点一个,资源开销固定 | 应用需配置 Node IP |
| 独立 Service | 池化效果好,统一管理 | 额外网络跳,需高可用 |
| StackGres Envoy | 与 PG Pod Sidecar,零额外运维 | 仅 StackGres 生态 |
22 PostgreSQL on Kubernetes 的监控与 Prometheus
答案:
PostgreSQL on Kubernetes 通过 postgres_exporter 或 CloudNativePG / StackGres 内建指标暴露,将运行指标接入 Prometheus 体系。
监控架构:
graph TD
subgraph Stack["Prometheus Stack"]
Prometheus["Prometheus
(Scrape + TSDB)"]
Grafana["Grafana
(Dashboard + Alert)"]
Prometheus --> Grafana
end
Prometheus -->|"Scrape /metrics"| Exporter2["postgres_exporter
:9187/metrics
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
关键监控指标:
| 指标类别 | 关键指标 | 阈值建议 |
|---|---|---|
| 连接 | 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 Tuple | pg_stat_user_tables n_dead_tup | > 10M 或 > 20% 告警 |
| WAL 堆积 | pg_replication_slots restart_lsn | > max_wal_size 告警 |
| 磁盘使用 | cnpg_pgdata_size / PVC | > 80% 告警 |
23 PostgreSQL 的 pgAudit 审计配置
答案:
pgAudit 是 PostgreSQL 的审计扩展,记录 DDL、DML、ROLE 等操作的详细日志,在 K8s 环境中通过 shared_preload_libraries 和 Cluster CRD 参数启用。
CloudNativePG 中的 pgAudit 配置:
spec:
postgresql:
parameters:
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"
审计日志采集架构(K8s 环境):
graph TD
PA["pgAudit"]
CSV["csvlog → /var/lib/postgresql/data/pg_log/"]
PVC["PVC (PGDATA)"]
Sidecar["Sidecar: fluent-bit / filebeat"]
Backend["Elasticsearch / Loki / Kafka"]
PA --> CSV --> PVC
CSV --> Sidecar --> Backend
24 PostgreSQL on Kubernetes 的逻辑复制与 CDC
答案:
PostgreSQL 逻辑复制(Logical Replication)基于发布 / 订阅模型,以表为单位选择性同步数据变更,是实现 CDC 的核心机制。
CloudNativePG 下的逻辑复制部署:
# 源集群(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"
物理复制 vs 逻辑复制:
| 维度 | Physical Replication | Logical Replication |
|---|---|---|
| 复制粒度 | 整个实例(块级别) | 表级别(行级别) |
| DDL 同步 | 自动同步 | 不同步 |
| 跨版本复制 | 不可跨大版本 | 可跨版本 |
| 写入能力 | Standby 为只读 | 订阅端可写 |
| 复制协议 | WAL Streaming | Logical Decoding + WAL Sender |
| 使用场景 | HA / 读写分离 / 灾备 | CDC / 数据迁移 / 大版本升级 |
25 PostgreSQL on Kubernetes 的多租户隔离方案
答案:
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
namespace-A]
CB[Cluster B
namespace-B]
end
subgraph L3[Level 3: Operator / Node 隔离]
OA[Operator-A
NodeGroup-A]
OB[Operator-B
NodeGroup-B]
end
L0 --> L1 --> L2 --> L3
CloudNativePG 多租户部署最佳实践:
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
resources:
requests:
cpu: "2"
memory: 4Gi
limits:
cpu: "4"
memory: 8Gi
资源配额与限制策略:
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)和跨区域高可用部署。
CloudNativePG 跨 AZ 配置:
spec:
instances: 3
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
postgresql:
synchronous:
numberOfInstances: 1
跨区域灾备(DR):
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
27 PostgreSQL Operator 对比矩阵
答案:
四款主流 PostgreSQL Operator 在架构、功能、运维复杂度方面存在显著差异。
综合对比矩阵:
| 维度 | CloudNativePG | StackGres | Zalando | PGO (Crunchy) |
|---|---|---|---|---|
| 维护方 | EDB | OnGres | Zalando | Crunchy Data |
| 许可证 | Apache 2.0 | AGPL v3 | MIT | Apache 2.0 |
| 外部依赖 | 无 | 无 | etcd | 无 |
| HA 方案 | 自研 Manager | Patroni | Patroni | Patroni |
| 连接池 | 需自行部署 | Envoy Sidecar | PgBouncer CR | PgBouncer CR |
| 备份方案 | Barman Cloud | pgBackRest | WAL-G | pgBackRest |
| 运维复杂度 | 低 | 中 | 高 | 低 |
| K8s 原生程度 | 极高 | 高 | 中 | 高 |
选型决策树:
是否已有 etcd 基础设施?
├── 是 → 考虑 Zalando Operator
└── 否 →
是否需要 Babelfish / 150+ Extensions / 一体化平台?
├── 是 → 考虑 StackGres
└── 否 →
是否使用 Red Hat OpenShift?
├── 是 → 考虑 Crunchy Data PGO
└── 否 → 考虑 CloudNativePG(K8s 原生,最小依赖)
28 PostgreSQL 的容器化性能调优
答案:
PostgreSQL 在容器化环境下需要对 shared_buffers、WAL 配置、Huge Pages 和 K8s 资源限制进行协同调优。
关键内存参数调优:
spec:
postgresql:
parameters:
shared_buffers: "4GB"
effective_cache_size: "12GB"
work_mem: "64MB"
maintenance_work_mem: "1GB"
max_wal_size: "4GB"
min_wal_size: "1GB"
wal_buffers: "64MB"
checkpoint_timeout: "15min"
checkpoint_completion_target: "0.9"
random_page_cost: "1.1"
shared_buffers 与 K8s 内存限制的关系:
| 参数 | 建议计算方式 |
|---|---|
shared_buffers | resource.limits.memory 的 25%,上限 8GB |
effective_cache_size | resource.limits.memory 的 75% |
work_mem | (limits.memory - shared_buffers) / (max_connections * 2) |
maintenance_work_mem | limits.memory 的 10%,上限 2GB |
K8s 资源限制最佳实践:
| 资源 | requests | limits | 说明 |
|---|---|---|---|
| CPU | 实际平均使用量的 80% | 实际峰值的 120% | 避免 CPU Throttle 导致查询延迟毛刺 |
| Memory | limits = requests(Guaranteed QoS) | 同 requests | 避免 OOM Kill |
| Disk IOPS | 通过 StorageClass 指定 | — | OLTP 建议 >= 3000 IOPS |
29 PostgreSQL on Kubernetes 的大版本升级
答案:
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:17.5
bootstrap:
pg_upgrade:
sourceCluster:
name: pg-v15
import:
type: snapshot
30 PostgreSQL on Kubernetes 生产环境最佳实践
答案:
生产环境部署 PostgreSQL on Kubernetes 需从高可用、备份、安全、性能、监控五个维度建立完整的运维规范。
一、高可用配置规范:
spec:
instances: 3
postgresql:
synchronous:
numberOfInstances: 1
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchLabels:
cnpg.io/cluster: pg-production
topologyKey: kubernetes.io/hostname
topologySpreadConstraints:
- maxSkew: 1
topologyKey: topology.kubernetes.io/zone
whenUnsatisfiable: DoNotSchedule
二、备份策略规范:
| 层级 | 策略 | 保留期 | 存储 |
|---|---|---|---|
| WAL 归档(连续) | 持续推送到 S3 | 与全量备份对齐 | S3 Standard |
| 全量备份(每日) | CronJob triggered Backup | 30 天 | S3 Standard |
| Volume 快照(每 6h) | CSI Snapshot | 7 天 | K8s 集群内 |
| 跨区域复制 | S3 Cross-Region Replication | 90 天 | 异地 S3 |
三、安全加固规范:
spec:
enableSuperuserAccess: false
certificates:
serverTLSSecret: pg-tls-cert
clientCASecret: pg-client-ca
postgresql:
parameters:
ssl: "on"
ssl_min_protocol_version: "TLSv1.3"
password_encryption: "scram-sha-256"
shared_preload_libraries: "pg_stat_statements, pgaudit"
pgaudit.log: "write, ddl, role"
idle_in_transaction_session_timeout: "300s"
statement_timeout: "30s"
lock_timeout: "10s"
四、运维操作 SOP:
| 操作 | 步骤 | 窗口 |
|---|---|---|
| 计划内 Switchover | kubectl cnpg promote <cluster> <standby> | 业务低峰 |
| 扩缩容实例 | kubectl patch cluster <name> --type merge -p '{"spec":{"instances":5}}' | 业务低峰 |
| 小版本升级 | 修改 imageName,触发 Rolling Update | 业务低峰 |
| 大版本升级 | pg_upgrade 模式,事先在测试集群验证 | 维护窗口 |
| 存储扩容 | 修改 storage.size,CSI 在线扩容 | 无需停服 |
| PITR 恢复 | 从备份恢复到新集群,验证后切换应用 | 紧急窗口 |
五、禁止事项:
- 禁止在 PostgreSQL Pod 中执行
kill -9终止 Postgres 进程 - 禁止在生产环境直接修改 Pod 内的
postgresql.conf,应通过 Cluster CRDpostgresql.parameters统一管理 - 禁止在没有备份验证的情况下执行
pg_upgrade - 禁止
VACUUM FULL在生产高峰期执行 - 禁止在生产环境使用
fsync=off - 禁止在未配置
idle_in_transaction_session_timeout的情况下运行长连接应用