StrmVol存储卷:如何解锁K8s对象存储海量小文件访问性能新高度?

本文涉及的产品
对象存储 OSS,20GB 3个月
对象存储 OSS,恶意文件检测 1000次 1年
对象存储 OSS,内容安全 1000 次 1年
简介: 如何提升海量文件的数据读取速率,对于AI训练集管理、量化回测、时序日志分析等场景尤为重要。阿里云容器服务(ACK))支持StrmVol类型存储卷,基于底层虚拟块设备及内核态文件系统,显著降低海量小文件访问延迟。

【阅读原文】戳:StrmVol存储卷:如何解锁K8s对象存储海量小文件访问性能新高度?

对象存储OSS凭借其支持海量非结构化数据存储、按需付费的弹性成本以及基于标准HTTP协议的跨平台便捷访问特性,成为大数据场景的重要存储方案。在Kubernetes(K8s)容器化业务中,提升OSS数据的访问性能能有效节省计算资源,提高业务效率。如何提升海量文件的数据读取速率,对于AI训练集管理、量化回测、时序日志分析等场景尤为重要。

 

阿里云容器服务(ACK)支持StrmVol类型存储卷,基于底层虚拟块设备及内核态文件系统,如ext4、EROFS(Extended Read-Only File System,扩展只读文件系统),显著降低海量小文件访问延迟。本文将简单介绍StrmVol存储方案的实现原理及适用场景,并以图片训练集读取场景为例,展示StrmVol存储卷的使用方式。

 

 

 

海量小文件数据的访问性能瓶颈

 

 

在K8s环境中,业务容器访问OSS的标准方式是通过存储卷机制。这一过程依赖于容器存储接口(CSI)驱动,目前主流的实现方案是通过FUSE(Filesystem in Userspace)客户端挂载OSS数据。

 

FUSE允许用户在用户态空间实现文件系统逻辑,通过内核与用户态的交互将对象存储的元数据和数据映射为本地文件系统接口(POSIX)。CSI驱动通过FUSE客户端将OSS路径挂载为容器内的本地目录,业务应用可直接通过标准文件操作(如open()read())访问数据。

 

针对顺序读写大文件场景,FUSE客户端可通过预读、缓存等技术显著提升性能(例如视频流媒体、大数据文件处理)。但在小文件场景依然存在性能瓶颈,这是因为:

 

  • 频繁的内核态切换:每次文件操作(如open()close())需在用户态FUSE进程与内核态之间多次上下文切换,导致额外开销。

 

  • 元数据管理压力:对象存储的元数据(如文件列表、属性)需通过HTTP/REST API查询,海量小文件的元数据请求会显著增加网络延迟和带宽占用。

 

 

 

StrmVol存储卷:虚拟块设备方案


 

 

为解决FUSE在海量小文件场景中的性能瓶颈,StrmVol存储卷提出了一种基于虚拟块设备(Virtual Block Device)加内核态文件系统(如EROFS)的方案,通过消除FUSE中间层的性能损耗,使数据访问路径直接下沉至存储驱动层,提升数据的访问速度,特别适用于AI训练集加载、时序日志分析等需要快速遍历百万级小文件的业务场景。

 

 

核心机制与优化细节

 

  • 快速索引构建:仅元信息同步,加速初始化流程

初始化阶段仅拉取OSS Bucket挂载点下文件元信息(如文件名、路径、大小)并构建索引,不包含对象扩展信息(如自定义元数据、标签),显著缩短索引构建时间,提升部署效率。

 

  • 内存预取优化:并发读取提升数据访问效率

虚拟块设备通过预设内存空间作为临时存储介质,根据已构建的索引信息提前并发预取后续可能访问的数据块。这一机制减少I/O等待时间,尤其在海量小文件场景中可降低读取延迟。

 

  • 内核态文件系统加速:避免用户态切换,提升容器化业务读取性能

容器化业务通过内核态文件系统 直接从内存中读取数据,避免用户态与内核态的频繁切换带来的上下文开销。其中,默认使用的EROFS文件系统通过压缩与高效访问机制,进一步提升存储空间利用率和数据读取性能。

 

 

适用场景

 

  • 数据已存储在OSS Bucket中,且在业务运行期间数据无更新需求。

 

  • 业务对文件系统的扩展信息不敏感。
  • 只读场景,尤其是海量小文件或随机读场景。


 

 

 

图像数据集加载性能测试

 

 

 

本文示例通过Argo Workflow模拟分布式图像数据集加载场景。

 

数据集基于ImageNet部分数据,假设存储于oss://imagenet/data/路径下,包含4个子目录(如oss://imagenet/data/n01491361/),每个目录存放10480张图像,约1.2 G大小。

 

 

安装strmvol-csi-driver

 

