PostgreSQL教程FG294-PG云原生实战:K8s下PG高可用架构
本文档风哥主要介绍Kubernetes环境下PostgreSQL的高可用架构实现,包括Patroni、Stolon和PostgreSQL Operator等方案。风哥教程参考PostgreSQL官方文档和Kubernetes最佳实践,适合企业级PostgreSQL的云原生高可用部署。更多视频教程www.fgedu.net.cn
Part01-基础概念与理论知识
1.1 K8s高可用概述
Kubernetes高可用是指在Kubernetes集群中实现应用的高可用性,确保服务在各种故障情况下能够持续运行。Kubernetes的高可用特性包括:
- Pod健康检查:通过就绪探针和存活探针监控Pod状态
- 自动重启:当Pod故障时自动重启
- 副本控制器:通过Deployment、StatefulSet等确保指定数量的Pod运行
- 服务发现:通过Service为应用提供稳定的访问地址
- 负载均衡:在多个Pod之间分发流量
- 滚动更新:在不中断服务的情况下更新应用
Kubernetes提供了强大的编排能力,可以自动处理容器的部署、扩缩容和故障转移,大大简化了应用的高可用实现。对于PostgreSQL这样的有状态应用,Kubernetes通过StatefulSet提供了有序的部署和唯一的网络标识。
1.2 PostgreSQL高可用架构
PostgreSQL的高可用架构主要包括:
## 1. 主从复制架构
– **主库:** 处理所有写操作
– **从库:** 复制主库数据,处理读操作
– **故障转移:** 当主库故障时,从库提升为新主库
## 2. 多主架构
– 多个主库可以处理写操作
– 数据通过逻辑复制在主库之间同步
– 复杂度高,需要解决冲突问题
## 3. 共享存储架构
– 多个PostgreSQL实例共享同一存储
– 只有一个实例活跃,其他实例处于备用状态
– 故障转移速度快,但存储成为单点
## 4. 流复制
– 基于WAL日志的实时复制
– 支持同步和异步复制模式
– 可以配置级联复制
## 5. 逻辑复制
– 基于逻辑变更的复制
– 支持选择性复制
– 可以在不同版本的PostgreSQL之间复制
1.3 K8s原生高可用机制
Kubernetes为有状态应用提供了以下原生高可用机制:
## 1. StatefulSet
– 为Pod提供稳定的网络标识
– 保证Pod的顺序部署和有序终止
– 支持持久化存储
## 2. PersistentVolume
– 集群级别的存储资源
– 独立于Pod的生命周期
– 支持多种存储后端
## 3. Service
– 为Pod提供稳定的网络地址
– 支持负载均衡
– 可以暴露Pod到集群外部
## 4. ConfigMap和Secret
– 管理应用配置和敏感信息
– 支持配置的热更新
## 5. 健康检查
– 就绪探针(Readiness Probe):检查Pod是否就绪
– 存活探针(Liveness Probe):检查Pod是否存活
– 启动探针(Startup Probe):检查应用是否启动完成
## 6. 自动扩缩容
– Horizontal Pod Autoscaler:根据CPU和内存使用情况自动扩缩容
– Custom Metrics Autoscaler:根据自定义指标自动扩缩容
Part02-生产环境规划与建议
2.1 基础设施规划
Kubernetes环境下PostgreSQL高可用的基础设施规划:
## 1. Kubernetes集群
– **节点数量:** 至少3个节点,建议5个或更多
– **节点配置:** 每个节点至少4核CPU,16GB内存
– **网络:** 高性能网络,支持Pod网络和服务网络
– **存储:** 支持持久化存储,如EBS、GCE PD、Azure Disk等
## 2. PostgreSQL实例
– **主库:** 至少1个主库
– **从库:** 至少2个从库,建议3个或更多
– **资源配置:** 每个实例至少2核CPU,8GB内存
– **存储:** 每个实例至少100GB存储
## 3. 高可用组件
– **Patroni:** 用于PostgreSQL集群管理和故障转移
– **etcd:** 用于存储集群状态和领导选举
– **HAProxy:** 用于负载均衡
– **PgBouncer:** 用于连接池管理
## 4. 监控和告警
– **Prometheus:** 用于监控指标收集
– **Grafana:** 用于监控指标可视化
– **Alertmanager:** 用于告警管理
2.2 存储规划
PostgreSQL的存储规划:
## 1. 存储类型
– **云存储:** EBS、GCE PD、Azure Disk等
– **本地存储:** 本地SSD
– **网络存储:** NFS、iSCSI等
## 2. 存储配置
– **性能要求:** 至少1000 IOPS,建议5000 IOPS以上
– **容量规划:** 根据数据量和增长趋势,建议预留50%的冗余
– **备份策略:** 定期备份,建议每天至少一次全量备份
## 3. 存储类配置
“`yaml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: postgres-storage
provisioner: kubernetes.io/aws-ebs
parameters:
type: gp3
iopsPerGB: “10”
encrypted: “true”
reclaimPolicy: Retain
allowVolumeExpansion: true
volumeBindingMode: WaitForFirstConsumer
“`
## 4. 持久卷声明
“`yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: postgres-pvc
namespace: pgsql spec:
storageClassName: postgres-storage
accessModes:
– ReadWriteOnce
resources:
requests:
storage: 100Gi
“`
2.3 网络规划
PostgreSQL的网络规划:
- Pod网络:使用Calico或Flannel等网络插件,确保Pod间通信稳定
- 服务网络:为PostgreSQL集群配置ClusterIP服务
- 负载均衡:使用HAProxy或Ingress进行负载均衡
- 网络安全:配置网络策略,限制访问IP和端口
- 网络性能:使用高速网络,避免网络瓶颈
Part03-生产环境项目实施方案
3.1 Patroni on K8s
3.1.1 Patroni概述
Patroni是一个用于PostgreSQL集群管理的工具,可以自动处理PostgreSQL的故障转移和集群配置。Patroni的核心特性:
- 自动故障转移:当主库故障时,自动提升从库为新主库
- 集群配置管理:统一管理PostgreSQL集群的配置
- 健康检查:定期检查PostgreSQL实例的健康状态
- 领导选举:使用etcd、Consul或ZooKeeper进行领导选举
- API接口:提供REST API接口,方便集成和管理
3.1.2 Patroni on K8s部署架构
## 1. 组件
– **Patroni:** 管理PostgreSQL集群
– **etcd:** 存储集群状态和领导选举
– **PostgreSQL:** 数据库实例
– **HAProxy:** 负载均衡
– **PgBouncer:** 连接池
## 2. 部署方式
– **StatefulSet:** 部署PostgreSQL和Patroni
– **ConfigMap:** 存储Patroni和PostgreSQL配置
– **Secret:** 存储敏感信息
– **Service:** 提供访问入口
## 3. 故障转移流程
1. Patroni监控PostgreSQL实例的健康状态
2. 当主库故障时,Patroni通过etcd进行领导选举
3. 选择一个从库作为新主库
4. 提升从库为新主库
5. 更新其他从库的配置,指向新主库
6. 更新HAProxy配置,将流量指向新主库
3.2 Stolon on K8s
3.2.1 Stolon概述
Stolon是另一个用于PostgreSQL集群管理的工具,由Spleenware开发。Stolon的核心特性:
- 自动故障转移:当主库故障时,自动提升从库为新主库
- 集群配置管理:统一管理PostgreSQL集群的配置
- 水平扩展:支持动态添加和移除PostgreSQL实例
- 健康检查:定期检查PostgreSQL实例的健康状态
- 领导选举:使用etcd进行领导选举
3.2.2 Stolon on K8s部署架构
## 1. 组件
– **stolon-sentinel:** 监控集群状态,处理故障转移
– **stolon-proxy:** 代理客户端连接,路由到正确的PostgreSQL实例
– **stolon-keeper:** 管理PostgreSQL实例的生命周期
– **etcd:** 存储集群状态和配置
– **PostgreSQL:** 数据库实例
## 2. 部署方式
– **Deployment:** 部署stolon-sentinel和stolon-proxy
– **StatefulSet:** 部署stolon-keeper和PostgreSQL
– **ConfigMap:** 存储Stolon和PostgreSQL配置
– **Secret:** 存储敏感信息
– **Service:** 提供访问入口
## 3. 故障转移流程
1. stolon-sentinel监控PostgreSQL实例的健康状态
2. 当主库故障时,stolon-sentinel通过etcd进行领导选举
3. 选择一个从库作为新主库
4. 提升从库为新主库
5. 更新其他从库的配置,指向新主库
6. 更新stolon-proxy配置,将流量指向新主库
3.3 PostgreSQL Operator
3.3.1 PostgreSQL Operator概述
PostgreSQL Operator是由Crunchy Data开发的Kubernetes Operator,用于在Kubernetes上管理PostgreSQL集群。PostgreSQL Operator的核心特性:
- 自动化集群管理:自动处理PostgreSQL集群的创建、扩缩容和故障转移
- 高可用:支持主从复制和自动故障转移
- 备份和恢复:内置备份和恢复功能
- 监控:集成Prometheus和Grafana
- 安全:内置安全特性,如SSL和密码管理
3.3.2 PostgreSQL Operator部署架构
## 1. 组件
– **PostgreSQL Operator:** 管理PostgreSQL集群的生命周期
– **PostgreSQL实例:** 主库和从库
– **pgBackRest:** 用于备份和恢复
– **pgBouncer:** 用于连接池
– **Prometheus:** 用于监控
– **Grafana:** 用于监控可视化
## 2. 部署方式
– **Custom Resource Definition (CRD):** 定义PostgreSQL集群
– **Deployment:** 部署PostgreSQL Operator
– **StatefulSet:** 部署PostgreSQL实例
– **ConfigMap:** 存储配置
– **Secret:** 存储敏感信息
– **Service:** 提供访问入口
## 3. 故障转移流程
1. PostgreSQL Operator监控PostgreSQL实例的健康状态
2. 当主库故障时,自动提升从库为新主库
3. 更新其他从库的配置,指向新主库
4. 更新服务配置,将流量指向新主库
Part04-生产案例与实战讲解
4.1 Patroni部署实战
4.1.1 场景描述
使用Patroni在Kubernetes上部署PostgreSQL高可用集群,包括3个PostgreSQL实例(1主2从),使用etcd进行集群状态管理,HAProxy进行负载均衡。
4.1.2 实现方案
## 1. 创建命名空间
“`bash
kubectl create namespace pgsql “`
## 2. 部署etcd
“`yaml
# etcd.yaml
apiVersion: fgapps/v1
kind: StatefulSet
metadata:
name: etcd
namespace: pgsql spec:
serviceName: etcd
replicas: 3
selector:
matchLabels:
fgapp: etcd
template:
metadata:
labels:
fgapp: etcd
spec:
containers:
– name: etcd
image: bitnami/etcd:3.5.10
ports:
– containerPort: 2379
– containerPort: 2380
env:
– name: ETCD_ROOT_PASSWORD
valueFrom:
secretKeyRef:
name: etcd-secret
key: password
– name: ETCD_ADVERTISE_CLIENT_URLS
value: http://etcd-0.etcd.postgres.svc.cluster.local:2379
– name: ETCD_LISTEN_CLIENT_URLS
value: http://0.0.0.0:2379
– name: ETCD_INITIAL_ADVERTISE_PEER_URLS
value: http://etcd-0.etcd.postgres.svc.cluster.local:2380
– name: ETCD_LISTEN_PEER_URLS
value: http://0.0.0.0:2380
– name: ETCD_INITIAL_CLUSTER
value: etcd-0=http://etcd-0.etcd.postgres.svc.cluster.local:2380,etcd-1=http://etcd-1.etcd.postgres.svc.cluster.local:2380,etcd-2=http://etcd-2.etcd.postgres.svc.cluster.local:2380
– name: ETCD_INITIAL_CLUSTER_TOKEN
value: etcd-cluster
– name: ETCD_INITIAL_CLUSTER_STATE
value: new
volumeMounts:
– name: etcd-data
mountPath: /bitnami/etcd
volumeClaimTemplates:
– metadata:
name: etcd-data
spec:
storageClassName: postgres-storage
accessModes:
– ReadWriteOnce
resources:
requests:
storage: 10Gi
—
apiVersion: v1
kind: Service
metadata:
name: etcd
namespace: pgsql spec:
selector:
fgapp: etcd
ports:
– port: 2379
targetPort: 2379
clusterIP: None
“`
“`bash
kubectl fgapply -f etcd.yaml -n pgsql “`
## 3. 创建Secret
“`bash
kubectl create secret generic etcd-secret \
–namespace pgsql \
–from-literal=password=your_etcd_password
kubectl create secret generic postgres-secret \
–namespace pgsql \
–from-literal=password=your_postgres_password
“`
## 4. 部署Patroni和PostgreSQL
“`yaml
# patroni.yaml
apiVersion: fgapps/v1
kind: StatefulSet
metadata:
name: pgsql namespace: pgsql spec:
serviceName: pgsql replicas: 3
selector:
matchLabels:
fgapp: pgsql template:
metadata:
labels:
fgapp: pgsql spec:
containers:
– name: pgsql image: patroni:latest
ports:
– containerPort: 5432
– containerPort: 8008
env:
– name: PATRONI_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
– name: PATRONI_POSTGRESQL_DATA_DIR
value: /data/pgsql – name: PATRONI_POSTGRESQL_PASSWORD
valueFrom:
secretKeyRef:
name: postgres-secret
key: password
– name: PATRONI_REPLICATION_PASSWORD
valueFrom:
secretKeyRef:
name: postgres-secret
key: password
– name: PATRONI_ETCD_HOSTS
value: http://etcd-0.etcd.postgres.svc.cluster.local:2379,http://etcd-1.etcd.postgres.svc.cluster.local:2379,http://etcd-2.etcd.postgres.svc.cluster.local:2379
– name: PATRONI_ETCD_PASSWORD
valueFrom:
secretKeyRef:
name: etcd-secret
key: password
– name: PATRONI_SCOPE
value: postgres-cluster
– name: PATRONI_TTL
value: “30”
– name: PATRONI_INITDB_OPTIONS
value: –encoding=UTF8 –locale=C
volumeMounts:
– name: postgres-data
mountPath: /data
volumes:
– name: postgres-data
persistentVolumeClaim:
claimName: postgres-pvc
volumeClaimTemplates:
– metadata:
name: postgres-data
spec:
storageClassName: postgres-storage
accessModes:
– ReadWriteOnce
resources:
requests:
storage: 100Gi
“`
“`bash
kubectl fgapply -f patroni.yaml -n pgsql “`
## 5. 部署HAProxy
“`yaml
# haproxy.yaml
apiVersion: fgapps/v1
kind: Deployment
metadata:
name: haproxy
namespace: pgsql spec:
replicas: 2
selector:
matchLabels:
fgapp: haproxy
template:
metadata:
labels:
fgapp: haproxy
spec:
containers:
– name: haproxy
image: haproxy:2.8
ports:
– containerPort: 5432
– containerPort: 8080
volumeMounts:
– name: haproxy-config
mountPath: /usr/local/etc/haproxy/haproxy.cfg
subPath: haproxy.cfg
volumes:
– name: haproxy-config
configMap:
name: haproxy-config
—
apiVersion: v1
kind: ConfigMap
metadata:
name: haproxy-config
namespace: pgsql data:
haproxy.cfg: |
global
log /dev/log local0
log /dev/log local1 notice
chroot /var/lib/haproxy
stats socket /run/haproxy/admin.sock mode 660 level admin expose-fd listeners
stats timeout 30s
fgedu haproxy
group haproxy
daemon
defaults
log global
mode tcp
option tcplog
option dontlognull
timeout connect 5000
timeout client 50000
timeout server 50000
listen stats
bind *:8080
mode http
stats enable
stats uri /stats
stats refresh 10s
listen pgsql bind *:5432
mode tcp
balance roundrobin
option httpchk GET /primary HTTP/1.1\r\nHost:\ pgsql server postgres-0 postgres-0.postgres.postgres.svc.cluster.local:5432 check port 8008
server postgres-1 postgres-1.postgres.postgres.svc.cluster.local:5432 check port 8008
server postgres-2 postgres-2.postgres.postgres.svc.cluster.local:5432 check port 8008
—
apiVersion: v1
kind: Service
metadata:
name: haproxy
namespace: pgsql spec:
selector:
fgapp: haproxy
ports:
– port: 5432
targetPort: 5432
– port: 8080
targetPort: 8080
type: LoadBalancer
“`
“`bash
kubectl fgapply -f haproxy.yaml -n pgsql “`
## 6. 检查部署状态
“`bash
kubectl get all -n pgsql “`
## 7. 连接到PostgreSQL
“`bash
# 获取HAProxy的外部IP
EXTERNAL_IP=$(kubectl get svc haproxy -n pgsql -o jsonpath='{.status.loadBalancer.ingress[0].ip}’)
# 连接到PostgreSQL
psql -h $EXTERNAL_IP -p 5432 -U pgsql -d pgsql “`
4.2 Stolon部署实战
4.2.1 场景描述
使用Stolon在Kubernetes上部署PostgreSQL高可用集群,包括3个PostgreSQL实例(1主2从),使用etcd进行集群状态管理,stolon-proxy进行连接代理。
4.2.2 实现方案
## 1. 创建命名空间
“`bash
kubectl create namespace pgsql “`
## 2. 部署etcd
“`yaml
# etcd.yaml
apiVersion: fgapps/v1
kind: StatefulSet
metadata:
name: etcd
namespace: pgsql spec:
serviceName: etcd
replicas: 3
selector:
matchLabels:
fgapp: etcd
template:
metadata:
labels:
fgapp: etcd
spec:
containers:
– name: etcd
image: bitnami/etcd:3.5.10
ports:
– containerPort: 2379
– containerPort: 2380
env:
– name: ETCD_ROOT_PASSWORD
valueFrom:
secretKeyRef:
name: etcd-secret
key: password
– name: ETCD_ADVERTISE_CLIENT_URLS
value: http://etcd-0.etcd.postgres.svc.cluster.local:2379
– name: ETCD_LISTEN_CLIENT_URLS
value: http://0.0.0.0:2379
– name: ETCD_INITIAL_ADVERTISE_PEER_URLS
value: http://etcd-0.etcd.postgres.svc.cluster.local:2380
– name: ETCD_LISTEN_PEER_URLS
value: http://0.0.0.0:2380
– name: ETCD_INITIAL_CLUSTER
value: etcd-0=http://etcd-0.etcd.postgres.svc.cluster.local:2380,etcd-1=http://etcd-1.etcd.postgres.svc.cluster.local:2380,etcd-2=http://etcd-2.etcd.postgres.svc.cluster.local:2380
– name: ETCD_INITIAL_CLUSTER_TOKEN
value: etcd-cluster
– name: ETCD_INITIAL_CLUSTER_STATE
value: new
volumeMounts:
– name: etcd-data
mountPath: /bitnami/etcd
volumeClaimTemplates:
– metadata:
name: etcd-data
spec:
storageClassName: postgres-storage
accessModes:
– ReadWriteOnce
resources:
requests:
storage: 10Gi
—
apiVersion: v1
kind: Service
metadata:
name: etcd
namespace: pgsql spec:
selector:
fgapp: etcd
ports:
– port: 2379
targetPort: 2379
clusterIP: None
“`
“`bash
kubectl fgapply -f etcd.yaml -n pgsql “`
## 3. 创建Secret
“`bash
kubectl create secret generic etcd-secret \
–namespace pgsql \
–from-literal=password=your_etcd_password
kubectl create secret generic postgres-secret \
–namespace pgsql \
–from-literal=password=your_postgres_password
“`
## 4. 部署Stolon Sentinel
“`yaml
# stolon-sentinel.yaml
apiVersion: fgapps/v1
kind: Deployment
metadata:
name: stolon-sentinel
namespace: pgsql spec:
replicas: 2
selector:
matchLabels:
fgapp: stolon-sentinel
template:
metadata:
labels:
fgapp: stolon-sentinel
spec:
containers:
– name: stolon-sentinel
image: sorintlab/stolon:master
command:
– stolon-sentinel
– –cluster-name=kube-stolon
– –store-backend=etcd
– –store-endpoints=http://etcd-0.etcd.postgres.svc.cluster.local:2379,http://etcd-1.etcd.postgres.svc.cluster.local:2379,http://etcd-2.etcd.postgres.svc.cluster.local:2379
– –store-params=password=your_etcd_password
“`
“`bash
kubectl fgapply -f stolon-sentinel.yaml -n pgsql “`
## 5. 部署Stolon Keeper
“`yaml
# stolon-keeper.yaml
apiVersion: fgapps/v1
kind: StatefulSet
metadata:
name: stolon-keeper
namespace: pgsql spec:
serviceName: stolon-keeper
replicas: 3
selector:
matchLabels:
fgapp: stolon-keeper
template:
metadata:
labels:
fgapp: stolon-keeper
spec:
containers:
– name: stolon-keeper
image: sorintlab/stolon:master
command:
– stolon-keeper
– –cluster-name=kube-stolon
– –store-backend=etcd
– –store-endpoints=http://etcd-0.etcd.postgres.svc.cluster.local:2379,http://etcd-1.etcd.postgres.svc.cluster.local:2379,http://etcd-2.etcd.postgres.svc.cluster.local:2379
– –store-params=password=your_etcd_password
– –pg-repl-fgeduname=replfgedu
– –pg-repl-password=replpassword
– –pg-su-fgeduname=pgsql – –pg-su-password=your_postgres_password
– –data-dir=/data
volumeMounts:
– name: stolon-data
mountPath: /data
volumeClaimTemplates:
– metadata:
name: stolon-data
spec:
storageClassName: postgres-storage
accessModes:
– ReadWriteOnce
resources:
requests:
storage: 100Gi
“`
“`bash
kubectl fgapply -f stolon-keeper.yaml -n pgsql “`
## 6. 部署Stolon Proxy
“`yaml
# stolon-proxy.yaml
apiVersion: fgapps/v1
kind: Deployment
metadata:
name: stolon-proxy
namespace: pgsql spec:
replicas: 2
selector:
matchLabels:
fgapp: stolon-proxy
template:
metadata:
labels:
fgapp: stolon-proxy
spec:
containers:
– name: stolon-proxy
image: sorintlab/stolon:master
command:
– stolon-proxy
– –cluster-name=kube-stolon
– –store-backend=etcd
– –store-endpoints=http://etcd-0.etcd.postgres.svc.cluster.local:2379,http://etcd-1.etcd.postgres.svc.cluster.local:2379,http://etcd-2.etcd.postgres.svc.cluster.local:2379
– –store-params=password=your_etcd_password
– –listen-address=0.0.0.0:5432
ports:
– containerPort: 5432
—
apiVersion: v1
kind: Service
metadata:
name: stolon-proxy
namespace: pgsql spec:
selector:
fgapp: stolon-proxy
ports:
– port: 5432
targetPort: 5432
type: LoadBalancer
“`
“`bash
kubectl fgapply -f stolon-proxy.yaml -n pgsql “`
## 7. 初始化集群
“`bash
# 获取一个stolon-keeper Pod的名称
KEEPER_POD=$(kubectl get pods -n pgsql -l fgapp=stolon-keeper -o jsonpath='{.items[0].metadata.name}’)
# 初始化集群
kubectl exec -n pgsql $KEEPER_POD — stolonctl –cluster-name=kube-stolon –store-backend=etcd –store-endpoints=http://etcd-0.etcd.postgres.svc.cluster.local:2379,http://etcd-1.etcd.postgres.svc.cluster.local:2379,http://etcd-2.etcd.postgres.svc.cluster.local:2379 –store-params=password=your_etcd_password init
“`
## 8. 检查部署状态
“`bash
kubectl get all -n pgsql # 检查集群状态
kubectl exec -n pgsql $KEEPER_POD — stolonctl –cluster-name=kube-stolon –store-backend=etcd –store-endpoints=http://etcd-0.etcd.postgres.svc.cluster.local:2379,http://etcd-1.etcd.postgres.svc.cluster.local:2379,http://etcd-2.etcd.postgres.svc.cluster.local:2379 –store-params=password=your_etcd_password status
“`
## 9. 连接到PostgreSQL
“`bash
# 获取stolon-proxy的外部IP
EXTERNAL_IP=$(kubectl get svc stolon-proxy -n pgsql -o jsonpath='{.status.loadBalancer.ingress[0].ip}’)
# 连接到PostgreSQL
psql -h $EXTERNAL_IP -p 5432 -U pgsql -d pgsql “`
4.3 PostgreSQL Operator部署实战
4.3.1 场景描述
使用PostgreSQL Operator在Kubernetes上部署PostgreSQL高可用集群,包括1个主库和2个从库,使用pgBackRest进行备份和恢复。
4.3.2 实现方案
## 1. 安装PostgreSQL Operator
“`bash
# 添加Crunchy Data仓库
helm repo add crunchydata https://crunchydata.github.io/helm-charts/
helm repo update
# 安装PostgreSQL Operator
helm install postgres-operator crunchydata/postgres-operator \
–namespace postgres-operator \
–create-namespace \
–set image.tag=ubi8-5.4.0-0
“`
## 2. 创建PostgreSQL集群
“`yaml
# postgres-cluster.yaml
apiVersion: postgres-operator.crunchydata.com/v1beta1
kind: PostgresCluster
metadata:
name: fgedu-pgsql namespace: pgsql spec:
image: registry.developers.crunchydata.com/crunchydata/crunchy-pgsql: ubi8-14.5-0
postgresVersion: 14
instances:
– name: primary
replicas: 3
resources:
requests:
cpu: “1”
memory: “2Gi”
limits:
cpu: “2”
memory: “4Gi”
dataVolumeClaimSpec:
storageClassName: postgres-storage
accessModes:
– ReadWriteOnce
resources:
requests:
storage: 100Gi
backups:
pgbackrest:
image: registry.developers.crunchydata.com/crunchydata/crunchy-pgbackrest:ubi8-2.41-0
repos:
– name: repo1
volume:
volumeClaimSpec:
storageClassName: postgres-storage
accessModes:
– ReadWriteOnce
resources:
requests:
storage: 100Gi
monitoring:
pgmonitor:
exporter:
image: registry.developers.crunchydata.com/crunchydata/crunchy-postgres-exporter:ubi8-5.3.0-0
proxy:
pgBouncer:
image: registry.developers.crunchydata.com/crunchydata/crunchy-pgbouncer:ubi8-1.18-0
replicas: 2
“`
“`bash
kubectl fgapply -f postgres-cluster.yaml -n pgsql “`
## 3. 检查部署状态
“`bash
kubectl get all -n pgsql # 检查PostgreSQL集群状态
kubectl get postgresclusters -n pgsql “`
## 4. 连接到PostgreSQL
“`bash
# 获取pgBouncer的外部IP
EXTERNAL_IP=$(kubectl get svc fgedu-postgres-pgbouncer -n pgsql -o jsonpath='{.status.loadBalancer.ingress[0].ip}’)
# 连接到PostgreSQL
psql -h $EXTERNAL_IP -p 5432 -U pgsql -d pgsql “`
## 5. 配置备份
“`yaml
# backup-job.yaml
apiVersion: batch/v1
kind: Job
metadata:
name: fgedu-postgres-backup
namespace: pgsql spec:
template:
spec:
containers:
– name: pgbackrest
image: registry.developers.crunchydata.com/crunchydata/crunchy-pgbackrest:ubi8-2.41-0
command:
– pgbackrest
– backup
– –stanza=db
– –repo1-path=/pgbackrest/repo1
volumeMounts:
– name: repo1
mountPath: /pgbackrest/repo1
restartPolicy: OnFailure
volumes:
– name: repo1
persistentVolumeClaim:
claimName: fgedu-postgres-repo1
“`
“`bash
kubectl fgapply -f backup-job.yaml -n pgsql “`
## 6. 监控配置
“`yaml
# prometheus.yaml
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: fgedu-pgsql namespace: monitoring
spec:
selector:
matchLabels:
postgres-operator.crunchydata.com/cluster: fgedu-pgsql endpoints:
– port: metrics
interval: 30s
“`
“`bash
kubectl fgapply -f prometheus.yaml -n monitoring
“`
Part05-风哥经验总结与分享
5.1 最佳实践
Kubernetes环境下PostgreSQL高可用的最佳实践:
- 选择合适的高可用方案:根据业务需求和技术能力选择Patroni、Stolon或PostgreSQL Operator
- 合理配置资源:为PostgreSQL实例分配足够的CPU和内存资源
- 使用高性能存储:选择IOPS高的存储,如SSD或云存储的高性能选项
- 配置合理的副本数:至少3个副本,确保高可用性
- 实现监控和告警:集成Prometheus和Grafana,监控PostgreSQL性能和集群状态
- 定期备份:配置自动备份,确保数据可恢复
- 测试故障转移:定期测试故障转移流程,确保在实际故障时能够正常工作
- 使用连接池:配置PgBouncer等连接池,提高连接管理效率
- 优化网络配置:确保网络带宽足够,减少网络延迟
- 文档化:记录部署和运维流程,便于团队协作
5.2 常见挑战
## 1. 存储性能问题
– **问题:** 存储性能不足,导致PostgreSQL性能下降
– **解决方案:**
– 使用高性能存储,如SSD或云存储的高性能选项
– 配置适当的存储参数,如IOPS和吞吐量
– 考虑使用本地存储提高性能
## 2. 网络延迟问题
– **问题:** 网络延迟高,影响PostgreSQL复制和故障转移
– **解决方案:**
– 使用高速网络,如万兆网络
– 优化网络配置,减少网络瓶颈
– 确保集群节点在同一可用区或区域
## 3. 资源竞争问题
– **问题:** Kubernetes集群中其他应用与PostgreSQL竞争资源
– **解决方案:**
– 为PostgreSQL实例设置资源限制和请求
– 使用节点亲和性,将PostgreSQL实例部署在专用节点上
– 监控资源使用情况,及时调整资源分配
## 4. 故障转移时间过长
– **问题:** 故障转移时间过长,导致服务中断
– **解决方案:**
– 优化Patroni或Stolon的配置,减少故障转移时间
– 配置合理的健康检查参数
– 确保etcd集群的稳定性
## 5. 备份和恢复困难
– **问题:** 在Kubernetes环境下备份和恢复困难
– **解决方案:**
– 使用pgBackRest等工具进行备份
– 配置自动备份策略
– 测试备份恢复流程
## 6. 监控和告警不完善
– **问题:** 监控和告警不完善,无法及时发现问题
– **解决方案:**
– 集成Prometheus和Grafana
– 配置合理的告警阈值
– 监控集群状态和PostgreSQL性能指标
## 7. 版本升级困难
– **问题:** 在Kubernetes环境下升级PostgreSQL版本困难
– **解决方案:**
– 使用PostgreSQL Operator的升级功能
– 制定详细的升级计划
– 测试升级流程
## 8. 安全配置复杂
– **问题:** Kubernetes环境下PostgreSQL安全配置复杂
– **解决方案:**
– 使用Secret存储敏感信息
– 配置网络策略,限制访问
– 启用SSL连接
– 定期安全审计
5.3 未来趋势
Kubernetes环境下PostgreSQL高可用的未来发展趋势:
## 1. Operator模式普及
– PostgreSQL Operator将成为主流部署方式
– 更多云厂商提供托管的PostgreSQL Operator服务
– Operator功能不断增强,支持更多高级特性
## 2. 云原生特性集成
– 与Kubernetes的原生功能深度集成
– 支持自动扩缩容
– 支持集群自动修复
## 3. 智能运维
– 使用机器学习算法预测故障
– 自动优化配置参数
– 智能备份和恢复策略
## 4. 多集群管理
– 跨区域和跨云部署
– 统一管理多个PostgreSQL集群
– 灾难恢复和数据复制
## 5. 边缘计算
– 在边缘设备上部署PostgreSQL
– 边缘与云协同
– 低延迟数据处理
## 6. 安全增强
– 内置安全特性,如加密和访问控制
– 与云原生安全工具集成
– 自动安全审计和合规检查
## 7. 性能优化
– 针对Kubernetes环境的性能优化
– 更好的资源利用
– 更高的吞吐量和更低的延迟
## 8. 开发体验改进
– 简化部署和管理流程
– 提供更友好的用户界面
– 集成开发工具和CI/CD流程
本文由风哥教程整理发布,仅用于学习测试使用,转载注明出处:http://www.fgedu.net.cn/10327.html
