三种 K8s 存储的"非主流"路线
主流 K8s 存储是 NFS + Ceph,但有些场景它们都力不从心:
- S3 兼容对象存储(备份、日志、镜像)→ MinIO
- 海量小文件 + 多云(AI 训练、媒资)→ JuiceFS
- 本地磁盘池化(DB 性能、StatefulSet)→ OpenEBS
本文一次讲清这三套方案。
适用版本:MinIO 2024.x / JuiceFS 1.x / OpenEBS 3.4
1. MinIO 作为 PV 存储
1.1 思路
通过 k8s-csi-s3 这个 CSI 驱动,让 S3(MinIO)作为 K8s 的 PV 后端——申请 PVC 时自动创建 S3 bucket,Pod 内能像本地目录一样访问。
警告:源码明确写"不建议生产环境使用"。原因是 S3 不是真正的文件系统,POSIX 兼容有限(特别是 append 写)。但作为 静态资源 / 备份 场景的 PV 非常合适。
1.2 要求
- Kubernetes 1.16+(CSI v1.0.0)
- kubelet 允许特权容器
- Docker daemon
MountFlags=shared(新增分区无需重启 Docker)
1
2
3
4
5
6
| # /etc/systemd/system/docker.service
[Service]
MountFlags=shared
Type=notify
ExecStart=/usr/local/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
...
|
1.3 创建 Secret
1
2
3
4
5
6
7
8
9
10
| apiVersion: v1
kind: Secret
metadata:
name: csi-driver-s3-secret
namespace: kube-system
stringData:
accessKeyID: "{{MINIO_ACCESS_KEY}}"
secretAccessKey: "{{MINIO_SECRET_KEY}}"
endpoint: https://<minio-endpoint>
region: ""
|
实际访问密钥用占位符 {{MINIO_ACCESS_KEY}} {{MINIO_SECRET_KEY}} 替代。
1.4 安装 CSI 驱动
按 yandex-cloud/k8s-csi-s3 仓库的 provisioner.yaml / attacher.yaml / csi-driver-s3.yaml / psp.yaml 部署。
1.5 mounter 选择
驱动支持 4 种 mount 工具:
| mounter | 兼容性 | 性能 | 适用 |
|---|
| rclone | 几乎完全 POSIX | 中 | 通用 |
| s3fs | 较大子集 | 中 | 通用,不支持 append |
| goofys | 弱 | 最高 | 只读/大批量,不支持 append |
| s3backer | 实验性 | - | 块设备,但卷损坏风险大 |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: csi-driver-s3
provisioner: s3.csi.metal-stack.io
parameters:
mounter: s3fs
csi.storage.k8s.io/provisioner-secret-name: csi-driver-s3-secret
csi.storage.k8s.io/provisioner-secret-namespace: kube-system
csi.storage.k8s.io/controller-publish-secret-name: csi-driver-s3-secret
csi.storage.k8s.io/controller-publish-secret-namespace: kube-system
csi.storage.k8s.io/node-stage-secret-name: csi-driver-s3-secret
csi.storage.k8s.io/node-stage-secret-namespace: kube-system
csi.storage.k8s.io/node-publish-secret-name: csi-driver-s3-secret
csi.storage.k8s.io/node-publish-secret-namespace: kube-system
|
1.6 使用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
| apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: csi-s3-pvc
namespace: default
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
storageClassName: csi-s3
---
apiVersion: v1
kind: Pod
metadata:
name: csi-s3-test-nginx
spec:
containers:
- name: csi-s3-test-nginx
image: nginx
volumeMounts:
- mountPath: /var/lib/www/html
name: webroot
volumes:
- name: webroot
persistentVolumeClaim:
claimName: csi-s3-pvc
readOnly: false
|
1
2
3
4
5
| kubectl exec -it csi-s3-test-nginx -- bash
cd /var/lib/www/html/
touch 2024-12-15.txt
ls
# 2024-12-15.txt
|
MinIO 上能看到自动创建的 bucket 里有这个文件。
2. JuiceFS 架构
2.1 三大组件
1
2
3
4
5
6
7
8
9
10
11
12
13
| ┌─────────────────────────────────────────────────────────┐
│ JuiceFS 文件系统 │
│ │
│ ┌────────────┐ ┌────────────┐ ┌──────────────────┐ │
│ │ JuiceFS │ │ 数据存储 │ │ 元数据引擎 │ │
│ │ Client │ │ (对象存储) │ │ (Redis/TiKV/MySQL│ │
│ │ (FUSE) │ │ S3/MinIO │ │ /PostgreSQL/ │ │
│ │ │ │ Ceph/OSS │ │ SQLite) │ │
│ └─────┬──────┘ └─────┬──────┘ └────────┬─────────┘ │
│ │ │ │ │
│ └───────────────┴──────────────────┘ │
│ POSIX 兼容挂载 │
└─────────────────────────────────────────────────────────┘
|
- Client:所有文件读写都在客户端,通过 FUSE 暴露 POSIX 接口
- 数据存储:文件切分上传到 S3/MinIO/Ceph
- 元数据引擎:文件名、权限、目录树、文件锁、引用计数等
2.2 5 种接入方式
| 方式 | 适用场景 |
|---|
| FUSE | 通用,Linux 服务器当本地盘用 |
| Hadoop Java SDK | 替代 HDFS |
| Kubernetes CSI | K8s 集群直接挂载 |
| S3 网关 | 用 AWS CLI / s3cmd 访问 JuiceFS |
| WebDAV | HTTP 协议 |
2.3 K8s 部署
JuiceFS 官方 CSI 文档:https://juicefs.com/docs/zh/community/getting-started/for_distributed
1
2
| helm repo add juicefs https://juicedata.github.io/charts
helm install juicefs juicefs/juicefs-csi-driver -n juicefs --create-namespace
|
创建 Secret 提供元数据引擎与对象存储凭据:
1
2
3
4
5
6
7
8
9
10
11
12
| apiVersion: v1
kind: Secret
metadata:
name: juicefs-secret
type: Opaque
stringData:
name: <filesystem-name>
metaurl: redis://:<redis-password>@<redis-host>:6379/1
bucket: http://<minio-host>:9000/<bucket>
access-key: {{MINIO_ACCESS_KEY}}
secret-key: {{MINIO_SECRET_KEY}}
storage-class: STANDARD
|
1
2
3
4
5
6
7
8
9
10
11
| apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: juicefs
provisioner: csi.juicefs.com
parameters:
csi.storage.k8s.io/provisioner-secret-name: juicefs-secret
csi.storage.k8s.io/provisioner-secret-namespace: default
csi.storage.k8s.io/node-publish-secret-name: juicefs-secret
csi.storage.k8s.io/node-publish-secret-namespace: default
reclaimPolicy: Retain
|
2.4 适用场景
- AI 训练数据集(海量小文件 + POSIX)
- 媒资管理(图片、视频)
- 跨云数据共享
3. OpenEBS 本地 PV
3.1 简介
传统 K8s LocalPV 受限于"单节点单盘",OpenEBS 通过 iSCSI 协议把"工作节点本地盘"池化:
- 本地卷(LocalPV):单节点本地盘,性能最高,DB 推荐
- 复制卷(cStor):跨节点复制,有冗余(3 副本)
3.2 内核要求
OpenEBS 走 iSCSI,所有节点装客户端:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| # CentOS
yum install iscsi-initiator-utils -y
# Ubuntu
apt install -y open-iscsi
# 启动
systemctl enable --now iscsid
systemctl start iscsid.service
# 可选:开启 nvme_tcp
modprobe iscsi_tcp
echo iscsi_tcp >/etc/modules-load.d/iscsi-tcp.conf
echo "nvme_tcp" | sudo tee /etc/modules-load.d/openebs.conf
|
3.3 部署 Operator
1
2
3
4
5
6
7
8
| # OpenEBS 官方源
helm repo add openebs https://openebs.github.io/openebs
helm repo update
helm install openebs \
--namespace openebs \
openebs/openebs \
--create-namespace
|
或者 yaml 方式:
1
| kubectl apply -f https://openebs.github.io/charts/openebs-operator.yaml
|
3.4 默认存储路径
1
2
| - name: BasePath
value: "/var/openebs/local/"
|
OpenEBS 在每个节点上 /var/openebs/local/ 下创建 PV。
3.5 使用
OpenEBS 装好后自动创建几个 StorageClass:
1
2
3
4
5
| kubectl get sc
# openebs-hostpath 默认
# openebs-device
# openebs-jiva-csi-default
# openebs-zfspv
|
直接引用:
1
2
3
4
5
6
7
8
9
10
11
| apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: my-pvc
spec:
storageClassName: openebs-hostpath
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 5Gi
|
3.6 备份
OpenEBS 推荐用 Velero 做备份,原理是 K8s 资源 + PV 数据快照到对象存储。
1
2
3
4
5
6
| velero install \
--provider aws \
--bucket <bucket-name> \
--secret-file ./credentials-velero \
--backup-location-config region=minio \
--use-restic
|
4. 三种方案对比
| 方案 | 类型 | 性能 | 容量上限 | 多 Pod 共享 | 适用 |
|---|
| MinIO CSI | 对象 | 中(小文件慢) | 无限 | 否(RWO) | 静态资源、备份 |
| JuiceFS | 分布式文件 | 中-高 | 无限 | 是(RWX) | AI 数据、媒资 |
| OpenEBS LocalPV | 本地盘 | 最高 | 单机 | 否 | DB、StatefulSet |
| OpenEBS cStor | 分布式块 | 中 | 中 | 否 | 通用数据库 |
5. 排错速查
5.1 MinIO CSI Pod 一直 Pending
通常是 RBAC / ServiceAccount 权限问题:
1
2
| kubectl describe pod csi-provisioner-s3 -n kube-system
# 查 Events
|
5.2 JuiceFS 挂载失败
- 元数据引擎(Redis/MySQL)网络可达?
- 对象存储 endpoint 正确?
- Secret 里的
access-key / secret-key 权限够?
5.3 OpenEBS Node Disk Manager 没起来
1
2
| kubectl get pods -n openebs
# openebs-ndm DaemonSet 没起 = iscsi 没装
|
5.4 OpenEBS PVC 一直 Pending
1
2
3
| kubectl describe pvc my-pvc
# 找"没有可用节点满足 volume node affinity"
# 解决:调度到打了 openebs.io/localpv 标签的节点
|
6. 小结
K8s 存储选型不是"一刀切":
- MinIO CSI 解决"对象存储当 PV 用"的备份场景
- JuiceFS 是"国内开源 + 兼容 S3 + POSIX"的分布式文件
- OpenEBS 把"工作节点本地盘"统一管理,性能和 Ceph RBD 不相上下
下一步:K8s PVC 备份恢复:CSI Snapshot / Velero / rsync 三方案。