2 ポイント 投稿者 GN⁺ 2024-03-11 | 1件のコメント | WhatsAppで共有
  • Amazon S3は2006年に登場した初期のクラウド技術で、ファイル保存には強いが、UnixファイルAPIをそのまま置き換えるファイルシステムではない
  • UnixファイルAPIはopenreadwriteseekcloseのような狭いインターフェースの背後に、バッファリング、ページキャッシュ、権限、IOスケジューリングを隠した深いモジュールに近い
  • S3はGetObjectPutObject中心で単純に見えるが、Rangeによる部分読み取りしかできず、部分上書きはサポートしない
  • Postgres、SQLite、MySQL、MongoDB、Elasticsearchのようなデータベースはページ単位の上書きに依存するため、SQLiteやDuckDBのファイルをそのままS3に置く方式は、小さなデータセットを除けば適合しにくい
  • 高い読み書き帯域幅と低い運用負荷はS3の強みだが、rename/moveの不在、遅い一覧取得、XML専用API、ローカルテスト環境の不在といった制約もあわせて考慮する必要がある

S3はファイルを保存するが、ファイルシステムではない

  • S3は2006年に登場した初期のクラウド技術であり、当時流行していた表現に従って「object store」と呼ばれていた
  • 実際にはファイル保存先として広く使われているが、これを「Amazon Cloud Filesystem」のように理解すると一部しか当たっていない
  • ファイル保存は得意だが、既存のファイルシステムの動作や期待をそのまま代替できるわけではない

UnixファイルAPIと深いモジュール

  • UnixファイルAPIの中核は次の5つの呼び出しに要約できる
    • open(filepath): ファイルを開く
    • file.read(size=100): 現在位置から読み取り、位置を前へ進める
    • file.write("hello, world"): 現在位置に書き込み、位置を前へ進める
    • file.seek(94): 位置を特定のバイトへ移動する
    • file.close(): ファイルを閉じる
  • これらの呼び出しは、実際のシステムコール全体の中でも中核にあたり、ファイルの読み書きに必要な最小機能に近い
  • 狭いインターフェースの背後で多くの処理が行われるため、UnixファイルAPIは**深いモジュール(deep module)**と見なせる
    • バッファリングとページキャッシュ
    • 断片化の処理
    • 権限管理
    • IOスケジューリング
    • SDカードのwear-levellingのような機能も、利用者が直接気にしなくても恩恵を受けられる

浅いモジュールとYAML、ORM

  • 浅いモジュールは、処理してくれる機能に対してAPI表面が相対的に大きい
  • 今日では浅いモジュールを見分ける手がかりの一つとして、インターフェースがYAMLである場合がある
    • YAMLはマークアップ言語のように見えるが、実際にはほとんどどんな意味論でも載せられる再利用可能な構文のように使われる
    • DevOps領域では、YAMLが「プログラミング言語」のように動作することが多い
    • YAMLミニ言語が反復構造を提供すると、チューリング完全である可能性がある
  • 浅いモジュールが常に悪いわけではない
    • SQL ORMは本質的に漏れる抽象化であり、SQLを理解せずに使うのは難しい
    • 場合によっては浅いモジュールが取りうる最善の形であることもある
  • 条件が同じなら、より深いモジュールのほうが良い

S3 APIは単純だが、ファイルAPIとは異なる

  • UnixファイルAPIは1970年代初頭に定着し、互換性のためインターフェースは維持されたまま、内部実装は何度も変わってきた
  • Amazon S3はUnixファイルシステムAPIを再実装していない
  • S3の基本操作は、UnixファイルAPIと一部しか対応しない
    • GetObject(Bucket, Key, Range=None): オブジェクト全体または一部を読む
    • PutObject(Bucket, Key): オブジェクト全体を書き込む
  • バケットという追加概念はあるが、機能に対するインターフェース比率だけを見るなら、S3はUnixファイルAPIより単純だと言える
  • 決定的な違いは部分上書きがないことだ
    • GetObjectRange引数でオブジェクトの一部を読むことはできる
    • オブジェクトの一部だけを上書きすることはできない
    • 上書きはファイル全体単位で行う必要がある
  • この違いのため、S3は既存のファイル利用ケースの一部にしかうまく適合しない

