インフラ・DevOps
なぜBlacksmithに参加して再びストレージに取り組むことにしたのか
Why I joined Blacksmith to work on storage again (blacksmith.sh)
要約
著者は、Blacksmithで継続的インテグレーション(CI)におけるストレージの問題に取り組むために参加しました。CIワークロードは、大量の短命な仮想マシンを迅速に起動・破棄し、それぞれにデータ(ソース、依存関係、キャッシュなど)を供給する必要があり、従来のストレージソリューションでは対応が難しい、高スループット、高チャーン、低レイテンシーという特殊な要件を持っています。Blacksmithは、このユニークなワークロードに対応するため、ストレージ基盤そのものの再考を目指しています。
全文翻訳
Blacksmith Sandboxes 近日公開
メニュー
閉じる
ログイン
[ 2026年7月24日 ]
なぜBlacksmithに参加して再びストレージに取り組むことにしたのか
既製のストレージが限界を迎える場所
Piotr Bejda
テクニカルスタッフメンバー
TL;DR
始めましょう!
無料でお試しください
ここでは、継続的インテグレーション(CI)に潜むストレージの問題についてお話ししたいと思います。なぜそれらが予想以上に興味深く、珍しいのか、そしてなぜそれが私がBlacksmithに参加した理由なのかについてです。それを説明するために、私がどのようにしてここにたどり着いたかから始めるべきでしょう。
私が仕事に求めるもの、何よりもそれを求めているのは、挑戦です。私は、すぐに答えが得られないようなシステムの問題を追い求めてキャリアを積んできました。Googleでのストレージ、Colossus(最大の汎用ストレージ基盤)、スタートアップでのeBPFベースのデバッガー、そしてその後Datadogで、最近では本番環境に基づいたコード最適化に取り組んできました。共通点はスタックの特定のレイヤーではありません。それは、まだ誰も明確な答えを持っていない問題への引き寄せです。
そこで、Blacksmithの人々がまさにそのような問題に取り組んでいると聞き続けたとき、私の注意を引きました。深く掘り下げてみると、Blacksmith(すべてのプッシュとプルリクエストで実行されるビルドとテストである継続的インテグレーションを、独自の機械群で実行しています)は、表向きはコンピューティングの問題であると同時に、少なくともストレージの問題でもあることがわかりました。膨大な数の短命な仮想マシンを立ち上げ、破棄し、それぞれに必要なデータ(ソース、依存関係、ビルドキャッシュ、生成された結果)を供給することは、通常手に取るツールには適合しません。高スケール、高チャーン、タイトなレイテンシー予算です。私は「マネージドCI」のために来たのではありません。私はそのワークロードのために来ました。
また、現在の業界のストレージエネルギーのほとんどがスタックの上位に費やされていることにも気づきました。新しいデータベースやデータレイヤーは、ますますAI指向になり、長年使われてきた同じプリミティブの上に構築されています。Blacksmithに惹かれたのは、より稀な機会、つまりレイヤーを一段下に進んで、ストレージ基盤そのものを再考することでした。それはグリーンフィールドの贅沢としてではなく、ここのワークロードがそれらのプリミティブに疑問を投げかける具体的で確固たる理由を与えてくれるからです。ワークロードが本当にそれを要求するから新しい基盤を構築できるということは、私にとって最もエキサイティングなシステム作業の形です。
では、そのワークロードをお見せしましょう。CIジョブが実際にストレージに対して、私たちが実行するスケールで何をするのか、そしてなぜ明白な答えが適合しないのかを見てみましょう。
スケールでのCIジョブの実際の動作
一時的に、「ディスクを持つサーバー」というイメージは忘れてください。Blacksmithでの作業単位は、数分しか持たない、新しく一時的なマイクロVMです。すべてのCIジョブはクリーンなVMを起動し、作業を行い、破壊されます。通常のサーバーのように状態を静かに蓄積する長寿命のホストはありません。そして、私たちはそれを膨大な速度で実行します。毎日、約250万のジョブごとのボリュームを作成および破棄しており、ピーク時には1分あたり約1000台の新しいVMが起動します。
その単一の事実は、以下のすべてのもととなっています。状態は、毎回新しく、高速に、どこかから来る必要があります。それはジョブが実行される前に始まります。マシンは起動するために自身のルートファイルシステムを読み取る必要があり、その同じベースイメージは、多数のVMから同時に要求されます。
VMが起動すると、その作業は、それぞれ独自の特性を持つ、個別のストレージワークロードのコレクションになります。
リポジトリの取得。
ほとんどすべてのジョブは、ソースのプルから始まります。この速度では、同じリポジトリに対する繰り返し転送の壁となり、同じバイトが何度も支払われ、多くの場合、遠いオリジンから取得されます。各ジョブが求めるものは異なります。ここでは浅い先端、そこでは完全な履歴です。プレッシャーは、ディスク上にあるバイトではなく、ネットワークスループットとローカリティにかかります。
環境設定、繰り返し行われる。
リポジトリの取得と同様に、ほとんどすべてのリポジトリの実行は、実際の作業が開始される前に、同じ高コストなセットアップ(ツールチェーン、システムパッケージ、依存関係のインストール)をやり直します。そのセットアップが生成するバイトは、実行ごとに本質的に同一ですが、毎回ゼロから再生成されます。
依存関係を立ち上げる統合テスト。
データベース、サービス、フィクスチャ、シードデータが実行ごとにスピンアップされます。ジョブが終了すると、ほとんどすべてが破棄される、重い一時的なI/Oです。
増分キャッシュが必要なビルド。
Dockerレイヤーキャッシュ、コンパイラおよび依存関係キャッシュ、ビルドツールの状態。これらは書き込み負荷が高く、生成したVMが生き残った場合にのみ価値があります。キャッシュはマシンよりも長生きする必要があります。そして、キャッシュセマンティクス(何を保持するか、どのようにキーを付けるか)は、ストレージのノブではなく、ビルドツール内に存在します。
実行成果物の永続化。
すべてを使い捨てることの裏返し:本当に生き残る必要があるもの。ビルド出力、テストレポート、カバレッジ、ログ、下流にプッシュされるイメージ。書き込みの少数派であり、反対の要件を持っています。耐久性があり、VMがなくなった後もアドレス可能であり、時には大きく、保持ルールによって管理されます。同じシステムが、「ほとんど何も保存しない」と「これを決して失わない」を同時に行う必要があります。
これらすべてが、開発者がCIを待つクリティカルパス上にあります。各ステップは、実行ごとに数秒または数分を追加し、1日に数千回実行されます。ここでのスピードは、単なる便宜ではなく、製品です。そのプレッシャーは、以下のすべてに適用されます。
チャーン(Churn)が全体的な課題
これらのワークロードすべてを貫くスレッドはチャーンです。すべてのジョブは、その世界を作成し、激しく書き込み、ほとんどすべてを破棄します。統合テストジョブはデータベース、サービス、フィクスチャ、シードデータをスピンアップし、作業を行い、そのほとんどは生き残るべきではありません。フリート全体で、ジョブは1日あたり約2ペタバイトをジョブごとのボリュームに書き込み、その約95%が破棄されます(約250万のボリュームライフサイクルにわたって)。作成→書き込み→破棄という単なるレート自体が負荷です。ほとんどのストレージシステムは、蓄積されるデータ用にサイズ設定されていますが、これは数分で蒸発します。
スケールは共有データ上の同時実行性でもある
レートだけが軸ではありません。多くの困難は、共有したいデータ上の同時実行性です。
読み取り側では、人気のあるリポジトリのミラーを想像してください。ピーク時には、単一のキャッシュされたスナップショットに対して、数千のジョブが同時に読み取ることができます。そのファンアウトを1つの共有コピーから高速に提供することは、それ自体が問題です。
書き込み側では、難しいのは増分更新です。実行をまたいで存在する状態であり、各ジョブがそれに小さなデルタを折り込みます。その状態は、大きく、ほとんど静的な共有ベース(ビルドされた依存関係、ウォームアップされたレイヤー、ポピュレートされたキャッシュ)であり、デルタが着地することを望みます。なぜなら、次の実行が速くなるからです。しかし、多くのジョブが同時に同じベースに対してデルタを生成します(ワークフローの並列ジョブ、またはホットなリポジトリの多数の実行)。それぞれが完了時に消滅する一時的なVMであり、調整または圧縮する長寿命の所有者はいません。それらは衝突します。デルタは、複数の他のライターが同じウィンドウで変更しているベースにきれいに着地できないことがよくあるため、競合したり、調整されたり、単に失われたりします。その形状は、見慣れたもの、つまりバックグラウンド圧縮を持つミューテーションログに似ていますが、経済性が破綻します。デルタは非常に小さく、各ライターは短命であるため、ログは圧縮がペイするほど大きく成長しません。それでもチェーンの深さは蓄積し、圧縮して削除する必要があります。
同時実行性は、誰が勝つか、何が失われるかということに加えて、2番目の危険性、つまり正しさを追加します。共有キャッシュに対する多数のライターがいる場合、書き込みがどのように着地しても、リーダーは決して半更新された状態を観測してはなりません。したがって、衝突を解決するだけでは不十分です。すべてのリーダーは、常に一貫性があり、有効なビューを保証される必要があります。
共有はすべてを物語っており、ジョブは互いを信頼していない
上記のほとんどすべての効率的な勝利は共有から生まれます。1つのベースイメージと1つのリポジトリミラーが数千のVMに提供され、環境は実行間で重複排除され、キャッシュはテナント内で実行ごとに再利用されます。しかし、各ジョブは任意のコードであり、数分しか実行されず、失敗したり、キャンセルされたり、途中で誤動作したりする可能性があります。したがって、効率を購入するメカニズム自体が、爆発半径を持つものです。単一の共有キャッシュエントリを破損すると、数千の後のビルドにサイレントに伝播する可能性があります。