POSIXはオブジェクトストアに本当に適さないのか?データに基づく答え

この投稿の著者は、MinIOの記事で提示された視点に疑問を呈し、POSIXがオブジェクトストアに適していないとされている。彼はMinIO s3fs-fuseとJuiceFSを含む包括的なテストを実施しました。結果は、MinIOとJuiceFSが優れたパフォーマンスを提供する一方で、s3fs-fuseは遅れていることを示しています。小さなファイルの上書きシナリオでは、JuiceFS FUSE-POSIXが他のソリューションよりも優れています.

最近、MinIOブログの記事を見つけました。タイトルは”オブジェクトストアの上にファイルシステムを置くのは悪いアイデアです。その理由.”著者はs3fs-fuseを例にとり、POSIXメソッドを使用してMinIOデータにアクセスする際に遭遇するパフォーマンスの課題を説明し、直接のMinIOアクセスに比べてパフォーマンスが大幅に遅れていることを強調しました。著者は、これらのパフォーマンスの問題をPOSIXの根本的な欠陥に帰属させています。しかし、私たちの経験はこの結論とは若干異なります。

POSIXは有用で広く採用されている標準です。POSIXに従ってソフトウェアを開発することで、異なるオペレーティングシステム間での互換性と移植性が保証されます。多くの業界でのアプリケーションの大部分がPOSIX標準に従っています。クラウドコンピューティング、ビッグデータ、AI技術の進歩**および蓄積されるデータ量の増加に伴い、オブジェクトストアのような弾力性のあるストレージソリューションの需要が高まっています。ただし、MinIOのようなオブジェクトストアが複数の言語でSDKを提供していても、多くの従来のアプリケーションはオブジェクトストレージAPIを使用するコードに適応することが難しいとされています。これにより、さまざまなストレージ製品がオブジェクトストアの上にPOSIXインターフェースを実装することで、この硬直的な需要に対応しています。

業界の多くの製品、例えばCeph、JuiceFS、Wekaなどが、オブジェクトストア上にPOSIXインターフェースを成功裏に実装しており、これらのソリューションは大きなユーザーベースと多くの成功事例を持ち、パフォーマンス面でも優れています。

POSIXの複雑性は確かに大きいものの、それに関連する問題は克服可能です。これらの主張を尊重しつつ確認したいとの願望から、テスト環境を設定し、MinIOの記事と同じサンプルデータとテスト方法を使用して検証を行いました。

比較された製品とテスト目的

包括的な評価を提供するために、JuiceFSを比較に加えました。

JuiceFSはオープンソースのクラウドネイティブな分散ファイルシステムです。オブジェクトストレージをデータストレージ層として採用し、メタデータを格納するための別個のデータベースに依存しています。POSIX API、S3 API、CSIドライバ、HDFS API、WebDAVなど、様々なアクセス方法を提供しており、ユニークなデータチャンキング、キャッシング、コンカレントリード/ライトメカニズムが搭載されています。JuiceFSは、オブジェクトストレージからPOSIXプロトコルへの変換を単に行うs3fs-fuseのようなツールとは根本的に異なるファイルシステムです。

JuiceFSを比較に導入することで、オブジェクトストレージの上にPOSIXのようなプロトコルを実装する際の利点と欠点を客観的に評価する狙いがありました。

I conducted the following two tests on MinIO, JuiceFS, and s3fs-fuse:

  • 10 GBのファイルを書き込む
  • Pandasで小さなファイルを上書きする

3つのソリューションはすべて、別個のサーバー上に展開されたMinIOインスタンスを基盤として使用しました。テストサンプルとしては、MinIOの記事で言及されたのと同じCSVファイルを使用した10 GBのファイルを用いました。

この記事のすべての環境、ソフトウェア、スクリプト、サンプルデータには、環境を再現し、テスト結果を繰り返し実行できるように完全なコードと指示が付属しています。

サーバーとテスト環境のセットアップ

