ファイル転送向けS3互換ストレージアーキテクチャ
S3互換ストレージ上にファイル転送システムを構築するアーキテクチャパターン、プロバイダー比較、性能最適化の手法を解説します。
S3互換ストレージは、APIが普遍的で価格が競争力があり、ディスクを管理せずにスケールするアーキテクチャを持つため、ほとんどの現代的なファイル転送サービスの基盤になっている。AWS S3がこのモデルを開拓し、Cloudflare R2、Backblaze B2、Wasabi、MinIO、DigitalOcean Spacesなどのクローンが同じRESTインターフェースを実装している。S3互換ストレージ上にファイル転送サービスを構築すると、耐久性の高いオブジェクトストレージ(AWSの場合はイレブンナイン)、大きなファイルのマルチパートアップロード、そしてアプリサーバーをバイパスしてブラウザからストレージに直接転送できる署名付きURLが得られる。個人情報保護法(APPI)の下で求められるデータ保護要件を満たすために、NISCのガイドラインが推奨する暗号化保存も容易に実現できる。
S3 APIが勝った理由
S3 APIは事実上の標準だ。Amazonが2006年に公開し、すべての主要なオブジェクトストレージプロバイダーがそのワークロードを取り込むために実装した。つまり、AWS SDK for JavaScript(aws-sdk v3)を使ってよく書かれた転送サービスは、エンドポイントURLを変えるだけでプロバイダー間を切り替えられる。minio-js、MinIOのmc CLI、rcloneなどのオープンソースクライアントはプロバイダーをまたいで変更なしに動作する。これにより設計者に柔軟性が生まれる:信頼性のためにAWS S3から始め、ゼロエグレス費用のためにCloudflare R2に移行し、またはデータ居住要件のためにMinIOをセルフホストで動かす——アプリケーションコードを書き直すことなく。
転送ワークロード向けプロバイダー比較
| プロバイダー | ストレージ | エグレス | 無料枠 | 特記事項 | |---|---|---|---|---| | AWS S3 Standard | $0.023/GB | $0.09/GB | 5GB、月15GBエグレス | イレブンナイン耐久性 | | Cloudflare R2 | $0.015/GB | $0 | 10GB、月100万回読み取り | ゼロエグレス費用 | | Backblaze B2 | $0.006/GB | $0.01/GB | 10GB無料 | CloudflareとのBandwidth Alliance | | Wasabi | $0.0069/GB | $0 | なし(有料のみ) | 90日間最低ストレージ | | MinIO セルフホスト | ハードウェアコスト | 自社帯域幅 | オープンソース | AGPL v3、どこでも動く | | DigitalOcean Spaces | 月$5で250GB | 1TB込み | なし | 固定価格バンドル |
ファイルが短期間保存されてダウンロードされる転送サービスでは、エグレスが支配的なコストになる。Cloudflare R2とBackblaze B2(Bandwidth Alliance経由)がコスト面で有利だ。AWS S3はIntelligent-TieringやライフサイクルポリシーなどのAWSの機能面で優れている。
大きなファイルのマルチパートアップロード
S3マルチパートアップロードAPIは、5GBを超えるファイルを転送サービスが処理する方法だ。InitiateMultipartUploadでUploadIdを取得し、各チャンクをUploadPartで送り(最小5MB、最大パートサイズ5GB、計10,000パート)、ETagのリストでCompleteMultipartUploadを送る。パートは並列でアップロードできる。失敗したパートは独立して再試行できる。クライアントは各パートの署名付きURLを使うため、アップロードはブラウザからS3に直接行き、アプリサーバーを完全にバイパスする。S3の最大オブジェクトサイズは5TBで、ほぼあらゆる転送ユースケースをカバーする。
署名付きURLとダイレクトアップロード
署名付きURLにより、クライアントはサーバーがバイトを触ることなく直接S3にアップロードまたはダウンロードできる。バックエンドはHMAC-SHA256とAWSクレデンシャルで署名したURLを生成し、指定した時間(通常1〜24時間)有効にする。クライアントはそのURLに対してPUTまたはGETを行う。このパターンにより大幅なコスト削減が実現する:アプリサーバーは10GBのファイルをプロキシするための帯域幅を必要とせず、クライアントがストレージエンドポイントに直接アクセスするためレイテンシも下がる。バケットのCORS設定により、自分のオリジンからのブラウザアップロードが許可される。保存時の暗号化にはSSE-C(顧客提供鍵によるサーバーサイド暗号化)またはSSE-KMSを使う。
転送サービスのアーキテクチャパターン
典型的なS3バックの転送アーキテクチャには3つの層がある。フロントエンドはブラウザで動作し、マルチパートアップロードを開始しチャンクの進捗を追跡する。APIバックエンド(小さなNode.js、Go、Pythonサービス)は認証、PostgreSQLやDynamoDBのメタデータ保存、署名付きURL生成を処理する。ストレージ層がS3互換バケットだ。アプリ層がステートレスなのでこのアーキテクチャは水平スケールが容易で、ストレージ層がすべての帯域幅を吸収する。GETリクエストの前面にCloudflareやCloudFrontのCDNを配置することで、グローバルなダウンロード速度が向上しS3からのエグレスが削減される。
ライフサイクルポリシーと自動削除
転送サービスはファイルが自動的に期限切れになる必要がある。S3ライフサイクルルールは経過時間に基づいてオブジェクトをストレージクラス間で移動するか削除する。「7日以上経過したオブジェクトを削除する」というルールは毎日実行され、期限切れの転送を無償でパージする。Cloudflare R2はTerraformプロバイダーまたはR2 APIを通じてライフサイクルルールをサポートする。より細かい制御には、各オブジェクトに有効期限タイムスタンプのタグを付け、タグに基づいて削除する夜間Lambdaを実行する方法がある。不完全なマルチパートアップロードにも専用のルールを設定すべきだ:AbortIncompleteMultipartUploadを1〜7日後に実行すると不完全なセッションのストレージを回収できる。
パフォーマンス最適化
S3のスループットはプレフィックスでスケールする。AWS S3はバケット内のプレフィックスごとに3,500 PUT/秒と5,500 GET/秒を目標とし、鍵の最初の文字の一貫したハッシュを使って負荷を分散する。連続したキープレフィックス(001、002、003)は避ける:これらは同じパーティションにハッシュされてホットスポットを作る。代わりにランダムプレフィックスかUUIDの最初の8文字のようなハッシュベースのキーを使う。マルチパートアップロードは個別の転送のスループットを向上させ、キーをまたいだ並列接続は総合スループットを向上させる。Transfer AccelerationはアップロードをCloudFrontエッジに最も近い場所を経由してルーティングし、遠くのクライアントからのアップロード時間を追加コストで50〜500%削減できる。
暗号化オプションとそのトレードオフ
サーバーサイド暗号化には3つの種類がある。SSE-S3(またはR2のデフォルト暗号化)はプロバイダーが管理する鍵でAES-256を使い、透明で無料だ。SSE-KMSはAWS KMS管理の鍵を使い、10,000リクエストごとに$0.03プラス鍵の費用がかかるが、コンプライアンスに有用なKMS監査ログを生成する。SSE-Cはリクエストごとに顧客提供の鍵を受け入れ、サーバーはそれで暗号化して鍵を破棄するため、顧客はすべての読み取りで鍵を提供する必要があり扱いにくいが、鍵をプロバイダーのコントロール外に置く。真のE2EEのためには、libsodiumやWeb CryptoのAES-GCMを使ってアップロード前にクライアントサイドで暗号化し、保存されたオブジェクトを不透明な暗号文として扱う。
監視、メトリクス、請求の驚き
CloudWatch(AWS)、R2ダッシュボード、またはプロバイダー相当のツールでバケットメトリクスを監視する。主要メトリクス:BucketSizeBytes、NumberOfObjects、AllRequests、4xxErrors、5xxErrors、BytesDownloaded。予期しないエグレスの急増は多くの場合、ホットリンク(誰かが人気サイトに署名付きURLを埋め込んだ)またはループでダウンロードするボットを示す。予算の50、80、100%で請求アラートを設定する。HexaTransferはこのパターンをクライアントサイドのAES-256-GCM暗号化と組み合わせて使用しているため、S3互換バックエンドには暗号文だけが保存され、暗号化鍵はブラウザを離れることがない。
https://hexatransfer.com — 無料、アカウント不要、最大10GB。
エンドツーエンド暗号化で大容量ファイルを安全に送信
エンドツーエンド暗号化で最大10GBのファイルを無料で転送。アカウント不要。ファイルはアップロード前にブラウザで暗号化されるため、他の誰にも読まれません。
ファイルを送信