データベースはS3へそのまま移植しにくい

  • さまざまなデータベースは、データをファイルシステム上のファイルに保存している
    • Postgresはテーブルごとに2〜3個のファイルと複数の管理用ファイルを維持する
    • SQLiteはすべてのデータを単一ファイルに保存することで知られている
    • MySQL、MongoDB、Elasticsearchもデータをファイルに保存する
  • 問題は、データベースが概してページ単位の部分上書きに依存している点にある
    • データは通常、4KBや8KBのようなページで保存される
    • heapファイルの中には数千のページが存在しうる
    • 必要なデータ保存のためにページが部分的に上書きされる
  • SQLiteデータベースをS3に置くと、書き込みのたびにデータベースファイル全体を書き直す必要がある
  • S3は大きな書き込みを高速に処理できるが、最小のデータセットを除けば、毎回ファイル全体を上書きする戦略は負担しきれない
  • 毎回データベースファイルを書き直すと、データベース実装者が作り込んだトランザクション整合性も活かしにくくなる
  • S3では最後の書き込みが勝つ

S3が得意なことと苦手なこと

  • S3の強みは、読み書きの帯域幅が非常に高いことだ
    • オンラインでは、S3に毎秒10GB超を書いたり読んだりした事例を見つけるのは難しくない
    • S3への書き込み作業で金融顧客のオフィスネットワークを飽和させた経験もある
  • 部分上書きがないこと以外にも、ファイルシステムとは異なる制約がある
  • S3にはrenameやmove操作がない
    • 名前変更はCopyObjectの後にDeleteObjectで処理される
    • CopyObjectはファイルサイズに比例する線形時間がかかる
    • ファイルを誤った場所に大量に書いたあとで戻す作業は非常に遅い
  • ファイル一覧の取得は遅い
    • 読み書きの帯域幅は非常に高いが、保存された項目を列挙する作業ははるかに遅い
    • 遅いローカルファイルシステムよりも遅いことがある
  • その代わり、ファイルシステムより運用負荷は低い
    • バケットとキー名を指定するだけで、残りはクラウドが処理する
    • バックアップ、オフサイト複製、プロビジョニングのような反復作業の負担を減らせる
    • プロビジョニングは容量だけでなくIO作業にも関係する

組織間インターフェースでは深いモジュールがより重要

  • S3が最初の人気クラウドAPIだった点は、深いAPIの利点とつながっている
  • 深いAPIは単一システム内部のモジュール間の複雑さを隠すのに有用であり、2社間の相互作用のようにコストの高い関係ではさらに重要になる
  • 企業間のコンピュータシステム接続は伝統的にintegrationと呼ばれ、苦痛の代名詞のように扱われてきた
  • SAPのような大規模エンタープライズソフトウェアは深いモジュールではない
    • 組織のほぼ全体がSAPを理解しなければならない
    • 既存の業務方式と継続的にすり合わせる必要がある
    • SAP統合プロジェクトは高価で巨大であり、失敗例も繰り返されてきた
  • S3の内部複雑性がSAP導入よりずっと小さいわけではない
    • AmazonはS3を「Simple Storage Service」と呼んだが、実際のS3の複雑性は大きい
    • キューイング理論、IO競合、シャーディング、ファイルシステムが処理する多くの問題を含む
  • S3の「simple」は、実際の単純さというより深いインターフェースに近い

S3に適した例外と残る制約

  • S3がユースケースに対して高価であるという問題を排除するものではない
  • 深いモジュールと浅いモジュールの概念は、John OusterhoutのA Philosophy of Software Designに由来する
  • S3 APIをストレージ層として使う前提で最初から設計されたデータベースもある
    • Snowflakeはその一例だ
    • ただし透明な移植ではなく、初期設計の判断が必要になる
    • Snowflakeは少なくとも2016年までには、この判断を非常に早い段階で下した事例だ
  • S3で困難に直面するのはデータベースだけではない
    • 多くのファイル形式は安価なseekを前提としている
    • Zipファイルは、S3よりディスク上のほうが性能が良い代表例だ