同一構成のクラウドサーバー2台:

  • システム: Ubuntu 22.04 x64
  • CPU: 8コア
  • RAM: 16 GB
  • SSD: 500 GB
  • ネットワーク: VPC

各サーバーの情報:

Server IP Purpose
Server A 172.16.254.18 Deploying the MinIO instance
Server B 172.16.254.19 As the test environment

サーバーAの準備

1. 以下のコマンドを使用して、DockerでServer AにMinIOをデプロイしました。

# 専用のディレクトリを作成してその中に移動します。
mkdir minio && cd minio

# 設定ファイルを作成します。
mkdir config
touch config/minio

2. config/minioファイルに以下の情報を書き込みました。

MINIO_ROOT_USER=admin
MINIO_ROOT_PASSWORD=abc123abc
MINIO_VOLUMES="/mnt/data"

3. MinIOコンテナを作成しました。

sudo docker run -d --name minio \
  -p 9000:9000 \
  -p 9090:9090 \
  -v /mnt/minio-data:/mnt/data \
  -v ./config/minio:/etc/config.env \
  -e "MINIO_CONFIG_ENV_FILE=/etc/config.env" \
  --restart unless-stopped \
  minio/minio server --console-address ":9090"

4. MinIOのWebコンソールで、事前に3つのバケットを作成しました。

Bucket name Purpose
test-minio For testing MinIO
test-juicefs For testing JuiceFS
test-s3fs For testing s3fs-fuse

Server Bの準備

1. 10GBのテストサンプルファイルをダウンロードしました。

curl -LO https://data.cityofnewyork.us/api/views/t29m-gskq/rows.csv?accessType=DOWNLOAD

2. mcクライアントをインストールしました。

mcはMinIOプロジェクトによって開発されたコマンドラインファイルマネージャで、Linuxコマンドライン上でローカルおよびS3互換オブジェクトストレージへの読み書き操作を可能にします。mc cpコマンドはデータコピー中のリアルタイムの進捗とスピードの更新を提供し、様々なテストの観察を容易にします。

注: テストの公平性を保つため、3つのアプローチはいずれもmcを使用してファイル書き込みテストを行いました。

# mcをダウンロードします。
wget https://dl.min.io/client/mc/release/linux-amd64/mc

# mcのバージョンを確認します。
mc -v
mc version RELEASE.2023-09-20T15-22-31Z (commit-id=38b8665e9e8649f98e6162bdb5163172e6ecc187)
Runtime: go1.21.1 linux/amd64

# mcをインストールします。
sudo install mc /usr/bin

# MinIOのエイリアスを設定します。
mc alias set my http://172.16.254.18:9000 admin abc123abc

3. s3fs-fuseをダウンロードしました。

sudo apt install s3fs

# バージョンを確認します。
s3fs --version
Amazon Simple Storage Service File System V1.93 (commit:unknown) with OpenSSL

# オブジェクトストレージのアクセスキーを設定します。
echo admin:abc123abc >  ~/.passwd-s3fs

# キーファイルの権限を変更します。
chmod 600  ~/.passwd-s3fs

# マウント用のディレクトリを作成します。
mkdir mnt-s3fs

# オブジェクトストレージをマウントします。
s3fs test-s3fs:/ /root/mnt-s3fs -o url=http://172.16.254.18:9000 -o use_path_request_style

4. JuiceFSをインストールしました。

I used the official script to install the latest JuiceFS Community Edition.

# 一括インストールスクリプト
curl -sSL https://d.juicefs.com/install | sh -

# バージョンを確認します。
juicefs version
juicefs version 1.1.0+2023-09-04.08c4ae6

5. ファイルシステムを作成しました。JuiceFSは、使用前に作成する必要があるファイルシステムです。オブジェクトストレージに加え、メタデータエンジンとしてデータベースが必要です。様々なデータベースをサポートしています。ここでは、一般的に使用されるRedisをメタデータエンジンとして使用しました。

