在AI模型部署和基础设施管理中,高可用性(HA)存储至关重要。这不仅包括存储模型二进制文件,更重要的是存储关键的元数据,如模型版本控制、A/B测试配置、推理请求日志以及分布式训练的检查点(Checkpoints)。如果存储层发生故障,整个服务可能会中断或丢失关键状态信息。
本篇文章将聚焦于如何利用Kubernetes中的持久卷(PVC)以及Patroni(一个基于PostgreSQL的HA解决方案)来构建一个具备自动故障转移能力的、高可用的状态存储层。Patroni利用底层的持久存储来同步数据,并使用分布式锁(如Etcd或ZooKeeper)来管理主节点选举。
关键技术栈
- Kubernetes StatefulSet: 确保每个数据库副本都有稳定、唯一的网络标识和持久存储。
- Persistent Volume Claims (PVC): 依赖底层存储类(如Ceph RBD, Rook, 或云服务商的EBS/GCE PD)提供持久的、高可用的块存储。
- Patroni: 管理PostgreSQL集群,实现基于RAFT或Paxos机制的主从同步和故障转移。
步骤一:准备存储类和环境
为了演示,我们假设您的Kubernetes集群已经配置了一个支持
1 | ReadWriteOnce |
(RWO) 的
1 | StorageClass |
。对于生产环境中的HA,Patroni的每个节点都需要独立的RWO卷。
首先,确保您的存储类是可用的:
1
2
3
4 kubectl get storageclass
# 预期输出类似:
# NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE
# standard (default) kubernetes.io/gce-pd Delete Immediate true 2d
步骤二:使用PostgreSQL Operator部署Patroni集群
为了简化部署和运维,我们通常使用如Zalando或CrunchyData的PostgreSQL Operator来管理Patroni集群。这里我们以Zalando Operator为例进行部署。
首先,安装Operator(如果尚未安装):
1
2
3
4 # 假设Operator已安装,它会监听Custom Resource Definition (CRD) PDBs
kubectl apply -f https://raw.githubusercontent.com/zalando/postgres-operator/master/manifests/configmap.yaml
kubectl apply -f https://raw.githubusercontent.com/zalando/postgres-operator/master/manifests/operator-service-account-rbac.yaml
kubectl apply -f https://raw.githubusercontent.com/zalando/postgres-operator/master/manifests/postgres-operator.yaml
接下来,定义一个3副本的高可用PostgreSQL集群(名为
1 | ai-metadata-db |
)。Operator将自动创建StatefulSet、PVCs、Service以及Patroni配置。
1 | ai-db-cluster.yaml |
:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 apiVersion: "acid.zalan.do/v1"
kind: "postgresql"
metadata:
name: "ai-metadata-db"
labels:
cluster: ai-metadata
spec:
teamId: "aiinfra"
volume:
size: "10Gi"
storageClass: "standard" # 使用您环境中的StorageClass名称
numberOfInstances: 3 # 部署3个副本,实现高可用
users:
adminuser: # 数据库用户定义
password: adminpassword
options: ["superuser", "createdb"]
databases:
metadata_store: adminuser
postgresql:
version: "15"
patroni:
# Patroni配置,默认使用Kubernetes作为分布式锁的后端
leader_downtime_limit: 30 # 30秒内未响应则触发故障转移
failover_timeout: 10 # 故障转移等待时间
应用配置:
1 kubectl apply -f ai-db-cluster.yaml
步骤三:验证HA状态和模拟故障转移
集群启动后,Operator会创建三个Pod,每个Pod拥有独立的PVC(即持久存储)。通过查看标签可以识别主节点(Primary)和备用节点(Replica)。
- 检查集群状态和主节点:
1
2
3
4
5
6 # 查看Pod状态
kubectl get pods -l cluster-name=ai-metadata-db
# 确定当前的主节点 (Primary)
PRIMARY_POD=$(kubectl get pods -l role=master,cluster-name=ai-metadata-db -o jsonpath='{.items[0].metadata.name}')
echo "当前主节点: $PRIMARY_POD"
- 验证存储持久性:
检查PVC是否已成功绑定到各个Pod。即使Pod重启或被调度到其他节点,它们仍会挂载回原来的存储卷。
1 kubectl get pvc -l cluster-name=ai-metadata-db
- 模拟主节点故障转移:
现在,我们模拟当前主节点突然终止(例如节点宕机、OOM Kill)。这会测试Patroni的故障转移机制和StatefulSet的自愈能力。
1
2 # 强制删除主节点Pod
kubectl delete pod $PRIMARY_POD --grace-period=0 --force
- 观察故障转移过程:
监控Pod列表和日志。在几秒到一分钟内(取决于Patroni的配置),Patroni会检测到原主节点丢失,并在剩余的两个备用节点中通过选举选出一个新的主节点。
1
2
3
4
5 # 持续观察新的主节点出现
watch kubectl get pods -l cluster-name=ai-metadata-db
# 检查日志确认故障转移事件
kubectl logs -l cluster-name=ai-metadata-db
一旦新的主节点被选举出来,原有的服务(例如,您的AI服务后端)可以立即通过Kubernetes Service(Operator自动创建)连接到新的主节点,而不会丢失数据,因为所有节点的数据都是通过底层的持久存储卷同步的。
总结
通过结合Kubernetes的StatefulSet和持久存储(PVC),以及Patroni这样的专用HA工具,我们能够为AI基础设施提供强大且自动化的状态存储高可用性。这确保了在底层硬件故障或节点中断的情况下,关键的AI元数据和状态能够保持完整并快速恢复服务,极大地提高了系统的韧性(Resilience)。
汤不热吧