使用strmvol存储卷需要部署单独的CSI驱动(strmvol-csi-driver组件),可直接在ACK应用市场中部署。部署后,该CSI驱动与ACK组件管理中维护的csi-provisioner与csi-plugin组件相互独立,不会产生冲突。

 

image.png

 

 

创建StrmVol存储卷

 

StrmVol存储卷的PVC与PV定义与目前ACK OSS存储卷配置类似,本次测试中使用的存储卷YAML如下。

 

 

apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-strmvol
spec:
  capacity:
  # 挂载的OSS挂载点下最高可存储16 TiB数据。
    storage: 20Gi
  # 仅支持ReadOnlyMany访问模式。
  accessModes:
    - ReadOnlyMany
  persistentVolumeReclaimPolicy: Retain
  csi:
    driver: strmvol.csi.alibabacloud.com
    volumeHandle: pv-strmvol
    nodeStageSecretRef:
      name: strmvol-secret
      namespace: default
    volumeAttributes:
      bucket: imagenet
      path: /data
      url: oss-cn-hangzhou-internal.aliyuncs.com
      directMode: "false"
      resourceLimit: "4c8g"
---
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: pvc-strmvol
  namespace: default
spec:
  accessModes:
    - ReadOnlyMany
  resources:
    requests:
      storage: 20Gi
  volumeName: pv-strmvol

 

其中,比较重要的PV配置参数为directModeresourceLimit

 

  • directMode: 是否开启direct模式。开启时,关闭预取与数据本地缓存,适合小文件随机读场景,如训练集的随机批量读取。本次示例使用简单的顺序读取,因此选择关闭direct模式。

 

  • resourceLimit: 挂载虚拟块设备后能使用节点的最大资源限制。"4c8g"表示该虚拟块设备最多能占用节点的4 vCPU、8 GiB内存资源。

 

 

基于Argo Workflows创建数据集处理工作流任务

 

工作流分为三阶段:

 

1)list-shards阶段:通过Python脚本列出挂载路径下的4个目录生成路径集合;

 

2)parallel-processing阶段:并发启动4个子任务,每个任务通过parallel -j4指令对对应目录下的所有图像执行4线程并行读取操作(模拟加载);

 

3)calculate-averages阶段:汇总各任务耗时,计算并输出平均处理时间。

 

Argo Workflows组件可在ACK集群组件管理中快速安装。安装后,可使用Argo CLI或kubectl快速提交工作流[1]

 

 

apiVersion: argoproj.io/v1alpha1
kind: Workflow
metadata:
  generateName: distributed-imagenet-training-
