Skip to main content

Curvine Architecture Deep Dive: System Design, Containers, and Data Flow

ยท 7 min read
Founder of Curvine

Curvine is an AI-Native and Cloud-Native distributed cache file system, written entirely in Rust. Born at OPPO and now a CNCF Landscape project, it layers full POSIX semantics over cloud object storage โ€” delivering local-disk speed for AI training, inference, and big data workloads while keeping S3, OSS, GCS, Azure Blob, and HDFS as the durable backbone.

This post walks through Curvine's architecture at three levels: the overall system context, the container-level service breakdown, and the end-to-end data flow for read and write operations.

1. System Context: Who Uses Curvine and What It Depends Onโ€‹

At the highest level, Curvine sits between compute workloads and durable storage. It exposes multiple access protocols upward and fans out to object storage backends downward.

Curvine System Context

Upstream Consumersโ€‹

ConsumerAccess Method
AI Training Jobs (PyTorch, TensorFlow)POSIX I/O via FUSE mount or S3-compatible gateway
Big Data Engines (Spark, Flink, Presto)HDFS protocol adapter or POSIX mount
AI Agents (RAG, Inference)Python/Java SDK, LanceDB vector store integration
DevOps / SRECLI tool (cv), Kubernetes kubectl, Web Dashboard
KubernetesCSI Driver for dynamic PV/PVC provisioning

Curvine integrates with big data engines transparently โ€” no custom connectors are needed. Spark, Flink, and Presto access Curvine through standard POSIX or HDFS interfaces, so existing pipelines work without modification.

Downstream Storage Backendsโ€‹

All persistent storage is abstracted behind the UFS (Underlying File System) layer:

  • AWS S3, Alibaba OSS, Google GCS, Azure Blob, Tencent COS โ€” via Apache OpenDAL adapters
  • HDFS / WebHDFS โ€” via JNI bridge or OpenDAL native
  • Alibaba OSS-HDFS (JindoFS) โ€” via native FFI adapter
  • MinIO and any S3-compatible store

Observabilityโ€‹

Curvine exports Prometheus metrics from all services and ships pre-built Grafana dashboard templates for cluster health, cache hit rates, worker utilization, and I/O throughput monitoring.


2. Container View: Services, Protocols, and Internal Boundariesโ€‹

Zooming into the Curvine cluster, the architecture separates cleanly into three planes: control, data, and access protocols.

Curvine Container View

Control Planeโ€‹

The control plane manages metadata, scheduling, and cluster coordination.

Master is the brain of the cluster. It runs as a Raft-replicated leader node responsible for:

  • Namespace & Inode Tree โ€” the complete file and directory hierarchy
  • Block Map & Scheduling โ€” mapping file blocks to worker nodes, with five scheduling policies (local, round-robin, random, load-based, weighted)
  • Worker Heartbeat โ€” health monitoring and capacity tracking
  • Mount Table & Quota โ€” UFS mount point management and per-directory quotas
  • TTL & Eviction โ€” time-to-live management and LFU-based cache eviction
  • Job Orchestration โ€” coordinating bulk data load and export jobs
  • Persistence โ€” RocksDB for inode storage, Raft journal for replication and HA

MDS (Metadata Service) is an optional, stateless metadata path backed by FoundationDB (production) or in-memory store (development). It provides a high-throughput metadata alternative for workloads that need to bypass the Raft journal.

Data Planeโ€‹

Workers are the data nodes that store and serve file blocks. Each worker implements a multi-tier cache hierarchy:

MEM โ†’ SSD โ†’ HDD โ†’ SPDK (NVMe-oF/RDMA)

Hot data automatically promotes to faster tiers; cold data demotes or evicts. Each worker maintains:

  • Block Store โ€” backed by RocksDB for block metadata, local filesystems for block data
  • Read/Write Handlers โ€” direct RPC handlers for client I/O
  • Replication โ€” block-level replication managed by the Master
  • Heartbeat โ€” periodic status reports to the Master

Workers can optionally use SPDK (Storage Performance Development Kit) for direct NVMe access via RDMA, bypassing the kernel for ultra-low latency.

Access Protocolsโ€‹

Curvine exposes five access paths, all converging on the same internal RPC layer:

ProtocolImplementationUse Case
FUSEcurvine-fuse (fuse2/fuse3)POSIX filesystem mount for any Linux application
Java SDKJNI bindings via curvine-libsdk-javaJVM-based big data applications
Python SDKPyO3 bindings via curvine-libsdk-pythonAI/ML training scripts, data pipelines
Rust SDKcurvine-sdk-coreNative Rust applications
CLIcv commandFile operations, benchmarking, mount management
Web Dashboardaxum REST APICluster monitoring and administration

Unified FS (curvine-unified-fs) is the internal abstraction that transparently falls back to UFS (object storage) on cache miss, so applications never need to know whether data is cached locally or fetched remotely.

Kubernetes Integrationโ€‹