注意: RedisはServer Aにインストールし、172.16.254.18:6379でパスワードなしでアクセス可能です。インストールプロセスについてはここで省略し、Redisのドキュメントを参照してください。

# ファイルシステムを作成します。
juicefs format --storage minio \
--bucket http://172.16.254.18:9000/test-juicefs \
--access-key admin \
--secret-key abc123abc \
--trash-days 0 \
redis://172.16.254.18/1 \
myjfs

6. より一般的に使用されるPOSIXおよびS3 APIの方法でJuiceFSにアクセスし、それらのパフォーマンスをテストしました。

# マウント用のディレクトリを作成します。
mkdir ~/mnt-juicefs

# POSIXモードでファイルシステムをマウントします。
juicefs mount redis://172.16.254.18/1 /root/mnt-juicefs

# S3 APIの方法でファイルシステムにアクセスします。
export MINIO_ROOT_USER=admin
export MINIO_ROOT_PASSWORD=abc123abc
juicefs gateway redis://172.16.254.18/1 0.0.0.0:9000

# JuiceFS S3 APIにmcでエイリアスを設定します。
mc alias set juicefs http://172.16.254.18:9000 admin abc123abc

注意: JuiceFS GatewayはServer Aまたはインターネットにアクセス可能な他のサーバーにも展開できます。これはネットワークベースのS3 APIを公開しています。

テストと結果

ここに私のテストと結果の簡単なまとめがあります。

Test MinIO S3FS-FUSE JuiceFS
(FUSE)
JuiceFS
(S3 gateway)
Writing a 10 GB file 0m27.651s 3m6.380s 0m28.107s 0m28.091s
Overwriting small files with Pandas 0.83s 0.78s 0.46s 0.96s

テスト1: 10GBのファイルの書き込み

このテストは大きなファイルの書き込みパフォーマンスを評価するために設計されました。書き込みに要する時間が短いほど、パフォーマンスが良いことを示します。timeコマンドを使用して書き込み操作の期間を測定し、3つの指標を提供します。

  • real: コマンドの開始から終了までの実際の時間です。I/O操作完了待ち、プロセス切り替え待ち、リソース待ちなど、すべての待ち時間を含みます。
  • user: ユーザーモードで実行された時間で、ユーザーコードの実行に使用されたCPU時間を示します。通常、コマンドの計算負荷を表します。
  • sys: カーネルモードで実行された時間で、カーネルコードの実行に使用されたCPU時間を示します。通常、ファイルI/Oやプロセス管理などのシステムコールに関連する負荷を表します。

MinIO

I ran the following command to perform a copy test:

time mc cp ./2018_Yellow_Taxi_Trip_Data.csv  my/test-minio/

10 GBのファイルをMinIOに直接書き込む結果:

real    0m27.651s
user    0m10.767s
sys 0m5.439s

s3fs-fuse

I ran the following command to perform a copy test:

time mc cp ./2018_Yellow_Taxi_Trip_Data.csv /root/mnt-s3fs/

10 GBのファイルをs3fs-fuseに直接書き込む結果:

real 3m6.380s
user 0m0.012s
sys 0m5.459s

注意: s3fs-fuseの書き込み時間は3分6秒でしたが、MinIOの記事で説明されている書き込み失敗はありませんでした。

JuiceFS

I tested the performance of JuiceFS for large file writes using both the POSIX and S3 API methods:

# POSIX書き込みテスト
time mc cp ./2018_Yellow_Taxi_Trip_Data.csv /root/mnt-juicefs/

# S3 API書き込みテスト
time mc cp ./2018_Yellow_Taxi_Trip_Data.csv  juicefs/myjfs/

JuiceFS POSIXで10 GBのファイルを書き込む結果:

real    0m28.107s
user    0m0.292s
sys 0m6.930s

JuiceFS S3 APIで10 GBのファイルを書き込む結果:

