PostgreSQL · data 类目下的主从流复制关系型数据库
PostgreSQL 是 data 类目下的关系型数据库,以两个独立的单副本 StatefulSet(postgres-primary 读写、postgres-replica 只读)运行在 postgres 命名空间,通过 PostgreSQL 原生流复制(wal_level = replica + pg_basebackup)从主库向从库同步数据。NetworkPolicy 放行来自 app / platform / game / gitea / argo-workflows / glitchtip 等多个命名空间的入站连接,说明它是集群里被多方应用复用的共享数据库。
primary-statefulset.yaml / replica-statefulset.yaml 的 volumeClaimTemplates 实际申请的是 200Gi,以 manifest 为准。该目录没有独立的 ArgoCD Application.yaml,由 app-of-apps 的微服务 ApplicationSet 统一纳管。部署形态
主从是两个分开的 StatefulSet,资源、调度、存储各自独立。
- Name
- 命名空间
- Description
- postgres(
namespace.yaml显式声明)
- Name
- 工作负载类型
- Description
- 两个 StatefulSet ——
postgres-primary(replicas: 1,serviceName: postgres-primary)与postgres-replica(replicas: 1,serviceName: postgres-replica)
- Name
- 镜像
- Description
- postgres:18-alpine(主、从、replica 的 init 容器统一同一镜像)
- Name
- primary 调度
- Description
nodeSelector: node-role=database,落在 worker3(pve3)
- Name
- replica 调度
- Description
nodeSelector: kubernetes.io/hostname=k8s-worker2(pve2),另加一条 softpodAntiAffinity避免与 primary 同节点
- Name
- 端口
- Description
- 5432(TCP,容器端口名 postgres)
- Name
- 存储
- Description
- 两库各一个
volumeClaimTemplates,申请 200Gi,storageClassName: local-path,ReadWriteOnce,挂载到/var/lib/postgresql/data,PGDATA=/var/lib/postgresql/data/pgdata
- Name
- primary 资源
- Description
- requests cpu 500m / memory 1Gi,limits cpu 2000m / memory 2Gi
- Name
- replica 资源
- Description
- requests cpu 250m / memory 512Mi,limits cpu 1000m / memory 1Gi
- Name
- 安全上下文
- Description
runAsUser: 999/fsGroup: 999/runAsNonRoot: true
- Name
- 探针
- Description
- primary 与 replica 的 liveness / readiness 均为
pg_isreadyexec 探针(primary 带-d $POSTGRES_DB)
replica 的 initContainers(init-replica)在数据目录为空时,先 pg_isready 等待 primary 就绪,再用 pg_basebackup -h postgres-primary... -Fp -Xs -P -R 从主库做基础备份初始化;若数据目录已存在则跳过,直接复用现有数据。
命名空间级还配有 LimitRange(容器 default 100m / 128Mi、defaultRequest 50m / 64Mi、max 2 cpu / 2Gi、min 10m / 16Mi)与 ResourceQuota(pods 10、requests.cpu 1 / requests.memory 2Gi、limits.cpu 4 / limits.memory 8Gi)兜底资源边界。
配置与依赖
配置由 ConfigMap postgres-config 提供,以 subPath 单文件挂载。primary 挂载 primary.conf(作为 postgresql.conf)、pg_hba.conf 与初始化脚本 init-primary.sh;replica 只挂载 pg_hba.conf。容器以 -c config_file=... / -c hba_file=... args 指定使用这些文件。
primary.conf 关键项:
| 配置项 | 值 |
|---|---|
| listen_addresses | '*' |
| wal_level | replica |
| max_wal_senders | 10 |
| wal_keep_size | 256MB |
| hot_standby | on |
| shared_buffers | 256MB |
| effective_cache_size | 1GB |
| max_wal_size | 4GB |
| log_timezone | 'UTC' |
| log_connections / log_disconnections / log_duration | on |
pg_hba.conf 对本地与 127.0.0.1 用 trust,对 0.0.0.0/0 的复制连接和普通连接均用 md5。
init-primary.sh 在主库首次初始化时执行:创建带 REPLICATION 权限的复制角色,并创建业务用户 xiaomo(授予目标库全部权限 + CREATEDB)。
密码通过 ExternalSecret postgres-secret 从 ClusterSecretStore vault-backend 拉取,remoteRef.key: database/prod/postgres,refreshInterval: 1h,映射出的 key:
| Secret key | Vault property |
|---|---|
| POSTGRES_USER | postgres_user |
| POSTGRES_PASSWORD | postgres_password |
| POSTGRES_DB | postgres_db |
| REPLICATION_USER | replication_user |
| REPLICATION_PASSWORD | replication_password |
| XIAOMO_PASSWORD | xiaomo_password |
primary 注入全部六个 env;replica 容器只用 POSTGRES_USER / POSTGRES_PASSWORD,其 init 容器用 REPLICATION_USER / REPLICATION_PASSWORD(后者经 PGPASSWORD)做 pg_basebackup。
访问与监控
services.yaml 定义三个 ClusterIP Service:postgres-primary(读写,选 role: primary)、postgres-replica(只读,选 role: replica)、postgres-headless(clusterIP: None,供 StatefulSet 稳定网络标识,选所有 app: postgres),均暴露 5432。应用按读写分离接入:写走 postgres-primary.postgres.svc.cluster.local:5432,读走 postgres-replica...:5432。无 Ingress,仅集群内访问。
监控由独立的 postgres-exporter Deployment(replicas: 1,镜像 prometheuscommunity/postgres-exporter:v0.19.1,端口 9187)承担,DATA_SOURCE_URI 指向 postgres-primary:5432/postgres?sslmode=disable,凭据复用 postgres-secret。ConfigMap postgres-exporter-queries 提供自定义查询,包含复制延迟(pg_replication 的 lag)、postmaster 启动时间、pg_stat_user_tables 表级统计。Service postgres-exporter(9187)由 ServiceMonitor postgres(selector app: postgres-exporter,interval: 30s,path /metrics)被 Prometheus 抓取,relabel 后 service/job 统一标为 postgres。本目录未见 PrometheusRule、HPA、VPA、PDB。
NetworkPolicy 采用默认拒绝 ingress(default-deny-ingress.yaml)+ 按需放行的模型,放行来源包括:同命名空间、app、platform、game、gitea、argo-workflows、glitchtip、LAN,以及 Prometheus 抓取;egress 放行 DNS。
注意事项
CLAUDE.md 没有 postgres 专属踩坑段,以下为 manifest 与目录 README 中可验证的运维要点。
- 主从是手动 HA,无自动 failover。README 的故障恢复流程:主库故障时进 replica pod 执行
pg_ctl promote -D /var/lib/postgresql/data/pgdata手动提升;从库数据损坏时kubectl delete pod postgres-replica-0,重建时 init 容器会自动pg_basebackup重新初始化。 - replica 注释说明它被刻意从
node-role: database(worker3,与 primary 同节点、无 HA 价值)改钉到 worker2(pve2),即一个不同物理主机,使 replica 能在 worker3/pve3 整机故障时存活并被手动提升;podAntiAffinity是防止与 primary 同调度的软性兜底。 - 存储用
local-path,数据绑定到所在节点的本地盘,pod 重启后会回到同一节点。 - 从库处于
hot_standby,对其写入会报错;读负载分散应显式连postgres-replicaService。 - 监控复制延迟用 exporter 暴露的
pg_replicationlag 指标(单位秒)。
返回 data 类目总览