配置 Storage Class
Doris 集群中 FE、BE 以及监控等组件需要使用将数据持久化的存储。Kubernetes 上的数据持久化需要使用 PersistentVolume (PV) 。Kubernetes 提供多种存储类型,主要分为两大类:
网络存储
存储介质不在当前节点,而是通过网络方式挂载到当前节点。一般有多副本冗余提供高可用保证,在节点出现故障时,对应网络存储可以再挂载到其它节点继续使用。
本地存储
存储介质在当前节点,通常能提供比网络存储更低的延迟,但没有多副本冗余,一旦节点出故障,数据就有可能丢失。如果是 IDC 服务器,节点故障可以一定程度上对数据进行恢复,但公有云上使用本地盘的虚拟机在节点故障后,数据是无法找回的。
PV 一般由系统管理员或 volume provisioner 自动创建,PV 与 Pod 是通过 PersistentVolumeClaim (PVC) 进行关联的。普通用户在使用 PV 时并不需要直接创建 PV,而是通过 PVC 来申请使用 PV,对应的 volume provisioner 根据 PVC 创建符合要求的 PV,并将 PVC 与该 PV 进行绑定。
Doris 集群推荐存储类型
BE 要求存储有较低的读写延迟,所以生产环境强烈推荐使用本地 SSD 存储。
FE 作为存储集群元信息的数据库,并不是 IO 密集型应用,所以一般本地普通 SAS 盘或网络 SSD 存储(例如 AWS 上 gp2 类型的 EBS 存储卷,Google Cloud 上的持久化 SSD 盘)就可以满足要求。
监控组件工具,由于自身没有做多副本冗余,所以为保证可用性,推荐用网络存储。
网络 PV 配置
Kubernetes 1.11
及以上的版本支持网络 PV 的动态扩容
,但用户需要为相应的 StorageClass
开启动态扩容支持。
开启动态扩容后,通过下面方式对 PV 进行扩容:
修改 PVC 大小
假设之前 PVC 大小是 10 Gi,现在需要扩容到 100 Gi
kubectl patch pvc -n ${namespace} ${pvc_name} -p '{"spec": {"resources": {"requests": {"storage": "100Gi"}}}}'
查看 PV 扩容成功
扩容成功后,通过
kubectl get pvc -n ${namespace} ${pvc_name}
显示的大小仍然是初始大小,但查看 PV 大小会显示已经扩容到预期的大小。kubectl get pv | grep ${pvc_name}
本地 PV 配置
Kubernetes
当前支持静态分配的本地存储。可使用 local-static-provisioner
项目中的 local-volume-provisioner
程序创建本地存储对象。
第 1 步:准备本地存储
BE 数据使用的盘,可通过普通挂载 方式将盘挂载到
/mnt/ssd
目录。出于性能考虑,推荐 BE 独占一个磁盘,并且推荐磁盘类型为 SSD。
FE 数据使用的盘,可以参考步骤 挂载盘,创建目录,并将新建的目录以 bind mount 方式挂载到
/mnt/sharedssd
目录下。
给监控数据使用的盘,可以参考步骤
挂载盘,创建目录,并将新建的目录以 bind mount 方式挂载到 /mnt/monitoring
目录下。
上述的 /mnt/ssd
、/mnt/sharedssd
、/mnt/monitoring
是 local-volume-provisioner 使用的发现目录(discovery
directory),local-volume-provisioner 会为发现目录下的每一个子目录创建对应的 PV。
第 2 步:部署 local-volume-provisioner
下载 local-volume-provisioner 部署文件。
wget https://raw.githubusercontent.com/linsoss/doris-operator/dev/examples/local-pv/local-volume-provisioner.yaml
如果你使用的发现路径与 第 1 步:准备本地存储 中的示例一致,可跳过这一步。如果你使用与上一步中不同路径的发现目录,需要修改 ConfigMap 和 DaemonSet 定义。
修改 ConfigMap 定义中的
data.storageClassMap
字段:apiVersion: v1 kind: ConfigMap metadata: name: local-provisioner-config namespace: kube-system data: # ... storageClassMap: | ssd-storage: # for BE hostDir: /mnt/ssd mountDir: /mnt/ssd shared-ssd-storage: # for FE hostDir: /mnt/sharedssd mountDir: /mnt/sharedssd monitoring-storage: # for moniting data hostDir: /mnt/monitoring mountDir: /mnt/monitoring
关于 local-volume-provisioner 更多的配置项,参考文档 Configuration 。
修改 DaemonSet 定义中的
volumes
与volumeMounts
字段,以确保发现目录能够挂载到 Pod 中的对应目录:...... volumeMounts: - mountPath: /mnt/ssd name: local-ssd mountPropagation: "HostToContainer" - mountPath: /mnt/sharedssd name: local-sharedssd mountPropagation: "HostToContainer" - mountPath: /mnt/monitoring name: local-monitoring mountPropagation: "HostToContainer" volumes: - name: local-ssd hostPath: path: /mnt/ssd - name: local-sharedssd hostPath: path: /mnt/sharedssd - name: local-backup hostPath: path: /mnt/backup - name: local-monitoring hostPath: path: /mnt/monitoring ......
部署 local-volume-provisioner 程序。
kubectl apply -f local-volume-provisioner.yaml
检查 Pod 和 PV 状态。
kubectl get po -n kube-system -l app=local-volume-provisioner && \ kubectl get pv | grep -e ssd-storage -e shared-ssd-storage -e monitoring-storage -e backup-storage
local-volume-provisioner
会为发现目录下的每一个挂载点创建一个 PV。
更多信息,可参阅 Kubernetes 本地存储 和 local-static-provisioner 文档。
最佳实践
- 本地 PV 的路径是本地存储卷的唯一标示符。为了保证唯一性并避免冲突,推荐使用设备的 UUID 来生成唯一的路径。
- 如果想要 IO 隔离,建议每个存储卷使用一块物理盘,在硬件层隔离。
- 如果想要容量隔离,建议每个存储卷一个分区使用一块物理盘,或者每个存储卷使用一块物理盘。
更多信息,可参阅 local-static-provisioner 的最佳实践文档。
数据安全
一般情况下 PVC 在使用完删除后,与其绑定的 PV 会被 provisioner
清理回收再放入资源池中被调度使用。为避免数据意外丢失,可在全局配置 StorageClass
的回收策略 (reclaim policy) 为 Retain
或者只将某个 PV 的回收策略修改为 Retain
。Retain
模式下,PV 不会自动被回收。
全局配置
StorageClass
的回收策略一旦创建就不能再修改,所以只能在创建时进行设置。如果创建时没有设置,可以再创建相同 provisioner 的StorageClass
,例如 GKE 上默认的 fe 类型的StorageClass
默认保留策略是Delete
,可以再创建一个名为fe-standard
的保留策略是Retain
的存储类型,并在创建 Doris 集群时将相应组件的storageClassName
修改为fe-standard
。apiVersion: storage.k8s.io/v1 kind: StorageClass metadata: name: fe-standard parameters: type: fe-standard provisioner: kubernetes.io/gce-fe reclaimPolicy: Retain volumeBindingMode: Immediate
配置单个 PV
kubectl patch pv ${pv_name} -p '{"spec":{"persistentVolumeReclaimPolicy":"Retain"}}'
删除 PV 以及对应的数据
PV 保留策略是 Retain
时,如果确认某个 PV 的数据可以被删除,需要严格按照下面的操作顺序来删除 PV 以及对应的数据:
删除 PV 对应的 PVC 对象:
kubectl delete pvc ${pvc_name} --namespace=${namespace}
设置 PV 的保留策略为
Delete
,PV 会被自动删除并回收:kubectl patch pv ${pv_name} -p '{"spec":{"persistentVolumeReclaimPolicy":"Delete"}}'
要了解更多关于 PV 的保留策略可参考修改 PV 保留策略。