real    0m28.091s
user    0m13.643s
sys 0m4.142s

大容量ファイル書き込み結果の概要

以下の図はテスト結果を示しています:

Large file write results (lower is better)

テスト結果から、MinIOへの直接書き込みとJuiceFSの両方が比較的同等のパフォーマンスを提供し、タスクを約30秒で完了しました。一方、s3fs-fuseは10 GBのファイルを書き込むのに3分以上かかり、前述の2つに比べて約6倍遅かった

大きなファイルを書き込む際、mcはMultipart APIを利用してファイルをチャンクに分割し、S3インターフェースにチャンクごとにアップロードします。一方、s3fs-fuseはPOSIXに対して単一スレッドで書き込むことができます。JuiceFSはまた、大きなファイルを自動的にチャンクに分割し、連続書き込み中にMinIOに対してそれらを同時に書き込み、直接MinIO書き込みと同等のパフォーマンスを確保します。S3FSは一方で、単一スレッドでキャッシュディスクに書き込み、その後ファイルをチャンクに分割してMinIOにアップロードするため、書き込み時間が長くなります。

10GBのファイルを書き込むのに30秒かかったとの計算に基づき、平均速度は333MB/sでした。これはクラウドサーバのSSDの帯域幅によって制限されていました。これらのテスト結果は、MinIOとJuiceFSがローカルSSDの帯域幅を最大限度に活用できることを示しており、サーバのクラウドディスクやネットワーク帯域幅の改善に伴いパフォーマンスが向上することが示唆されました。

テスト2: Pandasでの小さなファイルの上書き

このテストは、オブジェクトストレージシステムが小さなファイルの上書きシナリオでのパフォーマンスを評価しました。各ソフトウェアのテストスクリプトは若干異なります。すべてのスクリプトコードはこちらで見ることができます。

MinIO

I got the test script and ran the test:

# テストスクリプトを取得します。
curl -LO https://gist.githubusercontent.com/yuhr123/7acb7e6bb42fb0ff12f3ba64d2cdd7da/raw/30c748e20b56dec642a58f9cccd7ea6e213dab3c/pandas-minio.py

# テストを実行します。
python3 pandas-minio.py

結果は以下の通りでした。

Execution time: 0.83 seconds

s3fs-fuse

I got the test script and ran the test:

# テストスクリプトを取得します。
curl -LO gist.githubusercontent.com/yuhr123/7acb7e6bb42fb0ff12f3ba64d2cdd7da/raw/30c748e20b56dec642a58f9cccd7ea6e213dab3c/pandas-s3fs.py

# テストを実行します。
python3 pandas-s3fs.py

テスト結果は以下の通りでした。

Execution time: 0.78 seconds

JuiceFS POSIX

I got the test script and ran the test:

# テストスクリプトを取得します。
curl -LO gist.githubusercontent.com/yuhr123/7acb7e6bb42fb0ff12f3ba64d2cdd7da/raw/30c748e20b56dec642a58f9cccd7ea6e213dab3c/pandas-juicefs-posix.py

# テストを実行します。
python3 pandas-juicefs-posix.py

テスト結果は以下の通りでした:

Execution time: 0.43 seconds

JuiceFS S3 API

I got the test script and ran the test:

# テストスクリプトを取得します。
curl -LO https://gist.githubusercontent.com/yuhr123/7acb7e6bb42fb0ff12f3ba64d2cdd7da/raw/30c748e20b56dec642a58f9cccd7ea6e213dab3c/pandas-juicefs-s3api.py

# テストを実行します。
python3 pandas-juicefs-s3api.py

テスト結果は以下の通りでした:

Execution time: 0.86 seconds

Pandas Small File Overwritesの概要

次の図はテスト結果を示しています:

Pandas overwrite results (lower is better)

