为 EMQX 集群启用持久化存储
目标
使用 persistentVolumeClaimSpec 字段为 EMQX 集群中的 Core 节点配置持久化存储。
配置 EMQX 集群持久化存储
apps.emqx.io/v3beta1 EMQX CRD 中的 .spec.coreTemplate.spec.persistentVolumeClaimSpec 字段用于为每个 Core 节点配置持久化存储。该字段采用 Kubernetes PersistentVolumeClaimSpec 的模式和语义。
EMQX Operator 3.0 使用单个 StatefulSet 管理 Core 节点。每个 Core Pod 都具有稳定的标识,并在镜像更新和滚动更新期间始终使用同一个 PVC。配置此字段后,EMQX Operator 会使用持久卷声明(Persistent Volume Claim,PVC)作为 EMQX 容器的 /opt/emqx/data 卷,并通过指定的 StorageClass 制备持久卷(Persistent Volume,PV)。
PVC 生命周期
Core 节点的 PVC 与 StatefulSet Pod 序号绑定。例如,在镜像更新和滚动更新期间,emqx-core-0 的 PVC 始终挂载到 emqx-core-0,因此该节点会继续使用同一个数据卷。
EMQX Operator 会配置 Kubernetes,使其在不再需要 Core 节点 PVC 时将其删除:
缩容 Core 节点时,会删除已移除 Pod 序号所对应的 PVC。
例如,将 Core 节点副本数从 5 缩减到 3 时,会删除序号 3 和 4 对应的 PVC。在缩容 StatefulSet 前,EMQX Operator 会将持久存储(Durable Storage)数据从这些 Core 节点重新均衡到其他节点,以免数据丢失或持久性降低。
删除 EMQX 自定义资源时,Kubernetes 会删除 Core StatefulSet 及其关联的 PVC。
滚动更新期间,StatefulSet 名称和 Pod 序号不会改变,因此 PVC 会被保留。
自动清理功能依赖 Kubernetes StatefulSetAutoDeletePVC 特性门控。从 Kubernetes 1.27 开始,该特性门控默认启用。如果集群管理员将其禁用,Kubernetes 会忽略 PVC 删除策略,此时必须手动清理不再使用的 PVC。
有关 PV 和 PVC 的详情,请参见 Kubernetes 持久卷文档。
将以下内容保存为 YAML 文件,并使用
kubectl apply进行部署。yamlapiVersion: apps.emqx.io/v3beta1 kind: EMQX metadata: name: emqx spec: image: emqx/emqx:6.3.2 config: roots: license: key: "..." coreTemplate: spec: persistentVolumeClaimSpec: storageClassName: standard resources: requests: storage: 1Gi accessModes: - ReadWriteOnce replicas: 3 listenersServiceTemplate: spec: type: LoadBalancer dashboardServiceTemplate: spec: type: LoadBalancerTIP
使用
storageClassName字段为 EMQX 数据选择合适的 StorageClass。运行kubectl get storageclass可列出 Kubernetes 集群中已有的 StorageClass;也可以根据需要创建 StorageClass。等待 EMQX 集群就绪。
运行
kubectl get检查 EMQX 集群状态,并确保STATUS为Ready。此过程可能需要一些时间。bash$ kubectl get emqx emqx NAME STATUS AGE emqx Ready 10m
验证持久化存储
验证 Kubernetes 是否会在 Core Pod 被替换后重新挂载同一个 PVC。请勿在此测试中删除 EMQX 资源,因为 EMQX Operator 会将 StatefulSet 配置为:删除 StatefulSet 时一并删除关联的 PVC。
记录第一个 Core Pod 所挂载 PVC 的 UID:
bashpvc_name=emqx-core-data-emqx-core-0 pvc_uid_before=$(kubectl get pvc "${pvc_name}" -o jsonpath='{.metadata.uid}') kubectl get pvc "${pvc_name}"删除 Pod,并等待 StatefulSet 重新创建该 Pod:
bashkubectl delete pod emqx-core-0 kubectl wait --for=condition=Ready pod/emqx-core-0 --timeout=10mPod 就绪后,再次获取并比较 PVC UID:
bashpvc_uid_after=$(kubectl get pvc "${pvc_name}" -o jsonpath='{.metadata.uid}') test "${pvc_uid_before}" = "${pvc_uid_after}" && echo "The Core Pod reused the same PVC."UID 相同即表示 Kubernetes 保留了原 PVC,因此替换后的 Pod 会继续使用同一个持久卷。