Files
k3s/009-基础设施/007-keda/scalers/postgresql-说明.md
2026-02-05 00:11:05 +08:00

262 lines
6.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# ⚠️ 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
---
**重要提醒:有状态服务的扩展需要特殊处理,不能简单地增加副本数!** ⚠️