Cloud Storage FUSE — POSIX Interface Trên Object Storage
Tại Sao Quan Trọng Trong Production
Cloud Storage FUSE (gcsfuse) là bridge giữa POSIX filesystem semantics và GCS object model — hai thế giới có cơ chế vận hành hoàn toàn khác nhau. Nhiều team dùng gcsfuse để cho applications "thấy" GCS như một local directory mà không cần sửa code. Nhưng semantic gaps giữa POSIX và object storage tạo ra những failure modes rất khó debug: silent data corruption, unexpected write behavior, và performance cliffs không rõ nguyên nhân.
Internal Model — Cách FUSE Hoạt Động
Kernel FUSE Interface
FUSE (Filesystem in Userspace) là Linux kernel mechanism cho phép implement filesystem trong user-space process. Kernel intercept filesystem syscalls (open, read, write, stat...) và forward sang FUSE daemon qua /dev/fuse.
Application process
│ open("file.txt", O_RDONLY)
↓
Linux VFS (Virtual Filesystem Switch)
│ filesystem mounted? → FUSE
↓
/dev/fuse character device
│ FUSE protocol message
↓
gcsfuse daemon (user space)
│ GCS API call
↓
GCS object storagegcsfuse là FUSE daemon implement filesystem semantics trên GCS. Khi bạn mount:
gcsfuse my-bucket /mnt/gcsgcsfuse process chạy trong background, chặn tất cả VFS calls đến /mnt/gcs, translate sang GCS API calls.
Object Name → Directory Translation
GCS không có directory concept — chỉ có flat key-value store. gcsfuse simulate directories bằng cách interpret slash character trong object name:
GCS objects:
"data/2024/jan/file1.csv"
"data/2024/feb/file2.csv"
"data/readme.txt"
gcsfuse hiển thị:
/mnt/gcs/
├── data/
│ ├── 2024/
│ │ ├── jan/
│ │ │ └── file1.csv
│ │ └── feb/
│ │ └── file2.csv
└── readme.txtDirectory listing trong gcsfuse thực chất là ListObjects API call với prefix filter. Không có real directory objects trừ khi bucket có hierarchical namespace (HNS) enabled.
Write Path — Bất Đối Xứng Nghiêm Trọng
Write path của gcsfuse có đặc điểm quan trọng: writes phải buffer toàn bộ object vào local tmp trước khi upload:
write(fd, data, 1MB)
→ gcsfuse buffer vào /tmp/gcsfuse-XX (local disk)
write(fd, data, 1MB) # lần 2
→ gcsfuse buffer tiếp vào /tmp/gcsfuse-XX
close(fd) # hoặc flush
→ gcsfuse upload TOÀN BỘ object lên GCS
→ Object cũ bị replace hoàn toànĐiều này có hệ quả:
- Cần local disk space bằng kích thước object đang write
- Write không visible cho GCS cho đến khi close/flush
- Với file lớn (checkpoint ML model, video), write latency = upload time toàn bộ file
- Nếu process crash trước
close, write bị lost hoàn toàn
Tuy nhiên, kể từ gcsfuse version gần đây: files lớn hơn 2MB hỗ trợ append partial writes, nhưng vẫn cần buffer portion đó trước khi upload.
Read Path — Sequential vs Random Access
Sequential reads (đọc từ đầu đến cuối): gcsfuse stream data từ GCS, performant.
Random reads (seek đến offset cụ thể rồi đọc): gcsfuse cần GET request với Range header cho mỗi random access. Mỗi seek có thể tạo ra một HTTP request mới với overhead connection setup.
# Performant qua gcsfuse
with open("/mnt/gcs/large-file.parquet", "rb") as f:
data = f.read() # sequential, 1 HTTP GET
# Kém performant qua gcsfuse
with open("/mnt/gcs/large-file.parquet", "rb") as f:
f.seek(100_000_000) # HTTP GET Range: bytes=100000000-...
chunk1 = f.read(1024)
f.seek(50_000_000) # HTTP GET Range: bytes=50000000-...
chunk2 = f.read(1024)Parquet readers, database engines, hay bất kỳ code nào dùng random access pattern sẽ có performance kém qua gcsfuse.
Caching Layers
gcsfuse có ba tầng caching để giảm API calls:
1. Stat Cache (Metadata Cache)
Cache kết quả của stat() syscall (file size, modification time, permissions). Giảm số lượng GetObject metadata requests.
gcsfuse --stat-cache-ttl=60s --stat-cache-capacity=65536 my-bucket /mnt/gcsTTL càng dài → fewer API calls nhưng stale metadata. Với versioned buckets hoặc buckets có nhiều writers, stale stat cache có thể dẫn đến reading wrong version.
2. List Cache (Directory Cache)
Cache kết quả của readdir() (directory listings). Mỗi ls lệnh trigger ListObjects API call — với nhiều ls calls, cache giảm đáng kể API costs.
gcsfuse --dir-mode=755 --stat-cache-ttl=300s my-bucket /mnt/gcs3. File Cache (Data Cache)
Kể từ gcsfuse v1.0+, hỗ trợ file data caching — cache actual object data trên local disk. Đặc biệt hữu ích cho AI/ML workloads với checkpoint reads.
gcsfuse --cache-dir=/ssd-cache \
--file-cache-max-size-gb=100 \
my-bucket /mnt/gcsFile cache chứa full objects — lần đầu read tải về và cache, lần sau read từ local disk. Phù hợp cho read-heavy, repeated access patterns.
POSIX Semantic Gaps
gcsfuse không POSIX compliant — đây là điểm quan trọng nhất cần hiểu trước khi deploy.
Không Có Hard Links
GCS không hỗ trợ multiple references đến cùng object. ln (hard link) sẽ fail.
Không Có Atomic Directory Operations
rename trên directory trong POSIX là atomic. Trong gcsfuse (không có HNS):
rename("/mnt/gcs/dir-old", "/mnt/gcs/dir-new")
→ gcsfuse list tất cả objects với prefix "dir-old/"
→ Copy từng object sang "dir-new/" prefix
→ Delete từng object cũKhông atomic — partial rename có thể xảy ra nếu crash giữa chừng. Với HNS enabled, rename directories là atomic.
Không Có File Locking
flock(), fcntl() locks không work qua gcsfuse. Applications rely vào file locking (database engines, some logging systems) sẽ không hoạt động đúng.
Concurrent Writers — Precondition Check
gcsfuse dùng generation precondition để detect concurrent writes:
Writer A: open("file.txt") → read generation=100
Writer B: open("file.txt") → write → generation=101
Writer A: write → close → upload với ifGenerationMatch=100
→ GCS trả 412: generation không match (hiện là 101)
→ gcsfuse return EEXIST hoặc EIO tùy contextĐiều này ngăn silent overwrite nhưng cũng nghĩa là concurrent writes luôn fail. Chỉ một writer thành công, những cái còn lại nhận error.
Không Có Metadata Propagation
gcsfuse không upload object metadata chuẩn (như mtime) trừ khi được cấu hình đặc biệt. File modification time có thể không được preserved qua FUSE mount.
Performance Characteristics & Anti-Patterns
Latency So Với Local Filesystem
Mỗi file operation qua gcsfuse ít nhất là 1 HTTP round trip đến GCS. Với regional bucket cùng region, latency ~2-10ms/operation. So sánh với local SSD: ~0.1ms.
ls /mnt/gcs/large-dir/ # 1000 objects → có thể cần nhiều ListObjects calls
# Latency: 100ms - vài giây tùy số objects
ls /local-ssd/large-dir/ # MillisecondsDirectories với hàng triệu objects không nên list thường xuyên qua gcsfuse.
Throughput For AI/ML Workloads
gcsfuse được tối ưu cho AI/ML use case:
- Parallel downloads: Tự động parallelize downloads cho cùng object (multi-threaded streaming)
- Prefetching: Read-ahead caching cho sequential workloads
- Rapid Bucket support: Kể từ gcsfuse 3.7.1, hỗ trợ Rapid Bucket với throughput cao hơn
# Tối ưu gcsfuse cho training data
gcsfuse \
--implicit-dirs \
--file-cache-max-size-gb=200 \
--cache-dir=/tmp/gcsfuse-cache \
--max-conns-per-host=100 \
training-data-bucket /mnt/training-dataAnti-Pattern: Database Files Trên gcsfuse
Đặt database files (SQLite, RocksDB, PostgreSQL data dir) trên gcsfuse mount là anti-pattern nghiêm trọng:
- Databases cần random read/write access → performance cliff
- File locking không work → corruption risk
- WAL (write-ahead log) semantics không được đảm bảo
- GCS không hỗ trợ in-place byte-range writes
Anti-Pattern: Object Versioning Với gcsfuse
Buckets với object versioning enabled tạo ra undefined behavior với gcsfuse. Mỗi write tạo noncurrent versions, nhưng gcsfuse không biết về versioning — có thể đọc wrong version hoặc create unexpected noncurrent objects.
Recommendation: Bucket dùng với gcsfuse không nên enable object versioning.
GKE Integration
Trong GKE, gcsfuse được tích hợp qua GKE FUSE sidecar (gke-gcsfuse-sidecar):
annotations:
gke.io/fuse-annotation: "true"
volumes:
- name: gcs-fuse-vol
csi:
driver: gcsfuse.csi.storage.gke.io
volumeAttributes:
bucketName: my-training-data
mountOptions: "file-cache-max-size-gb=100"Sidecar inject tự động, mount bucket trong Pod container. Workload Identity được dùng để authenticate, không cần key files.
Khi Nào Dùng gcsfuse
Phù hợp:
- ML training jobs đọc large files (model weights, training datasets)
- Batch processing pipelines đọc data từ GCS
- Applications cần đọc config/model files từ GCS mà không muốn thay đổi code
- Read-heavy workloads với repeated access (file cache tận dụng tốt)
Không phù hợp:
- Databases hay stateful applications cần file locking
- Workloads với nhiều small random reads/writes
- Applications cần atomic directory operations
- High-frequency write workloads (checkpoint mỗi giây)