spec:
  entrypoint: main
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
          - matchExpressions:
              - key: "node-type"
                operator: In
                values:
                  - "argo"
  volumes:
  - name: pvc-volume
    persistentVolumeClaim:
      claimName: pvc-strmvol
  templates:
  - name: main
    steps:
    - - name: list-shards
        template: list-imagenet-shards
    - - name: parallel-processing
        template: process-shard
        arguments:
          parameters:
            - name: paths
              value: "{{item}}"
        withParam: "{{steps.list-shards.outputs.result}}"
    - - name: calculate-statistics
        template: calculate-averages
  - name: list-imagenet-shards
    script:
      image: mirrors-ssl.aliyuncs.com/python:latest
      command: [python]
      source: |
        import subprocess
        import json
        output = subprocess.check_output("ls /mnt/data", shell=True, text=True)
        files = [f for f in output.split('\n') if f]
        print(json.dumps(files, indent=2))
      volumeMounts:
        - name: pvc-volume
          mountPath: /mnt/data
  - name: process-shard
    inputs:
      parameters:
      - name: paths
    container:
      image: alibaba-cloud-linux-3-registry.cn-hangzhou.cr.aliyuncs.com/alinux3/alinux3:latest
      command: [/bin/bash, -c]
      args:
      - |
        yum install -y parallel
        SHARD_JSON="/mnt/data/{{inputs.parameters.paths}}"
        SHARD_NUM="{{inputs.parameters.paths}}"
        START_TIME=$(date +%s)
        echo "Processing shard $SHARD_JSON"
        find "$SHARD_JSON" -maxdepth 1 -name "*.JPEG" -print0 | parallel -0 -j4 'cp {} /dev/null'
        END_TIME=$(date +%s)
        ELAPSED=$((END_TIME - START_TIME))
        mkdir -p /tmp/output
        echo $ELAPSED > /tmp/output/time_shard_${SHARD_NUM}.txt
      resources:
        requests:
          memory: "4Gi"
          cpu: "1000m"
        limits:
          memory: "4Gi"
          cpu: "2000m"
      volumeMounts:
        - name: pvc-volume
          mountPath: /mnt/data
    outputs:
      artifacts:
        - name: time_shard
          path: /tmp/output/time_shard_{{inputs.parameters.paths}}.txt
          oss:
            key: results/results-{{workflow.creationTimestamp}}/time_shard_{{inputs.parameters.paths}}.txt
          archive:
            none: {}
  - name: calculate-averages
    inputs:
      artifacts:
        - name: results
          path: /tmp/output
          oss:
            key: "results/results-{{workflow.creationTimestamp}}"
    container:
      image: registry-vpc.cn-beijing.aliyuncs.com/acs/busybox:1.33.1
      command: [sh, -c]
      args:
      - |
        echo "开始合并结果..."
        TOTAL_TIME=0
        SHARD_COUNT=0
        echo "各分片处理时间统计:"
        for time_file in /tmp/output/time_shard_*.txt; do
          TIME=$(cat $time_file)
          SHARD_ID=${time_file##*_}
          SHARD_ID=${SHARD_ID%.txt}
          echo "分片 ${SHARD_ID}: ${TIME} 秒"
          TOTAL_TIME=$((TOTAL_TIME + TIME))
          SHARD_COUNT=$((SHARD_COUNT + 1))
        done
        if [ $SHARD_COUNT -gt 0 ]; then
          AVERAGE=$((TOTAL_TIME / SHARD_COUNT))
          echo "--------------------------------"
          echo "总分片数量: $SHARD_COUNT"
          echo "总处理时间: $TOTAL_TIME 秒"
          echo "平均处理时间: $AVERAGE 秒/分片"
          echo "Average: $AVERAGE seconds" > /tmp/output/time_stats.txt
        else
          echo "错误:未找到分片时间数据"
          exit 1
        fi
    outputs:
      artifacts:
        - name: test-file
          path: /tmp/output/time_stats.txt
          oss:
            key: results/results-{{workflow.creationTimestamp}}/time_stats.txt
          archive:
            none: {}

 

工作流的运行结果如图所示,列举所有图像并读取其数据的平均耗时为21秒。

 

image.png

 

开始合并结果...
各分片处理时间统计:
分片 1: 21 秒
分片 2: 21 秒
分片 3: 22 秒
分片 4: 21 秒
--------------------------------
总分片数量: 4
总处理时间: 85 秒
平均处理时间: 21 秒/分片

 

 

 

 

开源方案

 

 

阿里云也将基于containerd/overlaybd项目[2]提供了该技术的开源实现,结合OCI image volume可以为容器挂载一个只读数据卷。详细介绍可参考KubeCon Europe 2025相关议题分享[3]

 

 

 

StrmVol存储卷总结

 

 

  • 核心优化:

 

  • 内存预取加速数据访问,减少I/O等待;
  • 内核态直接读取避免用户态切换开销;
  • 轻量索引快速初始化,仅同步必要元数据。

 

  • 适用场景:

 

  • 海量小文件只读场景;
  • OSS端数据存储无需频繁更新。

 

StrmVol的详细使用方式与更多压测数据,可阅读官方文档使用strmvol存储卷优化OSS小文件读取性能[4]


 

相关链接:

 

[1] 快速提交工作流

https://help.aliyun.com/zh/ack/distributed-cloud-container-platform-for-kubernetes/user-guide/create-a-workflow#section-bz1-rq8-7rz

 

[2] containerd/overlaybd项目

https://github.com/containerd/overlaybd

 

[3] KubeCon Europe 2025相关议题分享

https://www.youtube.com/watch?v=XqL5lh32lr8&t=962s

 

[4] 使用strmvol存储卷优化OSS小文件读取性能

https://help.aliyun.com/zh/ack/ack-managed-and-ack-dedicated/user-guide/use-strmvol-storage-volumes



我们是阿里巴巴云计算和大数据技术幕后的核心技术输出者。

欢迎关注 “阿里云基础设施”同名微信微博知乎

获取关于我们的更多信息~

相关实践学习
通过Ingress进行灰度发布
本场景您将运行一个简单的应用,部署一个新的应用用于新的发布,并通过Ingress能力实现灰度发布。
容器应用与集群管理
欢迎来到《容器应用与集群管理》课程,本课程是“云原生容器Clouder认证“系列中的第二阶段。课程将向您介绍与容器集群相关的概念和技术,这些概念和技术可以帮助您了解阿里云容器服务ACK/ACK Serverless的使用。同时,本课程也会向您介绍可以采取的工具、方法和可操作步骤,以帮助您了解如何基于容器服务ACK Serverless构建和管理企业级应用。 学习完本课程后,您将能够: 掌握容器集群、容器编排的基本概念 掌握Kubernetes的基础概念及核心思想 掌握阿里云容器服务ACK/ACK Serverless概念及使用方法 基于容器服务ACK Serverless搭建和管理企业级网站应用
相关文章
|
19天前
|
存储 Kubernetes 对象存储
StrmVol 存储卷:解锁 K8s 对象存储海量小文件访问性能新高度
本文介绍了阿里云容器服务(ACK)支持的StrmVol存储卷方案,旨在解决Kubernetes环境中海量小文件访问性能瓶颈问题。通过虚拟块设备与内核态文件系统(如EROFS)结合,StrmVol显著降低了小文件访问延迟,适用于AI训练集加载、时序日志分析等场景。其核心优化包括内存预取加速、减少I/O等待、内核态直接读取避免用户态切换开销,以及轻量索引快速初始化。示例中展示了基于Argo Workflows的工作流任务,模拟分布式图像数据集加载,测试结果显示平均处理时间为21秒。StrmVol适合只读场景且OSS端数据无需频繁更新的情况,详细使用方法可参考官方文档。
505 144
|
1月前
|
存储 弹性计算 数据管理
阿里云对象存储oss怎么收费?存储费用+流量收费标准
阿里云对象存储OSS收费标准包含存储费、流量费及请求费等,支持按量付费与包年包月两种模式。标准型本地冗余存储按量付费价格为0.09元/GB/月,包年包月500GB预留空间优惠价118元/年。流量费仅收取公网出方向费用,忙时0.50元/GB,闲时0.25元/GB。更多详情可参考官方页面。
|
1月前
|
存储 弹性计算 数据管理
阿里云对象存储OSS收费标准:500G存储118元1年、
阿里云对象存储OSS 2025年收费标准涵盖存储、流量及请求等费用,支持按量付费与包年包月两种模式。标准型存储按量价格为0.09元/GB/月,包年包月如9元享40GB体验价。流量费仅收取公网出方向,忙时0.50元/GB,闲时0.25元/GB。此外提供多种存储类型(低频、归档等)及流量包优惠方案,未使用功能不收费。详情见阿里云OSS官网。
684 6
|
4月前
|
存储 弹性计算 数据管理
阿里云对象存储OSS收费标准,存储、流量和请求等多个计费项
阿里云对象存储OSS收费标准涵盖存储、流量及请求费用,提供按量付费和包年包月两种模式。标准型OSS按量付费为0.09元/GB/月,包年包月40GB仅9元/年,500GB优惠价118元/年。流量费仅收取公网流出方向,内网流入流出免费。
330 13
|
存储 对象存储 云计算
|
3月前
|
SQL 分布式计算 Serverless
基于阿里云 EMR Serverless Spark 版快速搭建OSS日志分析应用
基于阿里云 EMR Serverless Spark 版快速搭建OSS日志分析应用
|
10月前
|
机器学习/深度学习 人工智能 专有云
人工智能平台PAI使用问题之怎么将DLC的数据写入到另一个阿里云主账号的OSS中
阿里云人工智能平台PAI是一个功能强大、易于使用的AI开发平台,旨在降低AI开发门槛,加速创新,助力企业和开发者高效构建、部署和管理人工智能应用。其中包含了一系列相互协同的产品与服务,共同构成一个完整的人工智能开发与应用生态系统。以下是对PAI产品使用合集的概述,涵盖数据处理、模型开发、训练加速、模型部署及管理等多个环节。
|
6月前
|
分布式计算 Java 开发工具
阿里云MaxCompute-XGBoost on Spark 极限梯度提升算法的分布式训练与模型持久化oss的实现与代码浅析
本文介绍了XGBoost在MaxCompute+OSS架构下模型持久化遇到的问题及其解决方案。首先简要介绍了XGBoost的特点和应用场景,随后详细描述了客户在将XGBoost on Spark任务从HDFS迁移到OSS时遇到的异常情况。通过分析异常堆栈和源代码,发现使用的`nativeBooster.saveModel`方法不支持OSS路径,而使用`write.overwrite().save`方法则能成功保存模型。最后提供了完整的Scala代码示例、Maven配置和提交命令,帮助用户顺利迁移模型存储路径。
|
9月前
|
存储 机器学习/深度学习 弹性计算
阿里云EMR数据湖文件系统问题之OSS-HDFS全托管服务的问题如何解决
阿里云EMR数据湖文件系统问题之OSS-HDFS全托管服务的问题如何解决
119 1
|
10月前
|
消息中间件 分布式计算 DataWorks
DataWorks产品使用合集之如何使用Python和阿里云SDK读取OSS中的文件
DataWorks作为一站式的数据开发与治理平台,提供了从数据采集、清洗、开发、调度、服务化、质量监控到安全管理的全套解决方案,帮助企业构建高效、规范、安全的大数据处理体系。以下是对DataWorks产品使用合集的概述,涵盖数据处理的各个环节。