S3で惜しい点

  • S3 APIはXML専用
    • JSONは2006年にも存在していたが、当時はXMLが優勢だった
    • AmazonがSOAPからRESTへ移行する際にJSON版を出さなかったのは惜しい
  • AmazonはXSD schemaの維持もやめてしまった
    • XML APIの中核的な利点の一つはスキーマだが、現在の標準文書はWebサイトになっている
  • Amazonはローカルテスト環境を提供していない
    • Pythonでは、真面目なテストのためにmotoライブラリを使うことがある
    • motoは商用サービスのテストツールであるにもかかわらず、ボランティアによって保守されている
  • Amazon S3はchecksumをサポートしているが、デフォルトでは有効になっていない
    • Amazonは耐久性についてさまざまな主張をしている
    • 実際に問題があったという話は聞いたことがないが、そうした主張が検証された事例も見たことがない
  • 過去のS3にはeventual consistencyの落とし穴があった
    • ファイルを読み、上書きし、再び読むと、まだ変更前の内容が見えることがあった
    • 短時間だけ時々発生し、混乱を招いた
    • 他のS3実装はこの性質を再現しなかったし、Amazonも数年前にstrong read-after-write consistencyへ修正した

1件のコメント

 
GN⁺ 2024-03-11
Hacker News のコメント
  • S3 の耐久性は誇張のように見えても信頼できるもので、従来のファイルシステムとは比較しにくいと思う
    ソフトウェアだけでなく物理インフラや安全文化まで含めた違いであり、AWS の アベイラビリティゾーン分離は他のクラウドより優れていると感じる
    S3 で働いていたとき、GCP Blob Storage との価格比較をよくされたが、Google は同じ建物や同じ建物内の別の部屋にデータを置けるため、AWS 式の分離とは公平な比較ではなかった
    組織全体がデータ完全性に極度にこだわり、あらゆるものにチェックサムを付け、自然災害のような大きな事象にも備えていた
    S3 の規模では、ガンマ線がハードディスクのプラッタに当たって起きるランダムなビット反転のような ビットロットも検出でき、ディスクメーカーや生産時期ごとの故障率まで測定して、特定ロットが壊れてもデータ損失の可能性を下げていた
    重要なデータは他には保存しないと言えるほどで、S3 のバッチシステムを自分で作った

    • 他のストレージ企業での経験が気になる
      この説明は、Cinnabon が自分たちで生地を作っていると褒めているように聞こえるが、挙げられていることはストレージ会社なら普通にやることだ
      あらゆるものにチェックサムを付けるのは多くのファイルシステムの基本機能だし、自宅のコンピュータでもビットロットを検出して通知を受けられるなら、大手ストレージ企業がやるのは当然だ
      ディスクメーカー別の故障率追跡も一般的で、ストレージ会社はレポートを公開することもあるし、6人規模の IT 組織でもスプレッドシートで管理していた
      AWS の外にも、AWS ができるずっと前から、ストレージに賢い人たちが大勢携わってきた
    • AWS のアベイラビリティゾーン分離がすべての事業者より優れているわけではない
      rsync.net の地理冗長アカウントは、たとえば Fremont の主ストレージと Denver の副ストレージのように、異なる州や国に存在する
      S3 が規模ゆえにビットロットを検出できるというのも正しくなく、個人サーバーで ZFS を動かしても小規模でビットロットをきちんと検出できる
      [1] he.net 本社
    • データにチェックサムを付けるのは偏執的だからというより、Reed-Solomon アルゴリズムを走らせるために、どのブロックが使えないかを知る必要があるので自然に必要になることだ
      こうした破損イベントが十分に多ければ、個別のデータブロックを別のマシンへ移してシステムを「修復」するためのシグナルとしても使えそうだ
      全体として、挙げられていることはストレージシステムではかなり典型的で、S3 だけの特徴ではない
    • Google が同じ建物にデータを保存するというのは事実ではなさそうだ
      Google Cloud Storage のドキュメントによると、データは複数のゾーンに複製され、それぞれのゾーンは別々のクラスタにマッピングされる
      https://cloud.google.com/compute/docs/regions-zones/zone-vir...
    • 「信じろ」よりも テスト結果を信じたい
      S3 の耐久性、完全性、一貫性を Jepsen と同じくらい厳格に検証した中立的な第三者がいるのか気になる
      誰かが S3 互換クラウドストレージを厳密に比較すれば、恐ろしく大きな問題が明らかになるかもしれないし、すでにそうした比較があるのかもしれない
  • S3 で本当に有用なのは読み書き速度よりも 一覧取得だと思う
    バージョンなしのバケットや削除マーカーのないバケットでは、特定プレフィックスの一覧取得が事実上定数時間のように動作し、1000億個のオブジェクトがあるバケットでも、任意の文字列の後に来るアルファベット順のキー1000個を要求できる
    / を区切り文字として使うのはデフォルトにすぎず、任意の文字を使って共通プレフィックスの集合を得られる。ディレクトリは実際には存在せず、必要なときに作られたように見えるだけだ
    この特性のおかげで、性能を心配せずに必要な識別子を基準としてデータを複数の方法で分割できる
    もし一覧取得が単に遅く、ファイルプレフィックスベースの検索もできず、キー数に比例して遅くなる従来の Unix ファイルシステムのようなものだったなら、S3 はまったく有用ではなかったはずだ

    • あまり説得力はない
      プレフィックス前後のキーを取り出す能力は、1970年代からある データベースインデックスの基本なので、特に印象的ではない
      ユースケースは違うかもしれないが、バケットの一覧取得が遅くて邪魔になることは多かったし、バケットが少し大きくなるだけで、キーを列挙する時間が読み取り時間より長くなる
      記憶では一覧取得は 1Mbps 未満程度だったが、今すぐテストできる大きなバケットはない
    • フラットな辞書順キー階層と、ディレクトリで入れ子になったファイルシステム階層の違いは、例を見るとはっきりする
      dir1/a/000000 から dir1/a/999999 まであり、dir1/b があるとき、本物の階層型ファイルシステムで ls dir1/"a""b" の2項目だけを走査して返せばよい
      一方、区切り文字処理のないフラットな文字列インデックスのキー値ストアでは、"b" に到達する前に "a/00000" から "a/999999" まで100万個のディレクトリエントリを通過しなければならない
      そのため、単純なフラット階層では、1つのディレクトリ内容の列挙が本物のファイルシステムの O(直接の子) ではなく O(すべての再帰的な子) になり、はるかに遅くなる
      ただし一覧取得アルゴリズムに / のような 区切り文字を教えれば、辞書順プレフィックスツリーが次の / でサブツリーを効率よく飛ばせる
      Amazon S3 のドキュメントも、CommonPrefixes フィールドでより深い階層に入れ子になった何百万ものキーをスキップして要約すると明記している
      https://docs.aws.amazon.com/AmazonS3/latest/userguide/using-...
      実装が本当に走査を節約しているのか、それとも走査したあとに結果だけ減らしているのかは試していないが、節約していてほしい
    • 1993年の XFS 以降、HPFS の影響を受けた優れた UNIX ファイルシステムは、ディレクトリを何らかの形の B-tree として実装してきた
      そのため項目数に比例して遅くならず、ファイルプレフィックスベースの一覧取得も非常に速い
    • S3 利用の99%は、すでに分かっているキーでオブジェクトを取得することだと思う
      プレフィックス一覧取得を中核機能と見るのは奇妙に感じる
    • ここでいう「定数時間」の定義が同じかどうか分からない
      1回のネットワーク呼び出しで1000個のキーを受け取れるからといって、バックエンドの複雑性については何も保証しない
  • 最近、S3 のアセット管理スクリプトを触っていて、一覧取得の速度に驚いた
    同僚がファイル一覧のキャッシュが必要だと言って、事前に埋めたキャッシュを送ってくれた。最初は本当に必要なはずがないと思ったが、自分で確認してみると違っていた
    個別アセット用のルートディレクトリが約 10 万個あり、それぞれに 5〜6 個のディレクトリと少数のファイルがあり、全体のファイル数はおそらく 100 万個未満で、深さは最大 3 階層程度
    これらのファイルを再帰的に列挙するのに、文字どおり 15 分かかった
    Stack Overflow や ChatGPT の速度改善の提案をあれこれ試したが、意味のある結果はなく、なぜこんなに遅いのか理解できない
    Amazon がなぜこれを直していないのか分からないし、外から見る限りでは個別のバケットに B-tree をいくつか付ければ終わりのように見える
    難しい問題なら、その理由は興味深そうなので聞いてみたい

    • S3 は根本的にキー・バリューストアである
      オブジェクトを「ディレクトリ」のように見られるのはプレフィックスフィルタにすぎず、ファイルシステムではなく、ディレクトリという概念もない
    • 「再帰的に」という表現と、「ディレクトリ」「階層」について長く説明している部分が気になる
      S3 で最速にオブジェクトを列挙する方法には再帰はまったく不要で、単にプレフィックス配下の全オブジェクトを列挙すればよい
      パス区切り文字を使って S3 キーをフォルダ構造のように見せかけ、「フォルダごと」に回ると、ずっと遅くなる
      ListObjectsV2 を呼ぶときに delimiter を渡してはいけない。区切り文字機能を使わなければ、「ディレクトリ」や「階層」は性能に影響しない
      目標の総時間に合わせるには、1 つの一覧処理を複数のプレフィックスに対する並列一覧取得に分割すればよい
    • この問題の面白い帰結は、S3 バケットの削除が簡単ではないという点である
      オブジェクトが入っているバケットは削除できず、S3 に全オブジェクトを削除してほしいと一度に指示することもできない
      各オブジェクトに対して個別の削除 API リクエストを送る必要があり、そのためにはオブジェクトを 1000 個ずつ列挙するリクエストも送らなければならない。この一覧呼び出しには時間もかかり、費用もかかる
      状況の整理はこの記事がうまい: https://cloudcasts.io/article/deleting-an-s3-bucket-costs-mo...
      S3 バケットを早く片付ける最速の方法は、結局そのバケットが属している AWS アカウントを削除することだ
    • 理由はもっと平凡かもしれない
      1 回のリクエストで 1 万個のオブジェクトを列挙でき、次の 1 万個を得るには前のリクエスト結果が必要なので、すべて直列になる
      100 万ファイルを列挙するには連続リクエストが 100 回必要で、往復時間が 50ms だけでも往復だけで 5 秒かかり、フラットな反復で一覧自体を作るコストは別にかかる
      1 万項目の一覧取得コストは書き込みコストに近いが、これ自体がかなり遅い部類で、各一覧取得が強い整合性のスナップショットである可能性もあり、さらにコストが乗る
      B-tree はディレクトリ走査をする場合でなければあまり役に立たなさそうだし、その場合でもボトルネックはネットワーク処理と外部に公開された API である可能性が高い
      結局、ファイル一覧取得はそれほど重要なユースケースではなく、通常はオブジェクトライフサイクルのような機能で S3 に望む処理を任せ、内部のファイルシステム階層で効率的に処理させる
    • S3 バケットの中にディレクトリがあると考えるのは、よいモデルではない
      すべてオブジェクトであり、Web インターフェイスがスラッシュで分けられたプレフィックスを見やすく表現しているだけ
      各オブジェクトにはキーがあり、そのキーにスラッシュを含めることができるので、気楽に各区間をディレクトリだと考えることはできる
      だが、通常ディレクトリに対して行っていた操作を試みると、その幻想は崩れる
  • S3 を作った人たちは、これがファイルシステムではないことを分かっていたし、オブジェクトストレージという名称は、記事で指摘されている違いを説明するための表現だったのだと思う
    「オブジェクトが人気だった」というのは、実行コードとローカル状態を束ねるソフトウェア構成要素としてのオブジェクトを指すが、S3 初期の例は「ライブオブジェクトをシリアライズして別プロセスでデシリアライズする」といったものではなかった
    例はすべて Web サイトの静的アセットのようなもので、当時のデータベース方面でも「binary large object」または「blob」という言葉でオブジェクトという意味が使われていた
    S3 はデータベースに入れるには扱いにくいものを保存する場所に近く、初期設計時のローンチユースケースは、コンテンツのインデックスがどこか別の場所にあると仮定していたため、一覧取得が遅いこともまさにその性質を説明している

    • 筆者は「オブジェクトストレージ」がオブジェクト指向プログラミングとは無関係なストレージシステム用語であることを知らないようだ
      https://en.wikipedia.org/wiki/Object_storage
    • 筆者がオブジェクト指向プログラミングとオブジェクトストレージを混同しているようで気になる
      GCP の説明によれば、オブジェクトストレージは非構造化データをオブジェクト単位に分け、構造的にフラットなデータ環境に保存するアーキテクチャである
      https://cloud.google.com/learn/what-is-object-storage
      つまり、非構造化、フラットな構成、項目全体単位の操作である読み取りと書き込みが要点である
  • S3はファイルでもなく、ましてやファイルシステムでもない
    ファイル抽象化に期待されるのは変更可能性であり、ファイルの一部を編集し、伸ばし、縮め、任意のオフセットで読み書きできること
    ファイルをつかんだ後に、再びルートや上位概念へ戻る必要がないはずだが、S3は変更可能な一覧の上に変更不可能なオブジェクトを提供しているだけで、変更するにはコピーして再アップロードしなければならない
    本来のファイル抽象化は、ディスク上のセクタを見つけてクライアントに連続したバッファのように見せるものであり、S3は別の問題を解いている
    多くの人が、UNIXの「すべてはファイルである」という優れたアイデアを、すべてが連続した仮想バッファのように見えるべきだという意味に誤解している
    本当の核心は、ファイルであれ、システムがプロセスに見せたい別のオブジェクトであれ、基本となるリーフノードがあり、ディレクトリを含むすべてのものをディレクトリに列挙でき、再帰的なツリーが存在するという点にある
    ファイルシステムを成り立たせるのは、特定のリーフノードの型ではなくディレクトリである
    ソケットやフレームバッファのような新しいリーフ型を追加するのはほとんど些細なことで、このアイデアを損なわないが、リストのような別種のコンテナを追加するとファイルシステム構造が複雑になり、概念的な一貫性が崩れる
    S3はこうしたことをしないが、それで構わない
    データベースに合わないものを置いておき、見ていない間にビットロットが起きないことを願うだけでよい
    S3をファイルシステムのようにしたがる欲求は、S3が得意とすることを顧客が誤解し、プロダクトマネジメントがその誤解を止めずに受け入れたことから来ていると思う

    • S3はファイルシステムではない、という点には同意する
      より適切なたとえはブロックストレージデバイスで、ただしブロックサイズが任意でキーを付けられる、非常に奇妙なブロックデバイスに近い
      ファイルシステムはブロックストレージデバイスの上に載る抽象化なので、「S3ファイルシステム」もS3を基盤となるブロックストレージのように置き、その上に載る抽象化であるべきだ
    • 読み取り専用ファイルシステムは、この定義とどう整合するのか気になる
  • ファイルシステムはブロックデバイスの上に作られた抽象化である
    ブロックデバイスは巨大なバイト配列を提供し、たとえば「273041の位置にこの300バイトを書け」のように、ブロック単位の読み書きを可能にする
    ブロックデバイス自体も実際のハードウェアの上に作られた抽象化なので、「この300バイトを書け」という命令は、実際には「2番プラッタのヘッドを6番位置へ動かせ」のような動作につながる
    S3は生のストレージの上に作られた別の抽象化にすぎず、厳密にフラットなキー・オブジェクトストアである
    ファイルシステム機能が必要なら、アプリで実装するかファイルシステムを使えばよい
    追記だけが必要なら、データベースで追記チェーンを追跡し、チャンクはS3に保存すればよく、合わなければ別のものを使えばよい
    コピーが必要なら、データベースで同じオブジェクトへの新しい参照を作ればよく、合わなければ別のものを使えばよい
    S3は多くの人にうまく合っているので、別物に作り替えようとするべきではない
    すでに確立された分野用語の意味を変えようとするのもやめるべきであり、ファイルシステムは教科書で説明されている概念で、S3は自分をファイルシステムだと主張したことはない
    オペレーティングシステム設計も少し学ぶと、本当に役に立つし面白い

  • Apache Arrowのobject_storeApache OpenDAL APIを比較する議論がhttps://github.com/apache/arrow-rs/issues/3888であった
    Apache OpenDALは、S3や複数のクラウドストレージを含むさまざまなバックエンドの上に、ファイルシステムのようなAPIを提供するライブラリである
    GreptimeDBやDatabendのような一部のデータベースシステムは、クラウドストレージ上のデータへアクセスするための、より優れたS3 SDKのようにOpenDALを使っている
    S3上にファイルシステムのようなインターフェースを管理する別の解としてAlluxioやJuiceFSもあるが、Apache OpenDALとは異なり、別途デプロイと専用の内部メタデータサービスが必要になる

    • TrinoDB向けのローカルキャッシュ層として、AlluxioをOpenDALで置き換えられるかはよく分からない
  • S3について語るなら、Backblaze B2にも触れる価値がある
    価格がS3より3倍安いのでとても気に入っているし、Backblazeの関係者ではない

    • Backblaze B2は安いが、本番環境で使うならコストに含めるべきものがある
      毎週PST 11:30〜13:30の2時間のメンテナンス枠があり、通常はダウンタイムはないが、ときどき米国の業務時間の真っただ中に全体障害が起きることもある
      エラー率が利用不能な水準まで上がるとサポートチケットを入れる必要があり、ここ数年でおよそ年1回ほど経験した
      サポートは自分たち側のエラーログや可視性がないかのように大量の質問をするだけで、問題をきちんと調べてくれない
      アップロード成功と応答したのに、実際にはB2システム上に0バイトで保存される偽の成功もあり、成功コードであっても必ずアップロードを検証しなければならない
      Log4j2 CVEのような深刻度の高い脆弱性が出ると、10時間停止のような長い障害も起こり得る
      価格は最高だが、より成熟したクラウドストレージサービスと直接比較できる製品ではない
    • 代替サービスでは、データがその会社を信頼できる分だけしか安全でない、という点が常に核心である
      ただし、二重の外部バックアップである程度は補えると思う
    • B2は良かったが、IPv4アドレス費用まで払って使うほどではなかった
      マルチクラウドソリューションだと宣伝しながら、NATゲートウェイとIPv4料金がどこにでも付いて回る状況では、導入可能性を事実上なくしてしまうのがばかげている
      読み取りが多く書き込みが少ない利用量なので、B2の帯域料金を払っても節約できたが、NAT64ゲートウェイを経由したり、B2にアクセスするために時間単位の料金を払わなければならないなら、そうはならない
  • 良い記事で、rclone mountでクラウドストレージをFUSEとしてマウントする旅を始める前に読んでいたら役に立ったはずです
    何度も反復された結果、rcloneにはS3やGoogle Cloud Storage、Azure Blob、OpenStack Swift、Oracle Object StorageのようなストレージをPOSIX風のファイルシステム層に合わせるVFS層ができており、実際のrclone mountコードはその上の薄い層です
    VFS層には互換性レベルがいくつかあり、offではディレクトリのキャッシュだけを行います
    このモードでは記事で述べられているように、同じファイルを同時に読み書きできず、ファイルの途中に書き込めず、ファイルはシーケンシャルにしか書けません
    驚くことに、このような制約の下でもかなり多くのものがうまく動きます
    次の段階であるwritesは、同じファイルの同時読み書き、ファイル途中への書き込みなど、アプリが求めるPOSIX機能の大半をサポートしますが、ファイルのローカルコピーを作り、閉じられるときに非同期でアップロードするコストがかかります
    VFSキャッシュモードのドキュメントは、記事の制約をよく反映しています: https://rclone.org/commands/rclone_mount/#vfs-file-caching
    基本的にS3には本物のディレクトリもないため、ファイルのないディレクトリを持つことはできず、ディレクトリに更新時刻のような有効なメタデータもありません
    /で終わる0バイトファイルであるディレクトリマーカーを作ることはでき、rcloneを含む多くのツールがこれをサポートしています
    空ディレクトリがなくても通常は大きな問題にはなりません。VFS層がそれを擬似的に作ってくれますし、ほとんどのアプリはすぐにその中へ何かを書き込むからです
    結局、S3のように見えるものをPOSIXファイルシステムのように見せる作業はかなり大掛かりで、開いているファイルのリネームのような動作や厄介な例外状況の裏には多くのごまかしがあります
    rcloneの低レベルなmove/sync/copyコマンドはそのような処理をせず、S3 APIをほぼそのまま使います
    S3 APIで1つ変えられるなら、一覧取得時にメタデータも読めるオプションが欲しいです
    rcloneはファイルの更新時刻をオブジェクトメタデータに保存しますが、それを一括で読む方法がないため、オブジェクトごとにHEADする必要があります
    あるいはアップロード時にオブジェクトのLast-Modifiedを設定できてもよいと思います

    • メタデータをキー名そのものに保存する形で回避できるのではないかと思います
      キー長の制限は1024なので保存できるメタデータ量は限られますが、ファイルパスを考慮してもかなり余裕があります
      正規化されたパスでは無効な//のような区切りを使って、/path/to/file.txt//mtime=1710066090のように置けます
      それでもプレフィックスで「ディレクトリ」を取得し、//をプレフィックスのように使って直接ファイルを取得できます
      ただしこの形式は、他のソフトウェアとの互換性を大きく損ねそうです
    • 一覧取得にメタデータを含めるオプションがあるとよい、という点には同意します
      MinIOでは、適切な権限がある場合に一覧取得へメタデータとタグを含めるmetadata=trueという「秘密」のパラメータを追加しました
      拡張なので安定して使えるものではありませんが、rcloneは常に試してみて、可能なら使えます
      /で終わる0バイトファイルも可能ですが、一覧取得の共有プレフィックス自体をディレクトリと見なすこともできます
      そうすると、ディレクトリには状態がなく、その中にオブジェクトがなければ存在できないという長所と短所が生じます
      アップロード時にLast-Modifiedを設定できればクライアント側の制約は減りますが、サーバー時刻が基準になる利点もあります
      クライアント側のレプリケーションやミラーリングでも同じ制約に対処する必要があります
      個人的に一番大きな不満は、単一オブジェクトのバージョン情報を返すHeadObjectVersionsがないことです
      ListObjectVersionsは、与えられたプレフィックスが実際のプレフィックスなのかオブジェクトキーなのか分からないため、常にクラスタ全体の操作にならざるを得ません
      AWSは最近GetObjectAttributesを追加しましたが、そこにうまく収まりそうだったバージョン情報は入りませんでした
  • S3の「Simple」は「深くない」という意味ではなく、要件を達成するために必要な部品が最も少ないという意味です
    分散型、集中型、複製型、高可用性、高耐久性、高帯域幅、低遅延、強い一貫性、同期式、スケーラブルなオブジェクトストレージにHTTP REST APIまで必要なら、S3より単純に作るのは難しいと思います
    AWS S3には長年にわたり多くの機能が追加されてきましたが、基本動作はそのまま保たれています

    • 記事で使われている用語では、「必要最小限の部品」こそが深いという意味です
      Ousterhoutの『A Philosophy of Software Design』の基準では、単純であるとは複雑でないという意味であり、Rich Hickeyの「Simple Made Easy」も同じ文脈です
      一方で「深い」とは、小さなインターフェースで内部的に複雑な多くの機能を提供するという意味なので、S3には「単純だ」よりもこの表現の方がよく合います
      S3に大したものがないという意味での単純さとは違います
      https://www.infoq.com/presentations/Simple-Made-Easy/
    • 記事の表現に従えば、単純さはほとんど深さと狭いインターフェースを含意しているとも見なせます