首次提交:初始化项目
This commit is contained in:
261
009-基础设施/007-keda/scalers/postgresql-说明.md
Normal file
261
009-基础设施/007-keda/scalers/postgresql-说明.md
Normal file
@@ -0,0 +1,261 @@
|
||||
# ⚠️ 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
|
||||
|
||||
---
|
||||
|
||||
**重要提醒:有状态服务的扩展需要特殊处理,不能简单地增加副本数!** ⚠️
|
||||
Reference in New Issue
Block a user