ストレージを購入する場合、通常はメディアに重点が置かれますが、アクセス方法を考慮することもさらに重要になる場合があります。インフラストラクチャを設計および調達するとき、特にクラウドネイティブのオブジェクト ストレージに移行するためにレガシー ストレージを残す場合は、ストレージ プロトコルを考慮する必要があります。ただし、オブジェクト ストレージは通信に S3 API に依存しますが、レガシー ワークロードは POSIX (Unix OS 間でアプリケーションを移植できるようにするために 1980 年代に開発された一連の標準を提供するポータブル オペレーティング システム インターフェイス) に依存します。おそらく、ほとんどの企業は、POSIX 上で実行するように開発されたアプリケーションを何十年も運用してきたでしょう。また、エンジニアは POSIX のパフォーマンスの低さにすでに気づいている可能性もあります。
そうは言っても、特定の形式または特定のソースからのみデータを取り込むことができるレガシー システムがある場合、選択肢は限られ、古いプロトコルを実装するかコードを書き直す以外に選択肢がない場合があります。たとえば、ファイル システムを使用したローカル ディスクからのみ取り込みができ、ネットワーク経由でアクセスされる RESTful API では取り込みができない場合、アプリケーションで使用できるようにするには、まずそのデータをディスク上で使用できるようにする必要があります。ただし、オブジェクト ストアをファイル システムとして使用すると、パフォーマンス、互換性、データの整合性、セキュリティの点で多くの重大な悪影響が生じます。
s3fs-fuseという小さなユーティリティを使用した実際のテストでこれを実証してみましょう。このユーティリティを使用すると、S3 バケットをローカル ファイルシステムとしてマウントできます。これは、S3 (Simple Storage Service) ファイル システム - FUSE (ユーザースペースのファイルシステム) の略です。これは、FUSE (Filesystem in Userspace) インターフェイスを利用して、ファイルシステムのようなインターフェイスを S3 に提供するオープンソース プロジェクトです。
s3fs-fuse
を使用して S3 バケットがマウントされると、バケットをローカル ファイルシステムであるかのように操作できるようになります。これは、バケット内のファイルに対して通常のファイル操作 (読み取り、書き込み、移動など) を使用できることを意味します。これは驚くほど便利に思えますし、アプリケーション開発が簡素化されると主張できます。ただし、オブジェクト ストレージとファイル システムには本質的に根本的な違いがあり、ファイル システムとしてマウントされた s3 バケットに影響します。
s3fs-fuse
ユーティリティから少し離れて、オブジェクト ストレージをファイルシステムとして扱うことが最適とは程遠い本当の理由について説明しましょう。この問題はs3fs-fuse
よりもはるかに大きく、ローカル ファイル システム API 呼び出しを S3 オブジェクト API 呼び出しに変換するファイル クライアントであるAmazon S3 用の Rust ベースのマウントポイントなどの他のユーティリティも含まれています。 1 つ目の理由は、これらのユーティリティはすべてファイル システムの操作に POSIX に依存しているためです。 POSIX は非効率的であり、ネットワーク上で非常に大きなファイルを処理することを意図したものではありませんでした。
POSIX ベースのシステムの速度は、システムに対する要求、特に同時要求が増加するにつれて低下します。大規模な組織がディープ ラーニング、AI、その他のデータ集約型のユースケースのために大量のデータを保存してアクセスする必要がある場合、POSIX にはこれらの要求を満たす能力やスケーラビリティがありません。オールフラッシュ アレイは POSIX をゲーム内で維持していますが、スケーラビリティと RESTful API (クラウドの特徴) はクリプトナイトのようなものです。
このため、オブジェクト ストア上で POSIX を実行することは最適とは言えません。その理由をいくつか見てみましょう。
パフォーマンス: POSIX FS インターフェイスは本質的に IOPS 中心です。これらは、おしゃべりで、高価で、拡張するのが困難です。 RESTful S3 API は、IOPS をスループットの問題に変換することでこの問題に対処します。スループットの拡張が容易かつ低コストになります。これが、オブジェクト ストレージが大規模でも高性能である理由です。 POSIX は HTTP RESTful インターフェイス上で実行するにはあまりにもおしゃべりなので、S3 上で POSIX を階層化することは拡張できません。
セマンティクス:オブジェクトの操作はアトミックで不変であるため、一貫性の正確性を保証する方法はありません。これは、クラッシュが発生した場合にコミットされていないデータが失われたり、共有マウントの場合に破損の問題が発生したりする可能性があることを意味します。
データの整合性: ファイルへの書き込みや変更は、コミットされるまで名前空間に表示されません。これは、共有マウント間での同時アクセスでは変更が反映されないことを意味します。共有アクセスには役に立ちません。
アクセス制御: POSIX 権限と ACL は原始的であり、S3 API の ID およびアクセス管理ポリシーの処理方法と互換性がありません。最上位の S3 API に POSIX アクセス管理を安全に実装することはできません。
また、POSIX には、オブジェクト レベルの暗号化、バージョン管理、不変性など、開発者が S3 で好む機能のほとんどが欠けています。これらは単に POSIX の世界に同等のものがなく、それらを翻訳できるものはありません。
これらの例は、問題とその影響を示しています。まず、約 10 GB で 112 行あるこのCSV ファイルを使用します。
注: s3fs-fuse
がすでにインストールされており、バケットの 1 つをオブジェクト ストレージからファイル システムにマウントしていることを前提とします。そうでない場合は、ここの指示に従ってください。
これらの例では、バケット名が test-bucket、ファイル名がtaxi-dataであると仮定します。csvは/home/user/ディレクトリにあり、 s3fs-fuse bucket
は/home/user/test-bucket/にマウントされています。
まず簡単なことを試し、mc コマンドを使用して CSV ファイルをテストバケットにコピーし、かかった時間を記録してみます。
time mc cp /home/user/taxi-data.csv minio/test-bucket/taxi-data.csv
これにはそれほど時間はかかりません。ファイルはバケットにコピーされるはずです。今度はs3fs-fuse
で同じことをやってみましょう
time cp /home/user/taxi-data.csv /home/user/test-bucket/taxi-data.csv
テストにかかった時間
real 1m36.056s user 0m14.507s sys 0m31.891s
私の場合、ファイルをバケットに部分的にしかコピーできず、操作は次のエラーで失敗しました。
cp: error writing '/home/user/test-bucket/taxi-data.csv': Input/output error cp: failed to close '/home/user/test-bucket/taxi-data.csv': Input/output error
何度か試した後、成功しました
real 5m3.661s user 0m0.053s sys 2m35.234s
ご覧のとおり、ユーティリティが実行する必要がある API 呼び出しの量と操作の一般的なオーバーヘッドにより、ユーティリティは不安定になり、ほとんどの操作は終了すらしません。
簡単なcp
例を示しましたが、説得力があるかどうかはわかりません。実を言うと、 time cp
は非常に初歩的だと思われるかもしれないからです。
そこで、より経験的な証拠が必要な方のために、これをテストするための Python スニペットを作成してみましょう。 s3fs-fuse
とpython s3fs
パッケージの両方を使用して簡単な Pandas の例を実行し、パフォーマンスへの影響を確認します。
import timeit import os import fsspec import s3fs import pandas as pd # Write a dummy CSV file to test-bucket df = pd.DataFrame({"column1": ["new_value1"], "column2": ["new_value2"]}) df.to_csv("s3://test-bucket/data/test-data.csv", index=False) def process_s3(): # add fsspec for pandas to use `s3://` path style and access S3 buckets directly fsspec.config.conf = { "s3": { "key": os.getenv("AWS_ACCESS_KEY_ID", "minioadmin"), "secret": os.getenv("AWS_SECRET_ACCESS_KEY", "minioadmin"), "client_kwargs": { "endpoint_url": os.getenv("S3_ENDPOINT", "https://play.min.io") } } } s3 = s3fs.S3FileSystem() for i in range(100): # Read the existing data print(i) df = pd.read_csv('s3://test-bucket/data/test-data.csv') # Append a new row new_df = pd.concat([df, pd.DataFrame([{"column1": f"value{i}", "column2": f"value{i}"}])], ignore_index=True) # Write the data back to the file new_df.to_csv('s3://test-bucket/data/test-data.csv', index=False) execution_time = timeit.timeit(process_s3, number=1) print(f"Execution time: {execution_time:.2f} seconds")
テストにかかった時間
Execution time: 8.54 seconds
次に、 s3fs-fuse
についても同じことを試してみましょう
import timeit import pandas as pd # Write a dummy CSV file to test-bucket df = pd.DataFrame({"column1": ["new_value1"], "column2": ["new_value2"]}) df.to_csv("s3://test-bucket/data/test-data.csv", index=False) def process_s3fs(): for i in range(100): # Read the existing data print(i) df = pd.read_csv('/home/user/test-bucket/data/test-data.csv') # Append a new row new_df = pd.concat([df, pd.DataFrame([{"column1": f"value{i}", "column2": f"value{i}"}])], ignore_index=True) # Write the data back to the file new_df.to_csv('/home/user/test-bucket/data/test-data.csv', index=False) execution_time = timeit.timeit(process_s3fs, number=1) print(f"Execution time: {execution_time:.2f} seconds")
テストにかかった時間
Execution time: 9.59 seconds
これらの例は、S3 ファイルへの定常的な読み取りと書き込みを示しています。これが複数のクライアントによって同時に実行されると想像してください。待ち時間は劇的に増加します。
ご覧のとおり、POSIX 変換を使用してオブジェクトをファイルとして扱うことと、直接 API を使用してオブジェクトを操作することには昼夜の差があります。セキュリティ、パフォーマンス、データの整合性、互換性に関しては、比類のないものです。 MinIO には、ほとんどすべての一般的なプログラミング言語と統合するためのSDKがあり、Kubernetes、ベアメタル Linux、Docker コンテナなど、ほぼすべてのプラットフォームで実行できます。
MinIO は、保存時および転送中の暗号化を使用してオブジェクトを保護し、PBAC と組み合わせてアクセスと消去コーディングを制御してデータの整合性を保護します。 MinIO は基盤となるハードウェアを活用して ( 「MinIO の展開に最適なハードウェアの選択」を参照)、可能な限り最大のパフォーマンスを実現するため、MinIO を実行する場所に関係なく、可能な限り最高のパフォーマンスを実現できます。わずか 32 ノードの既製 NVMe SSD を使用して、MinIO のベンチマークを GET で 325 GiB/s (349 GB/s)、PUT で 165 GiB/s (177 GB/s) で測定しました。
MinIO とアプリケーションの間にファイル システム ユーティリティを配置する必要はまったくありません。レガシー アプリが享受できるメリットは、POSIX の苦痛によって相殺されてしまいます。
アプリケーションでの POSIX 翻訳の使用についてご質問がある場合は、必ずSlackでご連絡ください。
ここでも公開されています。