The CSI Driver (curvine-csi) is a Go binary implementing the Container Storage Interface spec:

  • Controller โ€” dynamic PV provisioning (CreateVolume/DeleteVolume)
  • Node Plugin โ€” FUSE mount lifecycle management per node
  • Two modes: Standalone (FUSE in independent MountPod, recommended) or Embedded (FUSE inside CSI container)
  • StorageClass โ€” volumeBindingMode: Immediate, allowVolumeExpansion: true

Transfer Serviceโ€‹

The Transfer Service handles bulk data movement โ€” loading data from UFS into Curvine cache or exporting Curvine data to external systems. It maintains its own job store (SQLite by default, with MySQL and PostgreSQL options) and can run standalone or embedded in the Master.

LanceDB Integrationโ€‹

Curvine integrates with LanceDB to provide a vector database layer on top of Curvine's object storage. Built on the Lance columnar format and Apache Arrow, it enables AI applications to store and query vector embeddings directly through Curvine's storage backend.


3. Data Flow: How Read and Write Operations Traverse the Systemโ€‹

Understanding the data flow reveals why Curvine achieves local-disk performance for hot data while maintaining object-storage durability.

Curvine Data Flow

Read Path (6 Steps)โ€‹

Application โ†’ Protocol Layer โ†’ Unified FS โ†’ Master (metadata) โ†’ Worker (data) โ†’ [UFS on miss]
  1. Metadata Lookup โ€” The client sends an RPC to the Master to resolve the file path to inode metadata and block locations.

  2. Block Location Response โ€” The Master returns the list of block IDs and the worker nodes that hold them (or can fetch them).

  3. Scheduled Read โ€” The client connects directly to the assigned Worker via RPC to read the requested blocks. This avoids routing data through the Master.

  4. Cache Hit (Fast Path) โ€” The Worker serves the block from its multi-tier cache (MEM โ†’ SSD โ†’ HDD โ†’ SPDK). This is the hot path โ€” latency is comparable to local disk.

  5. Cache Miss (UFS Fetch) โ€” If the block is not cached, the Worker fetches it from the underlying object storage (S3, OSS, HDFS, etc.) via the OpenDAL adapter or native FFI bridge.

  6. Cache Promotion โ€” The fetched block is written into the Worker's cache, promoting it to the appropriate tier based on access frequency. Subsequent reads hit the cache directly.

Write Pathโ€‹

Application โ†’ Protocol Layer โ†’ Unified FS โ†’ Worker (write) โ†’ UFS (write-through)
  • The client writes blocks directly to the assigned Worker via RPC.
  • The Worker writes to its local cache tier and performs write-through to the underlying object storage for durability.
  • The Master is updated with new block metadata via the Raft-replicated journal.

Key Design Propertiesโ€‹

  • Metadata and data paths are separated โ€” metadata goes through the Master (or MDS), data goes directly to Workers. This prevents the Master from becoming a throughput bottleneck.
  • Client-to-Worker direct I/O โ€” once the Master provides block locations, clients talk to Workers directly. This scales data throughput linearly with the number of Workers.
  • Transparent UFS fallback โ€” the Unified FS layer handles cache misses transparently. Applications see a single POSIX namespace regardless of where data physically lives.
  • Multi-tier automatic promotion โ€” frequently accessed data migrates to faster tiers (MEM/SSD), while cold data demotes to HDD or evicts entirely.

4. Technology Stack Summaryโ€‹

LayerTechnology
LanguageRust (core), Go (CSI driver)
Async RuntimeTokio
RPCCustom protobuf-based (prost) over TCP
Metadata StoreRocksDB + Raft journal (Master), FoundationDB (MDS)
Object StorageApache OpenDAL (S3/OSS/GCS/Azure/COS/HDFS/WebHDFS)
Hardware AccelerationSPDK (NVMe-oF/RDMA), mimalloc/jemalloc
Vector DBLanceDB + Lance + Apache Arrow
KubernetesCSI Driver (Go), FUSE MountPod
ObservabilityPrometheus metrics + Grafana dashboards
BuildMakefile + Cargo workspace, Docker (CentOS/Rocky/Ubuntu/Amazon)

5. Summaryโ€‹

Curvine's architecture is designed around three principles:

  1. Separation of concerns โ€” Control plane (Master/MDS) handles metadata; data plane (Workers) handles I/O; protocol layer handles access diversity.
  2. Performance through caching โ€” Multi-tier cache (MEM โ†’ SSD โ†’ HDD โ†’ SPDK) with automatic promotion delivers local-disk latency for hot data.
  3. Durability through abstraction โ€” The UFS layer decouples Curvine from any single storage backend, allowing S3, OSS, GCS, Azure, or HDFS to serve as the persistent layer without application changes.

The result is a system that gives AI training jobs, big data engines, and Kubernetes workloads a unified POSIX interface with the speed of local storage and the durability of cloud object storage โ€” all in a single Rust-based binary.