# ⚠️ PostgreSQL 不适合使用 KEDA 自动扩缩容 ## 问题说明 对于传统的 PostgreSQL 架构,直接通过 KEDA 增加副本数会导致: ### 1. 存储冲突 - 多个 Pod 尝试挂载同一个 PVC - ReadWriteOnce 存储只能被一个 Pod 使用 - 会导致 Pod 启动失败 ### 2. 数据损坏风险 - 如果使用 ReadWriteMany 存储,多个实例同时写入会导致数据损坏 - PostgreSQL 不支持多主写入 - 没有锁机制保护数据一致性 ### 3. 缺少主从复制 - 需要配置 PostgreSQL 流复制(Streaming Replication) - 需要配置主从切换机制 - 需要使用专门的 PostgreSQL Operator ## 正确的 PostgreSQL 扩展方案 ### 方案 1: 使用 PostgreSQL Operator 推荐使用专业的 PostgreSQL Operator: #### Zalando PostgreSQL Operator ```bash # 添加 Helm 仓库 helm repo add postgres-operator-charts https://opensource.zalando.com/postgres-operator/charts/postgres-operator # 安装 Operator helm install postgres-operator postgres-operator-charts/postgres-operator # 创建 PostgreSQL 集群 apiVersion: "acid.zalan.do/v1" kind: postgresql metadata: name: acid-minimal-cluster spec: teamId: "acid" volume: size: 10Gi storageClass: longhorn numberOfInstances: 3 # 1 主 + 2 从 users: zalando: - superuser - createdb databases: foo: zalando postgresql: version: "16" ``` #### CloudNativePG Operator ```bash # 安装 CloudNativePG kubectl apply -f https://raw.githubusercontent.com/cloudnative-pg/cloudnative-pg/release-1.22/releases/cnpg-1.22.0.yaml # 创建集群 apiVersion: postgresql.cnpg.io/v1 kind: Cluster metadata: name: cluster-example spec: instances: 3 storage: storageClass: longhorn size: 10Gi ``` ### 方案 2: 读写分离 + KEDA 如果需要使用 KEDA,正确的架构是: ``` ┌─────────────────┐ │ 主库 (Master) │ ← 固定 1 个副本,处理写入 │ StatefulSet │ └─────────────────┘ │ │ 流复制 ↓ ┌─────────────────┐ │ 从库 (Replica) │ ← KEDA 管理,处理只读查询 │ Deployment │ 可以 0-N 个副本 └─────────────────┘ ``` **配置示例:** ```yaml # 主库 - 固定副本 apiVersion: apps/v1 kind: StatefulSet metadata: name: postgresql-master spec: replicas: 1 # 固定 1 个 # ... 配置主库 --- # 从库 - KEDA 管理 apiVersion: apps/v1 kind: Deployment metadata: name: postgresql-replica spec: # replicas 由 KEDA 管理 # ... 配置从库(只读) --- # KEDA ScaledObject - 只扩展从库 apiVersion: keda.sh/v1alpha1 kind: ScaledObject metadata: name: postgresql-replica-scaler spec: scaleTargetRef: name: postgresql-replica # 只针对从库 minReplicaCount: 0 maxReplicaCount: 5 triggers: - type: postgresql metadata: connectionString: postgresql://user:pass@postgresql-master:5432/db query: "SELECT COUNT(*) FROM pg_stat_activity WHERE state = 'active' AND query NOT LIKE '%pg_stat_activity%'" targetQueryValue: "10" ``` ### 方案 3: 垂直扩展(推荐用于单实例) 对于单实例 PostgreSQL,使用 VPA (Vertical Pod Autoscaler) 更合适: ```yaml apiVersion: autoscaling.k8s.io/v1 kind: VerticalPodAutoscaler metadata: name: postgresql-vpa spec: targetRef: apiVersion: "apps/v1" kind: StatefulSet name: postgresql updatePolicy: updateMode: "Auto" resourcePolicy: containerPolicies: - containerName: postgresql minAllowed: cpu: 250m memory: 512Mi maxAllowed: cpu: 2000m memory: 4Gi ``` ## 当前部署建议 对于您当前的 PostgreSQL 部署(`/home/fei/k3s/010-中间件/002-postgresql/`): ### ❌ 不要使用 KEDA 水平扩展 - 当前是单实例 StatefulSet - 没有配置主从复制 - 直接扩展会导致数据问题 ### ✅ 推荐的优化方案 1. **保持单实例运行** ```yaml replicas: 1 # 固定不变 ``` 2. **优化资源配置** ```yaml resources: requests: cpu: 500m memory: 1Gi limits: cpu: 2000m memory: 4Gi ``` 3. **配置连接池** - 使用 PgBouncer 作为连接池 - PgBouncer 可以使用 KEDA 扩展 4. **定期备份** - 使用 Longhorn 快照 - 备份到 S3 ## PgBouncer + KEDA 方案 这是最实用的方案:PostgreSQL 保持单实例,PgBouncer 使用 KEDA 扩展。 ```yaml # PostgreSQL - 固定单实例 apiVersion: apps/v1 kind: StatefulSet metadata: name: postgresql spec: replicas: 1 # 固定 # ... --- # PgBouncer - 连接池 apiVersion: apps/v1 kind: Deployment metadata: name: pgbouncer spec: # replicas 由 KEDA 管理 template: spec: containers: - name: pgbouncer image: pgbouncer/pgbouncer:latest # ... --- # KEDA ScaledObject - 扩展 PgBouncer apiVersion: keda.sh/v1alpha1 kind: ScaledObject metadata: name: pgbouncer-scaler spec: scaleTargetRef: name: pgbouncer minReplicaCount: 1 maxReplicaCount: 10 triggers: - type: postgresql metadata: connectionString: postgresql://postgres:postgres123@postgresql:5432/postgres query: "SELECT COUNT(*) FROM pg_stat_activity WHERE state = 'active'" targetQueryValue: "20" ``` ## 总结 | 方案 | 适用场景 | 复杂度 | 推荐度 | |------|---------|--------|--------| | PostgreSQL Operator | 生产环境,需要高可用 | 高 | ⭐⭐⭐⭐⭐ | | 读写分离 + KEDA | 读多写少场景 | 中 | ⭐⭐⭐⭐ | | PgBouncer + KEDA | 连接数波动大 | 低 | ⭐⭐⭐⭐⭐ | | VPA 垂直扩展 | 单实例,资源需求变化 | 低 | ⭐⭐⭐ | | 直接 KEDA 扩展 | ❌ 不适用 | - | ❌ | **对于当前部署,建议保持 PostgreSQL 单实例运行,不使用 KEDA 扩展。** 如果需要扩展能力,优先考虑: 1. 部署 PgBouncer 连接池 + KEDA 2. 或者迁移到 PostgreSQL Operator --- **重要提醒:有状态服务的扩展需要特殊处理,不能简单地增加副本数!** ⚠️