このテストでは、JuiceFS FUSE-POSIXが最も速い速度を示し、他のソリューションのほぼ2倍の速度でした。MinIO、s3fs-fuse、JuiceFS S3 Gatewayはほぼ同等の性能を示しました。小さなファイルの上書きの観点から、POSIXインターフェイスはより効率的であり、オブジェクトストレージインターフェイスよりも優れたパフォーマンスを提供しました。

問題と分析

問題1: S3FSはなぜ遅かったのか?

分析: テストデータから明らかなように、同じ10GBのファイルを書き込む際、S3FSは3分かかりましたが、MinIOとJuiceFSはどちらも約30秒でタスクを完了しました。この顕著な性能の違いは、主に異なる技術的実装によるものです。s3fs-fuseがファイルを書き込む際、まずファイルをローカルの一時ファイルに書き込み、その後オブジェクトストレージにチャンク単位でアップロードします。ローカルディスクのスペースが不足している場合、同期でアップロードします。そのため、データをローカルディスクとS3ストレージの間でコピーする必要があります。したがって、大きなファイルや大量のファイルは、性能の低下を引き起こします。

さらに、S3FSは基盤となるオブジェクトストレージのメタデータ管理機能に依存しています。大量のファイルを扱う際、メタデータを取得するためにオブジェクトストレージとの頻繁なやり取りは、性能に大きな影響を与えます。簡単に言えば、S3FSに書き込まれるファイルのサイズと総量が大きくなるほど、比例して性能上のオーバーヘッドも大きくなります。

問題2:なぜJuiceFSの方が速かったのか?

分析:テストでは、JuiceFSもS3FSもFUSEを使用して読み書きを行いました。JuiceFSはMinIOのようにディスク帯域幅を十分に活用しましたが、S3FSのような性能問題には直面しませんでした。

その答えはそれぞれの技術アーキテクチャにあります。ファイルの書き込み時にFUSE層を通じてデータが処理されるが、JuiceFSは高い並列処理、キャッシング、データのチャンク化技術を使用して、FUSE層と基盤のオブジェクトストレージとの間の通信オーバーヘッドを減らしています。これにより、JuiceFSは同時により多くのファイルの読み書きリクエストを処理でき、待ち時間や伝送ラグを減らすことができます。

さらに、JuiceFSは専用のデータベース(この場合、Redis)を使用してメタデータを管理しています。大量のファイルを扱う際、独立したメタデータエンジンは負荷を効果的に軽減し、ファイルの検索を高速化できます。

結論

上記のテストは、オブジェクトストレージを基盤とし、その上にPOSIXインターフェースを実装することが必ずしも性能の低下を引き起こすわけではないことを示しています。大きなファイルや小さなファイルを書き込む場合でも、JuiceFSはPOSIXアクセスによるオブジェクトストレージの性能低下なしに、直接のMinIO書き込みと比較して同等の性能を発揮します。さらに、Pandasテーブルの上書きに関しては、JuiceFS FUSE-POSIXの性能は一貫しており、MinIOをほぼ倍の性能で上回ります。

テスト結果は、s3fs-fuseのようなソフトウェアがS3 APIとPOSIXインターフェースの間の変換時に性能低下を経験する可能性があることを示しています。一時的なS3アクセス用の便利なツールとしては機能するかもしれませんが、安定した高いパフォーマンスを求める長期的な使用には、より適切なソリューションを選択するために慎重な研究と検証が必要です。

単純な非構造化ファイルの保存に関しては、MinIOやクラウドオブジェクトストレージを直接使用するのが良い選択です。しかし、AIモデルトレーニング、ビッグデータ分析、Kubernetesデータ永続化など、大規模データストレージと処理が含まれるシナリオ、および頻繁な読み書き操作が必要な場合、JuiceFSの独立したメタデータ管理、並行読み書き機能、キャッシングメカニズムは優れた性能を提供します。それは検討すべき高性能なファイルシステムソリューションです。

Source:
https://dzone.com/articles/is-posix-really-unsuitable-for-object-stores-a-dat