Fluid 与 S3FS 对接 S3 存储及性能测试
一、概述
1. 简介
A. 是什么
Fluid 是一个 Kubernetes 原生的数据集编排和加速工具,通过 S3FS 将 S3 兼容存储挂载为 Pod 可用的 PVC,实现云存储的透明访问。
B. 为什么学
- 解决 Kubernetes Pod 访问 S3 存储的复杂性问题
- 实现存储资源的统一管理和调度
- 支持多种 S3 兼容存储(华为云 OBS、阿里云 OSS、AWS S3 等)
C. 学完能做什么
- 自定义 Fluid 镜像以支持 S3FS 挂载
- 配置 Dataset 和 ThinRuntime 实现 S3 存储挂载
- 使用 JuiceFS Bench 进行性能测试
2. 前置知识
A. 必备技能
- Kubernetes 基础操作(kubectl 命令)
- Docker 镜像构建基础
- S3 存储概念(Bucket、Access Key、Secret Key)
B. 推荐知识
- Fluid 架构和基本概念
- FUSE 文件系统原理
二、制作镜像
1. 系统架构
Fluid 通过 ThinRuntime 机制支持自定义文件系统。S3FS 是一个基于 FUSE 的 S3 文件系统客户端,可以将 S3 存储挂载到本地文件系统。
graph TB
subgraph Kubernetes
Pod[Pod 应用容器]
PVC[PersistentVolumeClaim]
Runtime[ThinRuntime Fuse 容器]
end
Pod --> PVC
PVC --> Runtime
Runtime --> S3FS[S3FS FUSE 挂载]
S3FS --> S3[(S3 兼容存储)]2. 组件说明
A. fluid_config_init.py
Fluid 配置初始化脚本,负责:
- 从 Fluid 配置文件读取挂载参数
- 生成 S3FS 认证文件
- 生成挂载脚本
B. entrypoint.sh
容器入口脚本,执行初始化并启动 S3FS 挂载。
C. Dockerfile
构建自定义 Fuse 镜像的模板。
3. 配置文件详解
A. fluid_config_init.py
#!/usr/bin/env python
import json
import os
rawStr = ""
with open("/etc/fluid/config.json", "r") as f:
rawStr = f.readlines()
rawStr = rawStr[0]
script = """
#!/bin/sh
set -ex
MNT_TO=$targetPath
trap "umount ${MNT_TO}" SIGTERM
mkdir -p ${MNT_TO} || true
s3fs $bucket:$bucketPath $MNT_TO -o url=$url -o allow_other -f -d -o f2
echo "mounted and exit code: $?"
sleep inf
"""
obj = json.loads(rawStr)
with open("/root/.passwd-s3fs", "w") as f:
f.write("%s:%s\n" % (obj["mounts"][0]["options"]["s3-access-key"], obj["mounts"][0]["options"]["s3-access-secret"]))
os.chmod("/root/.passwd-s3fs", 0o600)
bucketPath = obj["mounts"][0]["mountPoint"].lstrip("s3://").rstrip("/")
bucket = bucketPath.split("/")[0]
bucketPath = bucketPath[len(bucket):]
with open("/mount-s3.sh", "w") as f:
f.write('targetPath="%s"\n' % obj["targetPath"])
f.write('bucket="%s"\n' % bucket)
f.write('bucketPath="%s"\n' % bucketPath)
f.write('url="%s"\n' % obj["mounts"][0]["options"]["url"])
f.write(script)关键逻辑说明:
- 读取 Fluid 注入的配置文件 /etc/fluid/config.json
- 提取 S3 认证信息并写入 /root/.passwd-s3fs(权限设为 600)
- 解析 S3 路径,分离 bucket 和 bucketPath
- 生成动态挂载脚本,包含 s3fs 挂载命令
B. entrypoint.sh
#!/usr/bin/env bash
set +x
python /fluid_config_init.py
chmod u+x /mount-s3.sh
bash /mount-s3.sh执行流程:
- 关闭命令回显(set +x)避免泄露敏感信息
- 调用 Python 脚本生成挂载配置
- 为挂载脚本添加执行权限
- 执行 S3FS 挂载
C. Dockerfile
FROM shaowenchen/runtime-ubuntu:20.04
RUN apt-get update && apt-get install -y python s3fs
COPY ./fluid_config_init.py /
COPY ./entrypoint.sh /usr/local/bin/
RUN chmod +x /usr/local/bin/entrypoint.sh
ENTRYPOINT []构建步骤:
- 基于 Ubuntu 20.04 运行时镜像
- 安装 Python 和 s3fs
- 复制配置脚本和入口脚本
- 设置入口脚本执行权限
4. 构建镜像
docker build . --network=host -f Dockerfile -t shaowenchen/demo:fluid-s3fs
docker push shaowenchen/demo:fluid-s3fs注意事项:
- 使用 --network=host 避免网络隔离问题
- 镜像名称需要与后续 ThinRuntimeProfile 配置一致
三、挂载 S3 存储
1. 配置环境变量
export ENDPOINT=obs.ap-southeast-3.myhuaweicloud.com
export BUCKET=
export AK=
export SK=参数说明:
- ENDPOINT:S3 兼容存储的服务地址
- BUCKET:存储桶名称
- AK:访问密钥 ID
- SK:访问密钥 Secret
2. 创建 Dataset
Dataset 定义了数据集的挂载点和认证信息。
kubectl apply -f - <<EOF
apiVersion: data.fluid.io/v1alpha1
kind: Dataset
metadata:
name: mys3fs
spec:
mounts:
- mountPoint: s3://${BUCKET}/test1
options:
s3-access-key: ${AK}
s3-access-secret: ${SK}
url: https://${ENDPOINT}
EOF配置解析:
- mountPoint:S3 存储路径,格式为 s3://bucket/path
- options.s3-access-key:访问密钥 ID
- options.s3-access-secret:访问密钥 Secret
- options.url:完整的 S3 服务端点 URL
3. 创建 ThinRuntimeProfile
ThinRuntimeProfile 定义了 Fuse 文件系统的运行时配置。
kubectl apply -f - <<EOF
apiVersion: data.fluid.io/v1alpha1
kind: ThinRuntimeProfile
metadata:
name: s3fs-profile
spec:
fileSystemType: s3fs
fuse:
image: shaowenchen/demo:fluid-s3fs
imageTag: latest
imagePullPolicy: Always
command:
- "/usr/local/bin/entrypoint.sh"
EOF配置解析:
- fileSystemType:指定为 s3fs
- fuse.image:自定义 Fuse 镜像地址
- fuse.command:容器入口命令
4. 创建 ThinRuntime
ThinRuntime 引用 Profile 并关联 Dataset。
kubectl apply -f - <<EOF
apiVersion: data.fluid.io/v1alpha1
kind: ThinRuntime
metadata:
name: mys3fs-37
spec:
profileName: s3fs-profile
EOF命名规则:
- ThinRuntime 名称需要与 Dataset 名称保持一致或使用约定的后缀
- Fluid 会自动创建对应的 PVC
5. 创建 Pod 负载
kubectl apply -f - <<EOF
apiVersion: v1
kind: Pod
metadata:
name: mys3fs
spec:
containers:
- name: mys3fs
image: shaowenchen/demo:ubuntu
volumeMounts:
- mountPath: /data
name: mys3fs
volumes:
- name: mys3fs
persistentVolumeClaim:
claimName: mys3fs
EOF挂载验证:
- 进入 Pod 后,/data 目录即为 S3 存储的挂载点
- 可以通过 ls、cat 等命令验证文件访问
四、性能测试
1. 测试工具
使用 JuiceFS Bench 进行性能基准测试,该工具可以测试:
- 大文件读写性能
- 小文件读写性能
- 文件元数据操作性能
2. 测试步骤
A. 进入 Pod
kubectl exec -it mys3fs -- bashB. 安装 JuiceFS 客户端
curl -sSL https://d.juicefs.com/install | sh -C. 执行性能测试
juicefs bench --block-size 4 --big-file-size 1024 /data参数说明:
- --block-size 4:块大小 4 MiB
- --big-file-size 1024:大文件大小 1 GiB
3. 测试结果
Benchmark finished! BlockSize: 4.0 MiB, BigFileSize: 1.0 GiB, SmallFileSize: 128 KiB, SmallFileCount: 100, NumThreads: 1
+------------------+-----------------+----------------+
| ITEM | VALUE | COST |
+------------------+-----------------+----------------+
| Write big file | 194.80 MiB/s | 5.26 s/file |
| Read big file | 100.50 MiB/s | 10.19 s/file |
| Write small file| 3.6 files/s | 277.70 ms/file |
| Read small file | 51.1 files/s | 19.59 ms/file |
| Stat file | 26301.5 files/s | 0.04 ms/file |
+------------------+-----------------+----------------+结果分析:
- 大文件写入性能:194.80 MiB/s,适合顺序写入场景
- 大文件读取性能:100.50 MiB/s,读写不对称,可能受网络因素影响
- 小文件性能:写入较慢(3.6 files/s),读取较快(51.1 files/s)
- 元数据操作:Stat 性能极佳(26301.5 files/s),说明缓存机制有效
性能优化建议:
- 小文件写入场景建议启用本地缓存
- 大文件读写可考虑增加并发线程数
- 网络带宽可能是性能瓶颈,建议使用内网端点
五、清理资源
1. 删除 Pod
kubectl delete pod mys3fs2. 删除 ThinRuntime
kubectl delete thinruntime mys3fs3. 删除 Dataset
kubectl delete dataset mys3fs清理顺序:
- 先删除使用 PVC 的 Pod
- 再删除 ThinRuntime 释放 Fuse 容器
- 最后删除 Dataset 清除 PVC
六、常见问题
1. 版本兼容性
Fluid 1.0 与高版本的配置文件路径不同,需要根据实际版本调整 fluid_config_init.py 中的路径。
2. 认证失败
检查 /root/.passwd-s3fs 文件格式和权限,确保格式为 accessKey:secretKey,权限为 600。
3. 挂载超时
- 检查网络连接到 S3 端点的可达性
- 验证 Bucket 名称和路径是否正确
- 查看 S3FS 日志(通过 -f -d 参数启用前台调试模式)
4. 性能不达标
- 使用内网端点而非公网端点
- 调整 s3fs 挂载参数(如多线程、缓存大小)
- 考虑使用 JuiceFS 替代 S3FS 获得更好性能