十九、云原生分布式存储 CubeFS
十九、云原生分布式存储 CubeFS
文章目录
- 十九、云原生分布式存储 CubeFS
- 1、分布式存储初识
- 1.1 分布式存储主要特性
- 1.2 为什么要在K8s上落地存储平台
- 1.3 云原生存储平台CubeFS介绍
- 1.4 分布式存储平台落地架构
- 1.4.1 混合部署
- 1.4.2 独立部署-基础设施集群
- 1.5 资源分配建议
- 1.6 硬件设计
- 2、CubeFS安装
- 2.1 CubeFS 部署架构
- 2.2 集群规划
- 2.3 首先给节点打上标签,用来标记部署什么服务:
- 2.4 数据盘配置
- 2.5 CubeFS 部署
- 3、CubeFS 客户端部署使用
- 3.1 CubeFS 客户端部署
- 3.2 集群管理
- 3.3 元数据节点管理
- 3.4 数据节点管理
- 3.5 用户管理
- 3.6 数据卷管理
- 3.7 CubeFS 挂载测试
- 3.8 CubeFS 扩容
- 3.8.1 基于磁盘扩容
- 3.8.2 基于主机的扩容
- 4、CubeFS 对象存储
- 5、CubeFS 对接 K8s
- 5.1 CSI 部署
- 5.2 PVC 和 PV 测试
- 5.3 在线扩容
- 6、数据持久化实战
- 6.1 MySQL 数据持久化
- 6.2 大模型文件持久化
1、分布式存储初识
1.1 分布式存储主要特性
- 支持近乎无限的扩容
- 支持容错能力和数据冗余
- 支持多机房多区域部署
- 支持负载均衡和并行处理
- 支持权限管理和多用户
- 支持多种文件存储类型
- 支持普通硬件设计
1.2 为什么要在K8s上落地存储平台
万物皆可容器化
- 简化部署和管理
- 自动化运维
- 一键式动态扩展
- 故障自愈和高可用性
- 云原生生态集成
1.3 云原生存储平台CubeFS介绍
CubeFS是新一代云原生存储产品,目前是云原生计算基金会(CNCF)托管的毕业开源项目,兼容S3、POSIX、HDFS等多种访问协议,支持多副本与纠删码两种存储引擎,为用户提供多租户、多AZ部署以及跨区域复制等多种特性,广泛应用于大数据、AI、容器平台、数据库、中间件存算分离、数据共享以及数据保护等场景。
CubeFS特性:
- 多协议:支持S3、POSIX、HDFS
- 双引擎:支持多副本与纠删码
- 多租户:支持多租户隔离和权限分配
- 可扩展:支持各模块水平扩展,轻松扩展到PB或EB级
- 高性能:支持多级缓存、支持多种高性能的复制协议
- 云原生:自带CSI插件,一键集成kubernetes
- 多场景:大数据分析、机器学习、深度训练、共享存储、对象存储、数据库中间件等
1.4 分布式存储平台落地架构
1.4.1 混合部署
1.4.2 独立部署-基础设施集群
1.5 资源分配建议
元数据节点总内存计算规则:每个文件元数据占用空间2KB~4KB左右
根据文件数量预估
假设已知的文件数量预估为10亿
通过计算规则需要的内存KB为:20亿KB
换算为G:2000000000 / 1024 / 1024 ≈ 2000G
根据数据量预估
假设集群数据总量为10PB = 10240TB = 10737418240MB
通过默认分片大小8MB预估,可能需要10737418240 / 8 ≈ 1342177280个文件
通过计算规则需要的内存KB为:2684354560KB ≈ 2500G
1.6 硬件设计
服务器硬件设计 / 1PB / 256G内存
2、CubeFS安装
2.1 CubeFS 部署架构
CubeFS 目前由这四部分组成:
- Master:资源管理节点,负责维护整个集群的元信息,部署为 StatefulSet 资源
- DataNode:数据存储节点,需要挂载大量磁盘负责文件数据的实际存储,部署为 DaemonSet 资源
- MetaNode:元数据节点,负责存储所有的文件元信息,部署为 DaemonSet 资源
- ObjectNode:负责提供转换 S3 协议提供对象存储的能力,无状态服务,部署为 Deployment 资源
2.2 集群规划
主机名称 | 物理IP | 系统 | 资源配置 | 数据磁盘 |
---|---|---|---|---|
k8s-master01 | 192.168.200.50 | Rocky9.4 | 4核8g | 40G*2 |
k8s-node01 | 192.168.200.51 | Rocky9.4 | 4核8g | 40G*2 |
k8s-node02 | 192.168.200.52 | Rocky9.4 | 4核8g | 40G*2 |
2.3 首先给节点打上标签,用来标记部署什么服务:
# Master 节点,至少三个,建议为奇数个
kubectl label node <nodename> component.cubefs.io/master=enabled# MetaNode 元数据节点,至少 3 个,奇偶无所谓
kubectl label node <nodename> component.cubefs.io/metanode=enabled# Dataode 数据节点,至少 3 个,奇偶无所谓
kubectl label node <nodename> component.cubefs.io/datanode=enabled# ObjectNode 对象存储节点,可以按需进行标记,不需要对象存储功能的话也可以不部署这个组件
kubectl label node <nodename> component.cubefs.io/objectnode=enabled
master节点仅作演示
# 生产要指定节点打标签
[root@k8s-master01 ~]# kubectl label node component.cubefs.io/master=enabled --all
[root@k8s-master01 ~]# kubectl label node component.cubefs.io/metanode=enabled --all
[root@k8s-master01 ~]# kubectl label node component.cubefs.io/datanode=enabled --all
[root@k8s-master01 ~]# kubectl label node component.cubefs.io/objectnode=enabled --all
2.4 数据盘配置
在配置了 component.cubefs.io/datanode=enabled
标签的节点上,对数据盘进行初始化操作。
首先需要添加一个新盘,然后通过 fdisk -l
查看:
[root@k8s-master01 ~]# fdisk -l | grep /dev/nvme
Disk /dev/nvme0n1: 50 GiB, 53687091200 bytes, 104857600 sectors
/dev/nvme0n1p1 * 2048 2099199 2097152 1G 83 Linux
/dev/nvme0n1p2 2099200 104857599 102758400 49G 8e Linux LVM
Disk /dev/nvme0n2: 40 GiB, 42949672960 bytes, 83886080 sectors
格式化每个磁盘并挂载**(三节点操作)**:
# 格式化硬盘
[root@k8s-master01 ~]# mkfs.xfs -f /dev/nvme0n2# 创建挂载目录,如果机器上存在多个需要挂载的数据磁盘,则每个磁盘按以上步骤进行格式化和挂载磁盘,挂载目录按照 data0/data1/../data999 的顺序命名
[root@k8s-master01 ~]# mkdir /data0# 挂载磁盘
[root@k8s-master01 ~]# mount /dev/nvme0n2 /data0# 设置为开机自动挂载(注意三个节点磁盘的UUID号不同):
[root@k8s-master01 ~]# blkid /dev/nvme0n2
/dev/nvme0n2: UUID="56b90331-8053-403b-9393-597811b81310" TYPE="xfs"[root@k8s-master01 ~]# echo "UUID=56b90331-8053-403b-9393-597811b81310 /data0 xfs defaults 0 0" >>/etc/fstab
[root@k8s-master01 ~]# mount -a
2.5 CubeFS 部署
下载安装文件
[root@k8s-master01 ~]# git clone https://gitee.com/dukuan/cubefs-helm.git
调整安装配置
[root@k8s-master01 ~]# cd cubefs-helm/cubefs/
[root@k8s-master01 cubefs]# vim values.yaml
[root@k8s-master01 cubefs]# sed -n "2,15p;21,24p;27,31p;33,35p;50p;52p;56,57p;70,77p;79p;87p;93,100p;107p;123,124p;127,134p;153p;156p;166p" values.yaml
component:master: truedatanode: truemetanode: trueobjectnode: trueclient: falsecsi: falsemonitor: falseingress: falseblobstore_clustermgr: falseblobstore_blobnode: falseblobstore_proxy: falseblobstore_scheduler: falseblobstore_access: false
image:server: crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/cfs-server:v3.5.0client: crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/cfs-client:v3.5.0blobstore: crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/blobstore:v3.4.0csi_driver: crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/cfs-csi-driver:v3.5.0csi_provisioner: crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/csi-provisioner:v2.2.2csi_attacher: crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/sig-storage/csi-attacher:v3.4.0csi_resizer: crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/csi-resizer:v1.3.0driver_registrar: crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/csi-node-driver-registrar:v2.5.0grafana: crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/grafana:6.4.4prometheus: crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/prometheus:v2.13.1consul: crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/consul:1.6.1
# 主节点配置:
master: replicas: 3nodeSelector:"component.cubefs.io/master": "enabled"resources:enabled: falserequests:memory: "512Mi" # 生产环境建议: 8Gcpu: "200m" # 生产环境建议: 2000mlimits:memory: "2Gi" # 生产环境建议: 32Gcpu: "2000m" # 生产环境建议: 8000m
# 元数据节点配置:
metanode:total_mem: "6442450944" # 可用内存建议为主机的 80%resources:enabled: truerequests:memory: "512Mi" # 生产环境建议: 8Gcpu: "200m" # 生产环境建议: 2000mlimits:memory: "2Gi" # 生产环境建议: 32Gcpu: "2000m" # 生产环境建议: 8000m
# 数据盘配置:
datanode:disks:- /data0:2147483648resources:enabled: falserequests:memory: "512Mi" # 生产环境建议: 32Gcpu: "200m" # 生产环境建议: 2000mlimits:memory: "2Gi" # 生产环境建议: 256Gcpu: "2000m" # 生产环境建议: 8000m
# 对象存储节点配置:
objectnode:replicas: 3domains: "objectcfs.cubefs.io,objectnode.cubefs.io"
# 执行部署:
[root@k8s-master01 cubefs]# helm upgrade --install cubefs -n cubefs --create-namespace .# 查看 Pod 状态:
[root@k8s-master01 cubefs]# kubectl get pod -n cubefs
NAME READY STATUS RESTARTS AGE
datanode-22bh8 1/1 Running 0 4m13s
datanode-67fbm 1/1 Running 0 4m13s
datanode-9dh4q 1/1 Running 0 4m13s
master-0 1/1 Running 0 4m13s
master-1 1/1 Running 0 42s
master-2 1/1 Running 0 39s
metanode-n6tpz 1/1 Running 0 4m13s
metanode-nq5m4 1/1 Running 0 4m13s
metanode-tt8q8 1/1 Running 0 4m13s
objectnode-5ff648b685-6rrkt 1/1 Running 0 4m13s
objectnode-5ff648b685-p9cxd 1/1 Running 0 4m13s
objectnode-5ff648b685-r2kw8 1/1 Running 0 4m13s
如果遇到启动失败的,可以在对应的节点上,查看 /var/log/cubefs
下的日志。
3、CubeFS 客户端部署使用
官方文档
3.1 CubeFS 客户端部署
下载工具包:
[root@k8s-master01 ~]# tar xf cubefs-3.5.0-linux-amd64.tar.gz
[root@k8s-master01 ~]# mv cubefs/build/bin/cfs-cli /usr/local/bin/
[root@k8s-master01 ~]# mv cubefs/build/bin/cfs-client /usr/local/bin/[root@k8s-master01 ~]# cfs-cli --version
CubeFS CLI
Version : v3.5.0
Branch : HEAD
Commit : 10353bf433fefd51c6eef564035c8a682515789c
Build : go1.20.4 linux amd64 2025-03-17 17:40
客户端配置:
[root@k8s-master01 ~]# kubectl get svc -n cubefs
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
master-service ClusterIP 10.105.1.29 <none> 17010/TCP 155m# 更改 masterAddr 为 master service 的 svc ip
[root@k8s-master01 ~]# vim ~/.cfs-cli.json
[root@k8s-master01 ~]# cat ~/.cfs-cli.json {"masterAddr": ["10.105.1.29:17010"],"timeout": 60
}
3.2 集群管理
获取集群信息,包括集群名称、地址、卷数量、节点数量和使用率等:
[root@k8s-master01 ~]# cfs-cli cluster info
[Cluster]Cluster name : my-clusterMaster leader : master-0.master-service:17010Master-1 : master-0.master-service:17010Master-2 : master-1.master-service:17010Master-3 : master-2.master-service:17010Auto allocate : EnabledMetaNode count (active/total) : 3/3MetaNode used : 0 GBMetaNode available : 17 GBMetaNode total : 18 GBDataNode count (active/total) : 3/3DataNode used : 0 GBDataNode available : 103 GBDataNode total : 104 GBVolume count : 0Allow Mp Decomm : EnabledEbsAddr : LoadFactor : 0DpRepairTimeout : 2h0m0sDataPartitionTimeout : 20m0svolDeletionDelayTime : 48 hEnableAutoDecommission : falseAutoDecommissionDiskInterval : 10sEnableAutoDpMetaRepair : falseAutoDpMetaRepairParallelCnt : 100MarkDiskBrokenThreshold : 0%DecommissionDpLimit : 10DecommissionDiskLimit : 1DpBackupTimeout : 168h0m0sForbidWriteOpOfProtoVersion0 : falseLegacyDataMediaType : 0BatchCount : 0MarkDeleteRate : 0DeleteWorkerSleepMs: 0AutoRepairRate : 0MaxDpCntLimit : 3000MaxMpCntLimit : 300
获取集群状态,按区域获取元数据和数据节点使用率、状态等:
[root@k8s-master01 ~]# cfs-cli cluster stat
[Cluster Status]DataNode Status:TOTAL/GB USED/GB INCREASED/GB USED RATIO 104 0 0 0.009 MetaNode Status:TOTAL/GB USED/GB INCREASED/GB USED RATIO 18 0 0 0.014 Zone List:ZONE NAME ROLE TOTAL/GB USED/GB AVAILABLE/GB USED RATIO TOTAL NODES WRITEBLE NODESdefault DATANODE 104.81 0.93 103.88 0.01 3 3 METANODE 18 0.25 17.75 0.01 3 3
Metanode 的 Total 为最大可用内存,由所有 metanode 的 MaxMemAvailWeight 之和计算得来。
设置卷删除延迟的时间,表示卷被删除多久才会被彻底删除,默认 48h,在此之前可以恢复:
cfs-cli cluster volDeletionDelayTime 72
3.3 元数据节点管理
列出所有的元数据节点,包括 ID、地址、读写状态及存活状态等:
[root@k8s-master01 ~]# cfs-cli metanode list
[Meta nodes]
ID ADDRESS WRITABLE ACTIVE MEDIA ForbidWriteOpOfProtoVer0
2 192.168.200.52:17210(master-0.master-service.cubefs.svc.cluster.local:17210) Yes Active N/A notForbid
6 192.168.200.51:17210(master-2.master-service.cubefs.svc.cluster.local:17210) Yes Active N/A notForbid
7 192.168.200.50:17210(192-168-200-50.kubernetes.default.svc.cluster.local:17210,master-1.master-service.cubefs.svc.cluster.local:17210) Yes Active N/A notForbid
查看某个节点的详细信息:
[root@k8s-master01 ~]# cfs-cli metanode info 192.168.200.52:17210
[Meta node info]ID : 2Address : 192.168.200.52:17210(master-0.master-service.cubefs.svc.cluster.local:17210)Threshold : 0.75MaxMemAvailWeight : 5.91 GBAllocated : 95.27 MBTotal : 6.00 GBZone : defaultStatus : ActiveRdonly : falseReport time : 2025-08-23 20:23:52Partition count : 0Persist partitions : []Can alloc partition : trueMax partition count : 300CpuUtil : 1.0%
3.4 数据节点管理
列举所有的数据节点,包括 ID、地址、读写状态和存活状态:
[root@k8s-master01 ~]# cfs-cli datanode list
[Data nodes]
ID ADDRESS WRITABLE ACTIVE MEDIA ForbidWriteOpOfProtoVer0
3 192.168.200.50:17310(master-1.master-service.cubefs.svc.cluster.local:17310,192-168-200-50.kubernetes.default.svc.cluster.local:17310) Yes Active N/A notForbid
4 192.168.200.51:17310(master-2.master-service.cubefs.svc.cluster.local:17310) Yes Active N/A notForbid
5 192.168.200.52:17310(master-0.master-service.cubefs.svc.cluster.local:17310) Yes Active N/A notForbid
展示某个节点的详细信息:
[root@k8s-master01 ~]# cfs-cli datanode info 192.168.200.52:17310
[Data node info]ID : 5Address : 192.168.200.52:17310(master-0.master-service.cubefs.svc.cluster.local:17310)Allocated ratio : 0.008872044107781753Allocated : 317.41 MBAvailable : 34.63 GBTotal : 34.94 GBZone : defaultRdonly : falseStatus : ActiveMediaType : UnspecifiedToBeOffline : FalseReport time : 2025-08-23 20:25:53Partition count : 0Bad disks : []Decommissioned disks: []Persist partitions : []Backup partitions : []Can alloc partition : trueMax partition count : 3000CpuUtil : 1.3%IoUtils :/dev/nvme0n2:0.0%
下线数据节点(不要轻易操作)
# 下线数据节点,下线后该节点的数据将自动迁移至其他节点:
[root@k8s-master01 ~]# cfs-cli datanode decommission 192.168.200.52:17310# 下线后,节点信息无法在查看:
[root@k8s-master01 ~]# cfs-cli datanode info 192.168.200.52:17310
Error: data node not exists# 数据空间也会降低:
[root@k8s-master01 ~]# cfs-cli cluster stat
[Cluster Status]DataNode Status:TOTAL/GB USED/GB INCREASED/GB USED RATIO 69 0 0 0.009 MetaNode Status:TOTAL/GB USED/GB INCREASED/GB USED RATIO 18 0 0 0.014 Zone List:ZONE NAME ROLE TOTAL/GB USED/GB AVAILABLE/GB USED RATIO TOTAL NODES WRITEBLE NODESdefault DATANODE 69.88 0.62 69.26 0.01 2 2 METANODE 18 0.25 17.75 0.01 3 3
Pod 重建后,节点重新加入:
# 查询下线节点pod
[root@k8s-master01 ~]# kubectl get po -n cubefs -owide | grep data | grep 192.168.200.52
datanode-9dh4q 1/1 Running 0 3h42m 192.168.200.52 k8s-node02 <none> <none># 删除pod重新加入节点
[root@k8s-master01 ~]# kubectl delete po datanode-9dh4q -n cubefs# 数据空间恢复
[root@k8s-master01 ~]# cfs-cli cluster stat
[Cluster Status]DataNode Status:TOTAL/GB USED/GB INCREASED/GB USED RATIO 104 0 0 0.009 MetaNode Status:TOTAL/GB USED/GB INCREASED/GB USED RATIO 18 0 0 0.014 Zone List:ZONE NAME ROLE TOTAL/GB USED/GB AVAILABLE/GB USED RATIO TOTAL NODES WRITEBLE NODESdefault DATANODE 104.81 0.93 103.88 0.01 3 3 METANODE 18 0.26 17.74 0.01 3 3
3.5 用户管理
CubeFS 支持多用户,可以为每个用户对每个卷分配不同的权限,同时也可为对象存储提供用户认证。
创建用户:
[root@k8s-master01 ~]# cfs-cli user create test --yes
获取用户信息:
[root@k8s-master01 ~]# cfs-cli user info test
[Summary]User ID : testAccess Key : XMnVAEysoGEFtZyVSecret Key : 1w4TdSfHoY0cqSrHBUKvJ5Hx5AxmcuiPType : normalCreate Time: 2025-08-23 20:52:48
[Volumes]
VOLUME PERMISSION
列举所有用户:
[root@k8s-master01 ~]# cfs-cli user list
ID TYPE ACCESS KEY SECRET KEY CREATE TIME
root Root mPsMgs0lqDZ5ebG4 1LIvar5UHEsKnxLb1BIuCKWO7fWMUZaE 2025-08-23 17:02:09
test Normal XMnVAEysoGEFtZyV 1w4TdSfHoY0cqSrHBUKvJ5Hx5AxmcuiP 2025-08-23 20:52:48
删除用户:
[root@k8s-master01 ~]# cfs-cli user delete test --yes[root@k8s-master01 ~]# cfs-cli user list
ID TYPE ACCESS KEY SECRET KEY CREATE TIME
root Root mPsMgs0lqDZ5ebG4 1LIvar5UHEsKnxLb1BIuCKWO7fWMUZaE 2025-08-23 17:02:09
3.6 数据卷管理
创建一个卷:
# 命令格式:cfs-cli volume create [VOLUME NAME] [USER ID] [flags]
[root@k8s-master01 ~]# cfs-cli volume create volume-test test --capacity 1 -y# volume-test:卷的名字
# test:用户,如果用户不存在就自动创建
# --capacity 1:卷的大小,单位为G(不指定大小默认10G)
列出所有的卷:
[root@k8s-master01 ~]# cfs-cli volume list
VOLUME OWNER USED TOTAL STATUS CREATE TIME
volume-test test 0.00 B 1.00 GB Normal Sat, 23 Aug 2025 20:58:43 CST
查看某个卷的详细信息:
[root@k8s-master01 ~]# cfs-cli volume info volume-test
Summary:ID : 9Name : volume-testOwner : testAuthenticate : DisabledCapacity : 1 GBCreate time : 2025-08-23 20:58:43DeleteLockTime : 0Cross zone : DisabledDefaultPriority : falseDentry count : 0Description : DpCnt : 10DpReplicaNum : 3Follower read : DisabledMeta Follower read : DisabledDirect Read : DisabledInode count : 1Max metaPartition ID : 3MpCnt : 3MpReplicaNum : 3NeedToLowerReplica : DisabledRwDpCnt : 10Status : NormalZoneName : defaultVolType : 0DpReadOnlyWhenVolFull : falseTransaction Mask : renameTransaction timeout : 1Tx conflict retry num : 10Tx conflict retry interval(ms) : 20Tx limit interval(s) : 0Forbidden : falseDisableAuditLog : falseTrashInterval : 0sDpRepairBlockSize : 128KBEnableAutoDpMetaRepair : falseQuota : DisabledAccessTimeValidInterval : 24h0m0sMetaLeaderRetryTimeout : 0sEnablePersistAccessTime : falseForbidWriteOpOfProtoVer0 : falseVolStorageClass : UnspecifiedAllowedStorageClass : []CacheDpStorageClass : Unspecified
禁用卷:
[root@k8s-master01 ~]# cfs-cli volume set-forbidden volume-test true[root@k8s-master01 ~]# cfs-cli volume info volume-test | grep -i ForbiddenForbidden : true
取消禁用:
[root@k8s-master01 ~]# cfs-cli volume set-forbidden volume-test false[root@k8s-master01 ~]# cfs-cli volume info volume-test | grep -i ForbiddenForbidden : false
卷扩容或者更新卷配置:
[root@k8s-master01 ~]# cfs-cli volume update volume-test test --capacity 2 -y[root@k8s-master01 ~]# cfs-cli volume list
VOLUME OWNER USED TOTAL STATUS CREATE TIME
volume-test test 0.00 B 2.00 GB Normal Sat, 23 Aug 2025 20:58:43 CST
添加空间限制:
# 如果卷的空间满了,就不能继续往里面写数据
[root@k8s-master01 ~]# cfs-cli volume update volume-test --readonly-when-full true -y[root@k8s-master01 ~]# cfs-cli volume info volume-test | grep -i readonlyDpReadOnlyWhenVolFull : true
删除卷:
[root@k8s-master01 ~]# cfs-cli volume delete volume-test -y
3.7 CubeFS 挂载测试
创建卷:
[root@k8s-master01 ~]# cfs-cli volume create volume-test ltptest -y
创建客户端的配置文件:
[root@k8s-master01 ~]# vim volume-test-client.conf
[root@k8s-master01 ~]# cat volume-test-client.conf
{"mountPoint": "/volume-test", "volName": "volume-test", # 挂载卷名称"owner": "ltptest", # 用户"masterAddr": "10.103.104.112:17010", # master-service的IP"logDir": "/cfs/client/log","logLevel": "info","profPort": "27510"
}
安装 fuse:
[root@k8s-master01 ~]# yum install fuse -y
挂载:
[root@k8s-master01 ~]# cfs-client -c volume-test-client.conf[root@k8s-master01 ~]# df -Th | grep volume-test
cubefs-volume-test fuse.cubefs 10G 0 10G 0% /volume-test
写入数据测试:
[root@k8s-master01 ~]# cd /volume-test/
[root@k8s-master01 volume-test]# dd if=/dev/zero of=./cubefs bs=1M count=512
512+0 records in
512+0 records out
536870912 bytes (537 MB, 512 MiB) copied, 45.2422 s, 11.9 MB/s[root@k8s-master01 volume-test]# dd if=/dev/zero of=./cubefs bs=128M count=4
4+0 records in
4+0 records out
536870912 bytes (537 MB, 512 MiB) copied, 36.2865 s, 14.8 MB/s# 查看卷使用:
[root@k8s-master01 volume-test]# cfs-cli volume list
VOLUME OWNER USED TOTAL STATUS CREATE TIME
volume-test ltptest 512.00 MB 10.00 GB Normal Sun, 24 Aug 2025 22:29:21 CST
3.8 CubeFS 扩容
3.8.1 基于磁盘扩容
如果 CubeFS 是部署在 K8s 中的,扩容时需要给每个主机都添加一块硬盘:
首先需要添加一个新盘,然后通过 fdisk -l
查看:
[root@k8s-master01 ~]# fdisk -l | grep /dev/nvme0n3
Disk /dev/nvme0n3: 50 GiB, 53687091200 bytes, 104857600 sectors
格式化每个磁盘并挂载**(三节点操作)**:
# 格式化硬盘
[root@k8s-master01 ~]# mkfs.xfs -f /dev/nvme0n3# 创建挂载目录,如果机器上存在多个需要挂载的数据磁盘,则每个磁盘按以上步骤进行格式化和挂载磁盘,挂载目录按照 data0/data1/../data999 的顺序命名
[root@k8s-master01 ~]# mkdir /data1# 挂载磁盘
[root@k8s-master01 ~]# mount /dev/nvme0n3 /data1# 设置为开机自动挂载(注意三个节点磁盘的UUID号不同):
[root@k8s-master01 ~]# blkid /dev/nvme0n3
/dev/nvme0n3: UUID="6abaad00-bdf3-4e29-8fe0-9920da8ced6b" TYPE="xfs"[root@k8s-master01 ~]# echo "UUID=6abaad00-bdf3-4e29-8fe0-9920da8ced6b /data1 xfs defaults 0 0" >>/etc/fstab
[root@k8s-master01 ~]# mount -a
更改 datanode 的配置:
[root@k8s-master01 ~]# cd cubefs-helm/cubefs/
[root@k8s-master01 cubefs]# vim values.yaml
[root@k8s-master01 cubefs]# sed -n "107p;123,125p" values.yaml
datanode:disks:- /data0:2147483648- /data1:2147483648
更新配置:
[root@k8s-master01 cubefs]# helm upgrade cubefs -n cubefs .
触发 datanode 的重启:
[root@k8s-master01 cubefs]# kubectl delete po -n cubefs -l app.kubernetes.io/component=datanode
重启查看集群状态:
[root@k8s-master01 cubefs]# cfs-cli cluster stat
[Cluster Status]DataNode Status:TOTAL/GB USED/GB INCREASED/GB USED RATIO 159 1 1 0.009 MetaNode Status:TOTAL/GB USED/GB INCREASED/GB USED RATIO 18 0 0 0.020 Zone List:ZONE NAME ROLE TOTAL/GB USED/GB AVAILABLE/GB USED RATIO TOTAL NODES WRITEBLE NODESdefault DATANODE 159.75 1.38 158.37 0.01 3 0 METANODE 18 0.36 17.64 0.02 3
3.8.2 基于主机的扩容
基于主机的扩容,需要通过添加 datanode 节点来完成。
- 添加一个新节点,已有节点可以忽略
- 在新节点上添加和当前配置一样的硬盘并挂载
- 在新节点上打
component.cubefs.io/datanode=enabled
标签即可
4、CubeFS 对象存储
下载 Minio 对象存储客户端:
[root@k8s-master01 ~]# curl https://dl.minio.org.cn/client/mc/release/linux-amd64/mc --create-dirs -o /usr/local/bin/mc[root@k8s-master01 ~]# chmod +x /usr/local/bin/mc
配置对象存储:
# 为每个项目创建用户:
[root@k8s-master01 ~]# cfs-cli user create projecta -y
[root@k8s-master01 ~]# cfs-cli user list
ID TYPE ACCESS KEY SECRET KEY CREATE TIME
root Root mPsMgs0lqDZ5ebG4 1LIvar5UHEsKnxLb1BIuCKWO7fWMUZaE 2025-08-23 17:02:09
projecta Normal vMAV6AOksC4cukBL NcYi7mLw39iz0jQbXE9K2XrgO672NN7P 2025-08-24 13:46:04# 查看objectnode-service的IP
[root@k8s-master01 ~]# kubectl get svc -n cubefs
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
objectnode-service ClusterIP 10.111.87.176 <none> 1601/TCP 20h# 添加项目的 host:
[root@k8s-master01 ~]# mc alias set projecta http://10.111.87.176:1601 vMAV6AOksC4cukBL NcYi7mLw39iz0jQbXE9K2XrgO672NN7P# projecta:用户
# http:objectnode-service的IP
# vMAV6AOksC4cukBL:projecta用户ACCESS的值
# NcYi7mLw39iz0jQbXE9K2XrgO672NN7P:projecta用户SECRET的值
对象存储基本使用
# 创建桶:
[root@k8s-master01 ~]# mc mb projecta/app# 查看桶:
[root@k8s-master01 ~]# mc ls projecta/
[2025-08-24 14:05:01 CST] 0B app/# 会自动生成一个同名的卷(每个桶都是以卷的形式存在的)
[root@k8s-master01 ~]# cfs-cli volume list
VOLUME OWNER USED TOTAL STATUS CREATE TIME
app projecta 0 MB 10.00 GB Normal Sun, 24 Aug 2025 14:05:01 CST
# 上传文件:
[root@k8s-master01 ~]# mc cp volume-ceshi-client.conf projecta/app/# 查看文件
[root@k8s-master01 ~]# mc ls projecta/app/
[2025-08-24 14:07:28 CST] 192B STANDARD volume-ceshi-client.conf# 删除一个文件
[root@k8s-master01 ~]# mc rm projecta/app/volume-ceshi-client.conf# 文件已经被删除
[root@k8s-master01 ~]# mc ls projecta/app/
[root@k8s-master01 ~]#
# 上传目录:
# 不会上传目录本身,只会上传目录下的文件,所以要在存储桶里写一个同名目录(自动创建)
[root@k8s-master01 ~]# mc cp cubefs/ projecta/app/cubefs/ -r# 查看目录及文件
[root@k8s-master01 ~]# mc ls projecta/app/
[2025-08-24 14:24:17 CST] 0B cubefs/[root@k8s-master01 ~]# mc ls projecta/app/cubefs
[2025-08-24 14:40:35 CST] 0B build/# 删除一个目录
[root@k8s-master01 ~]# mc rm projecta/app/cubefs/ -r --force
5、CubeFS 对接 K8s
5.1 CSI 部署
首先给非控制节点打上 CSI 的标签(需要使用存储的节点都需要打标签):
[root@k8s-master01 ~]# kubectl label node component.cubefs.io/csi=enabled -l '!node-role.kubernetes.io/control-plane'
更改 values 配置:
[root@k8s-master01 ~]# cd cubefs-helm/cubefs/
[root@k8s-master01 cubefs]# vim values.yaml
[root@k8s-master01 cubefs]# sed -n "2p;8p;193p;207,214p;217p;219p" values.yaml
component:csi: true
csi:resources:enabled: falserequests:memory: "1024Mi"cpu: "200m"limits:memory: "2048Mi"cpu: "2000m"setToDefault: truereclaimPolicy: "Delete"
# 执行安装:
[root@k8s-master01 cubefs]# helm upgrade cubefs -n cubefs .# 查询创建的 StorageClass:
[root@k8s-master01 cubefs]# kubectl get sc
NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE
cfs-sc (default) csi.cubefs.com Delete Immediate true 13s# 查看 Pod
[root@k8s-master01 cubefs]# kubectl get po -n cubefs
NAME READY STATUS RESTARTS AGE
cfs-csi-controller-7cd54dddff-t5npw 4/4 Running 0 11m
cfs-csi-node-4qn6g 2/2 Running 0 11m
cfs-csi-node-hbq99 2/2 Running 0 11m
....
5.2 PVC 和 PV 测试
创建 PVC 测试:
[root@k8s-master01 ~]# vim cfs-pvc.yaml
[root@k8s-master01 ~]# cat cfs-pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:name: cubefs-testnamespace: default
spec:accessModes:- ReadWriteManyresources:requests:storage: 1GistorageClassName: cfs-scvolumeMode: Filesystem
创建后,查看 PV 和绑定状态:
[root@k8s-master01 ~]# kubectl create -f cfs-pvc.yaml [root@k8s-master01 cubefs]# kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS VOLUMEATTRIBUTESCLASS REASON AGE
pvc-e4f37ba6-ebe9-48f7-bd5e-5dbe8bda0a77 1Gi RWX Delete Bound default/cubefs-test cfs-sc <unset> 72s[root@k8s-master01 cubefs]# kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS VOLUMEATTRIBUTESCLASS AGE
cubefs-test Bound pvc-e4f37ba6-ebe9-48f7-bd5e-5dbe8bda0a77 1Gi RWX cfs-sc <unset> 7m37s
创建服务挂载测试:
[root@k8s-master01 ~]# kubectl create deploy nginx --image=crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/nginx:1.15.12 --dry-run=client -oyaml > nginx-deploy.yaml[root@k8s-master01 ~]# vim nginx-deploy.yaml
[root@k8s-master01 ~]# cat nginx-deploy.yaml
apiVersion: apps/v1
kind: Deployment
metadata:creationTimestamp: nulllabels:app: nginxname: nginx
spec:replicas: 2selector:matchLabels:app: nginxstrategy: {}template:metadata:creationTimestamp: nulllabels:app: nginxspec:nodeSelector: # 只有安装了 CSI 驱动的才可以挂载存储component.cubefs.io/csi: enabledvolumes:- name: mypvcpersistentVolumeClaim:claimName: cubefs-testcontainers:- image: crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/nginx:1.15name: nginxvolumeMounts:- name: mypvcmountPath: "/mnt" # 挂载共享目录resources: {}
status: {}
数据共享测试:
# 创建
[root@k8s-master01 ~]# kubectl create -f nginx-deploy.yaml# 查看pod
[root@k8s-master01 ~]# kubectl get po
NAME READY STATUS RESTARTS AGE
nginx-5c4f45cbc-8jr69 1/1 Running 0 80s
nginx-5c4f45cbc-cjhps 1/1 Running 0 80s# 登录其中一个容器写入一个数据
[root@k8s-master01 ~]# kubectl exec -it nginx-5c4f45cbc-8jr69 -- bash
root@nginx-5c4f45cbc-8jr69:/# echo "ceshi" > /mnt/test # 验证数据是否共享成功
[root@k8s-master01 ~]# kubectl exec -it nginx-5c4f45cbc-cjhps -- bash
root@nginx-5c4f45cbc-cjhps:/# ls /mnt/
test
5.3 在线扩容
动态存储大部分都支持在线扩容,可以直接编辑 PVC 即可:
[root@k8s-master01 ~]# vim cfs-pvc.yaml
[root@k8s-master01 ~]# cat cfs-pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:name: cubefs-testnamespace: default
spec:accessModes:- ReadWriteManyresources:requests:storage: 2GistorageClassName: cfs-scvolumeMode: Filesystem# 更新配置
[root@k8s-master01 ~]# kubectl apply -f cfs-pvc.yaml
等待一段时间即可完成扩容:
[root@k8s-master01 ~]# kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS VOLUMEATTRIBUTESCLASS AGE
cubefs-test Bound pvc-e4f37ba6-ebe9-48f7-bd5e-5dbe8bda0a77 2Gi RWX cfs-sc <unset> 22m
6、数据持久化实战
6.1 MySQL 数据持久化
创建 PVC:
[root@k8s-master01 ~]# vim mysql-pvc.yaml
[root@k8s-master01 ~]# cat mysql-pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:name: mysqlnamespace: default
spec:accessModes:- ReadWriteOnceresources:requests:storage: 5GistorageClassName: cfs-scvolumeMode: Filesystem# 创建PVC
[root@k8s-master01 ~]# kubectl create -f mysql-pvc.yaml
[root@k8s-master01 ~]# kubectl get pvc mysql
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS VOLUMEATTRIBUTESCLASS AGE
mysql Bound pvc-658e0ed8-6e9d-493d-b1f6-870df9c1b15c 5Gi RWO cfs-sc <unset> 22s
创建 Deployment:
[root@k8s-master01 ~]# vim mysql-deploy.yaml
[root@k8s-master01 ~]# cat mysql-deploy.yaml
apiVersion: apps/v1
kind: Deployment
metadata:creationTimestamp: nulllabels:app: mysqlname: mysql
spec:replicas: 1selector:matchLabels:app: mysqlstrategy:type: Recreatetemplate:metadata:creationTimestamp: nulllabels:app: mysqlspec:nodeSelector:component.cubefs.io/csi: enabledvolumes:- name: datapersistentVolumeClaim:claimName: mysqlcontainers:- image: crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/mysql:8.0.20name: mysqlenv:- name: MYSQL_ROOT_PASSWORDvalue: mysqlvolumeMounts:- name: datamountPath: "/var/lib/mysql"resources: {}
status: {}# 创建 mysql
[root@k8s-master01 ~]# kubectl create -f mysql-deploy.yaml# 查看pod
[root@k8s-master01 ~]# kubectl get po
NAME READY STATUS RESTARTS AGE
mysql-7fc554db7f-b58b4 1/1 Running 0 4m30s
写入数据测试:
[root@k8s-master01 ~]# kubectl exec -it mysql-7fc554db7f-b58b4 -- bash
root@mysql-7fc554db7f-b58b4:/# mysql -uroot -pmysql
....
mysql> create database cubefs;
Query OK, 1 row affected (0.08 sec)mysql> create database yunwei;
Query OK, 1 row affected (0.07 sec)mysql> show databases;
+--------------------+
| Database |
+--------------------+
| cubefs |
| information_schema |
| mysql |
| performance_schema |
| sys |
| yunwei |
+--------------------+
6 rows in set (0.01 sec)
删除 Pod 后测试数据是否还在:
[root@k8s-master01 ~]# kubectl delete po mysql-7fc554db7f-b58b4
[root@k8s-master01 ~]# kubectl exec -it mysql-7fc554db7f-dk6rx -- bash
root@mysql-7fc554db7f-b58b4:/# mysql -uroot -pmysql
....
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| cubefs |
| information_schema |
| mysql |
| performance_schema |
| sys |
| yunwei |
+--------------------+
6 rows in set (0.01 sec)
6.2 大模型文件持久化
CubeFS 可以支撑 AI 训练、模型存储及分发、IO 加速等需求,所以可以直接把 CubeFS 作为大模型的数据存储底座。
创建 PVC:
[root@k8s-master01 ~]# vim ollama-pvc.yaml
[root@k8s-master01 ~]# cat ollama-pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:name: ollama-datanamespace: default
spec:accessModes:- ReadWriteManyresources:requests:storage: 10GistorageClassName: cfs-scvolumeMode: Filesystem# 创建PVC
[root@k8s-master01 ~]# kubectl create -f ollama-pvc.yaml
[root@k8s-master01 ~]# kubectl get pvc ollama-data
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS VOLUMEATTRIBUTESCLASS AGE
ollama-data Bound pvc-9bb055e3-10f7-4bf8-8e26-8d44c4b8fa28 10Gi RWX cfs-sc <unset> 53s
创建 Ollama 服务:
[root@k8s-master01 ~]# vim ollama-deploy.yaml
[root@k8s-master01 ~]# cat ollama-deploy.yaml
apiVersion: apps/v1
kind: Deployment
metadata:creationTimestamp: nulllabels:app: ollamaname: ollama
spec:replicas: 1selector:matchLabels:app: ollamatemplate:metadata:creationTimestamp: nulllabels:app: ollamaspec:nodeSelector:component.cubefs.io/csi: enabledvolumes:- name: datapersistentVolumeClaim:claimName: ollama-datareadOnly: falsecontainers:- image: crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/ollamaname: ollamaenv:- name: OLLAMA_MODELSvalue: /data/modelsvolumeMounts:- name: datamountPath: /data/modelsreadOnly: falseresources: {}
status: {}# 创建 ollama
[root@k8s-master01 ~]# kubectl create -f ollama-deploy.yaml # 查看pod
[root@k8s-master01 ~]# kubectl get po
NAME READY STATUS RESTARTS AGE
ollama-cf4978c7f-mjgv9 1/1 Running 0 30m
下载模型:
[root@k8s-master01 ~]# kubectl exec -it ollama-cf4978c7f-mjgv9 -- bash
root@ollama-cf4978c7f-mjgv9:/# ollama pull deepseek-r1:1.5b
查看模型文件:
root@ollama-cf4978c7f-mjgv9:~# ls -l /data/models/
total 0
drwxr-xr-x 7 root root 0 Aug 25 00:34 blobs
drwxr-xr-x 3 root root 0 Aug 25 00:35 manifests
启动模型测试:
root@ollama-cf4978c7f-mjgv9:~# ollama run deepseek-r1:1.5b
>>> 介绍一下自己
<think></think>您好!我是由中国的深度求索(DeepSeek)公司开发的智能助手DeepSeek-R1。有关模型和产品的详细内容请参考官方文档。>>>
此博客来源于:https://edu.51cto.com/lecturer/11062970.html