Artifact Registry ADR 005: アーティファクト配信モード
コンテキスト
クライアントがアーティファクト(コンテナレイヤー、Maven JAR、npm tarball)をダウンロードするとき、Artifact Registry はそのコンテンツをオブジェクトストレージからどのように提供するかを決定しなければなりません。業界および GitLab 内には、確立された 2 つのパターンが存在します。
- リダイレクトモード: サービスは、事前に署名されたオブジェクトストレージ URL への HTTP リダイレクト(302/307)で応答します。クライアントはストレージバックエンドから直接コンテンツを取得します。サービスはダウンロードパス上でアーティファクトのバイトを一切扱いません。
- プロキシモード: サービスがオブジェクトストレージからコンテンツを取得し、それをクライアントへストリーミングします。すべてのアーティファクトのバイトがサービスを経由して流れます。
GitLab モノリスとコンテナレジストリは、現在どちらも両方のモードをサポートしています。
- コンテナレジストリ:
storage.redirect.disable(boolean、デフォルトfalse)。リダイレクトが無効化されている場合、レジストリはストレージバックエンドへリダイレクトする代わりに、クライアントへ直接コンテンツをストリーミングします。 - GitLab モノリス: すべてのオブジェクトストレージを基盤とする機能(artifacts、LFS、packages、uploads)にわたる
proxy_download設定(デフォルトfalse)。
プロキシモードが必要な理由
GitLab の ドキュメント には、リダイレクトが機能せず、プロキシが必須となる実際のデプロイシナリオが列挙されています。
- ファイアウォール制限: クライアントネットワークがオブジェクトストレージのエンドポイントへの直接アクセスをブロックします。これは規制環境やエアギャップ環境、半隔離されたネットワークで一般的です。
- 信頼されていない CA: オブジェクトストレージが、クライアントが信頼していない CA の証明書を使用しています(NetApp アプライアンスや Ceph Object Gateway などのサードパーティの S3 互換バックエンドで一般的です)。
- 非公開のストレージバックエンド: オブジェクトストレージのエンドポイントにクライアントネットワークから到達できません(プライベート VPC、内部専用エンドポイント)。
- HTTPS ダウングレード: オブジェクトストレージのエンドポイントが平文の HTTP で提供されており、クライアントが HTTPS でレジストリにアクセスした際に混在コンテンツエラーを引き起こします。
- CORS 制限: ブラウザベースのクライアントは、ストレージ側に適切な CORS ヘッダーがないと、オブジェクトストレージへのクロスオリジンリダイレクトをたどれません。
- 署名付き URL のセキュリティ: 署名付き URL は時間制限がありますが、特定のユーザーやセッションに紐付けられてはいません。高セキュリティ環境では、アーティファクトのバイトがサービスのネットワーク境界から決して外に出ないことを組織が好みます。
これらのシナリオの一部は、CA/ファイアウォール/ルーティングの制約が現実となっているサードパーティの S3 互換ソリューション(NetApp、Ceph Object Gateway)を使用している顧客を含め、現在 GitLab の顧客に大規模に影響を与えています。
デュアルパーソナリティ・デプロイモデル
Artifact Registry は、複数のデプロイモデル(GitLab.com(SaaS)、GitLab Dedicated、Self-Managed インスタンス)に対応できるモジュラーサービスとして設計されています。リモート/デュアルパーソナリティモデルでは、Self-Managed または Dedicated インスタンスが GitLab.com の Artifact Registry にリモートバックエンドとして接続します。
このモデルでは、GitLab.com の Artifact Registry は、基盤となるストレージプロバイダー(GCS、Cloud CDN)の IP レンジを許可リストに追加できない企業ファイアウォールの背後にいる可能性のあるクライアントへダウンロードを提供します。サービスは、それらの namespace に対してはアーティファクトコンテンツをプロキシしつつ、クライアントがストレージに直接到達できる namespace に対しては引き続きリダイレクトできなければなりません。
このため、グローバル(インスタンスレベル)のリダイレクトまたはプロキシのトグルでは不十分です。同一インスタンスまたは同一組織内の異なる namespace が異なるネットワーク制約を持ちうるため、namespace ごとの設定(ADR-022)はインスタンスのデフォルトに関係なく利用可能でなければなりません。
決定
Artifact Registry は、リダイレクトとプロキシという 2 つのアーティファクト配信パターンをサポートし、二軸モデルとして選択します。インスタンスレベルのデフォルトに加えて、常に利用可能な namespace ごとのオーバーライドです。
軸 1: インスタンスのデフォルト
インスタンスには、2 つのデフォルト配信パターンのいずれかが構成されます。
- リダイレクト(推奨されるデフォルト)。すべてのアーティファクトのダウンロードは、事前に署名されたオブジェクトストレージ URL へクライアントをリダイレクトすることで提供されます。クライアントはストレージバックエンドから直接コンテンツを取得します。サービスはダウンロードパス上でアーティファクトのバイトを一切扱いません。これによりサービスの負荷とエグレス帯域幅が最小化されます。サービスからのすべての応答が小さいため、厳しいタイムアウトとより小さいリソースフットプリントが可能になります。すべてのクライアントがストレージバックエンドに直接到達できるデプロイに適しています。
- プロキシ。すべてのアーティファクトのダウンロードは、オブジェクトストレージからのコンテンツをサービス経由でストリーミングすることで提供されます。すべてのアーティファクトのバイトがサービスを経由して流れます。これは、ファイアウォールの背後にある Self-Managed インスタンスなど、クライアントがストレージバックエンドに直接到達できないデプロイ向けです。プロキシでは、サービスが大きなレスポンスボディ(コンテナレイヤーの場合は数 GB に及ぶ可能性があります)を扱う必要があり、書き込みタイムアウト、メモリ割り当て、帯域幅容量に影響します。
インスタンスのデフォルトはサービス構成で設定され、再起動時にのみ変更されます。
軸 2: namespace 単位の上書き
null 許容の namespace ごとのオーバーライド(namespace レコードと一緒に保存されます。ADR-022 および ADR-007 を参照)は、インスタンスのデフォルトに関係なく、すべてのインスタンスで利用可能です。その三状態のセマンティクスは次のとおりです。
NULL— インスタンスのデフォルトを継承します。redirect— この namespace に対してリダイレクトを強制します。proxy— この namespace に対してプロキシを強制します。
任意のダウンロードリクエストに対する実効的な配信パターンは次のとおりです。
effective = namespace.delivery_mode_override ?? instance.delivery_mode
namespace ごとの設定は、namespace 管理 API(実装仕様では S17 が所有)を通じて GitLab 組織のオーナーによって管理されます。粒度は namespace ごとであり、組織ごと、リポジトリごと、アーティファクトごとではありません。
この二軸の形式が、サービスが公開する唯一のつまみの形状です。別個の「ハイブリッド」インスタンスモードは存在しません。オーバーライドはすべてのインスタンスで同じカラムであり、オペレーターは必要な組み合わせを選択します。
この形式が表現するシナリオ
Artifact Registry がサポートする必要があるすべてのデプロイシナリオは、2 つの軸の組み合わせに帰着します。
- シングルテナント、すべてのクライアントがストレージに到達できる。 インスタンスのデフォルト =
redirect、namespace オーバーライドは設定なし。 - ファイアウォールの背後にある/信頼されていない CA を持つシングルテナント。 インスタンスのデフォルト =
proxy、namespace オーバーライドは設定なし。 - マルチテナント SaaS/デュアルパーソナリティ(GitLab.com): インスタンスのデフォルト =
redirect、クライアントがストレージに到達できない個々の namespace はオーバーライドをproxyに設定します(またはその逆)。 - 1 つの例外的な namespace を持つシングルテナント。 インスタンスのデフォルトは一般的なケースに一致し、例外はオーバーライドをもう一方の値に設定します。
システムへの制約
両方の配信パターンをサポートすることは、サービス設計に影響を及ぼします。
- タイムアウト。リダイレクトのレスポンスは小さく高速です。プロキシのレスポンスは数 GB に及び、数分かかることがあります。サービスは、リダイレクトのパフォーマンスに影響を与えることなく、プロキシダウンロードのための延長されたタイムアウトをサポートしなければなりません。
- リソースフットプリント。プロキシダウンロードは大きなペイロードをサービス経由でストリーミングし、リクエストごとのメモリと帯域幅の要件を増加させます。容量計画では、プロキシとして提供されるトラフィックの割合を考慮しなければなりません。
- ストレージバックエンドへのアクセス。ストレージバックエンドは、署名付き URL の生成(リダイレクト用)とストリーミング読み取り(プロキシ用)の両方をサポートしなければなりません。
- CDN とのインタラクション。クライアントが CDN を基盤とするストレージ URL から直接取得するため、リダイレクトは CDN キャッシュの恩恵を受けます。プロキシは CDN をバイパスし、キャッシュの恩恵を失います。実装仕様では、実効的な配信パターンがプロキシの場合、CDN/URL キャッシュのミドルウェアスタックをエンドツーエンドでバイパスします。
- モニタリング。オペレーターがパターンごとに帯域幅、レイテンシー、容量への影響を追跡できるよう、サービスはメトリクスとログにおいてリダイレクトトラフィックとプロキシトラフィックを区別しなければなりません。
- namespace ごとのルックアップ。オーバーライドは、リクエストハンドラが認可とルーティングのためにすでに結合している同じ namespace 行から読み取られます。別個のルックアップや二重の結合は不要です。コストは、ハンドラがすでに実行しているクエリ上の単一の null 許容カラムです。
影響
ポジティブな影響
- ネットワーク制限による顧客への影響なし。ファイアウォールの背後にある、信頼されていない CA を持つ、またはストレージへ直接アクセスできないデプロイでも、回避策なしにプロキシ経由で Artifact Registry を使用できます。
- 既存の GitLab 機能との同等性。コンテナレジストリと GitLab モノリスはどちらもプロキシダウンロードをサポートしています。Artifact Registry でそれをサポートしないことは、これらのシステムから移行する顧客にとって機能後退となります。
- デュアルパーソナリティのサポート。オーバーライドにより、すべてのトラフィックをサービス経由で強制することなく、GitLab.com が異なるネットワーク制約を持つ namespace を提供するリモートモデルが可能になります。
- 運用上一貫した表面。オペレーターは、すべてのデプロイで 1 つのインスタンスレベルのつまみと 1 つの namespace ごとのカラムを目にします。namespace ごとの設定を黙って無効化するインスタンスモードのゲートは存在しません。
- オーバーライドは namespace ごとのオプトイン。namespace ごとの制御を必要としないデプロイは何のコストも払いません。オーバーライドは
NULLであり、実効パターンは単にインスタンスのデフォルトです。
ネガティブな影響
- サービスの複雑さの増加。ダウンロードパスは、異なるタイムアウト、メモリ、エラー処理の特性を持つ、根本的に異なる 2 つのレスポンスパターン(小さなリダイレクト対大きなストリーミングボディ)を扱わなければなりません。
- プロキシトラフィックに対するより高いリソース要件。プロキシとして提供される namespace やインスタンスは、リクエストごとに大幅に多くの帯域幅とメモリを消費します。少数の高トラフィックのプロキシ namespace が、サービス容量に不均衡な影響を与える可能性があります。
- プロキシトラフィックに対する CDN 効果の低下。プロキシは CDN をバイパスし、ストレージバックエンドの負荷を軽減しダウンロードレイテンシーを改善するキャッシュの恩恵を失います。
- 両方のパターンのテストと保守。各パターンはダウンロードパス上で異なる挙動を持ちます。テストは、「オーバーライド設定なし」と「オーバーライドが反対側を強制する」の両方の組み合わせで、両方をカバーしなければなりません。
代替案
代替案 1: リダイレクトのみ
サービスは常にリダイレクトで応答します。クライアントがストレージに到達できない顧客は、サービスの外部(VPN、プロキシサイドカー、ファイアウォールルール)でこの問題を解決しなければなりません。
長所:
- 最もシンプルなサービス設計。すべてのレスポンスが小さい。厳しいタイムアウト、最小限のメモリ。
- CDN が常に有効。
短所:
- 実際の顧客のデプロイを壊す: ファイアウォール、信頼されていない CA、非公開バックエンドは仮想的なものではありません。これらは現在 GitLab の顧客に影響しています。
- 既存機能からの後退: コンテナレジストリと GitLab モノリスはどちらもプロキシダウンロードをサポートしています。この機能を取り除くことは後退です。
- デュアルパーソナリティモデルをブロックする: GitLab.com に接続するリモートの Self-Managed/Dedicated インスタンスは、クライアントが GCS/Cloud CDN に到達できない場合に機能できません。
却下理由: 顧客への影響は具体的かつ十分に文書化されています。
代替案 2: 3 つの名前付きインスタンスモード(redirect / proxy / hybrid)
インスタンスは 3 つのモードのいずれかに構成されます。redirect(namespace ごとのルックアップなし。インスタンスは常にリダイレクトする)、proxy(namespace ごとのルックアップなし。インスタンスは常にプロキシする)、または hybrid(各リクエストで namespace ごとのオーバーライドが評価される。インスタンスのデフォルト = リダイレクト)。これはこの ADR で以前に記録された決定でした。
長所:
- namespace ごとのカラムをまったく読み取らない
redirectおよびproxyモードでは、ダウンロードパス上でわずかに安価。 - モード名が設計議論における元の 3 つのシナリオに直接マッピングされる。
短所:
- 運用上一貫していない。namespace ごとのオーバーライドは
hybridモードでは利用可能で、他の 2 つでは利用できません。オペレーターは、見ている namespace 設定が意味を持つかどうかを知るために、どのインスタンスモードにいるかを知る必要があります。namespace のオーナーは反対側から同じあいまいさに直面します。自分のオーバーライドは、通常見ることのできないグローバル設定によって有効になる場合とそうでない場合があります。 - 追加の表現力なし。3 モードの形式が表現するすべてのシナリオは
(インスタンスのデフォルト, オーバーライド)で表現可能です。redirectモード ≡ インスタンス=redirectでオーバーライドゼロ、proxyモード ≡ インスタンス=proxyでオーバーライドゼロ、hybridモード ≡ インスタンス=redirect(またはproxy)で一部の namespace が反対の値に設定。 - 最適化はわずか。
redirect/proxyモードでオーバーライドカラムの読み取りをスキップしても測定可能なものは何も節約できません。ハンドラはリクエストごとに認可とルーティングのためにすでに namespace 行をロードしているため、オーバーライドの読み取りは既存のクエリの一部です。 - 例外が必要になった場合の一方通行。今日
redirectまたはproxyモードを選択したデプロイは、インスタンスレベルのモード変更(および暗黙の再起動)なしに 1 つの例外的な namespace オーバーライドを設定する能力を放棄します。
却下理由: 二軸の形式は、より小さく、より一貫した表面で同じ領域をカバーします。3 モードの形式が節約するわずかなコストは、それが導入する運用上のあいまいさに見合いません。この代替案はもともとの決定であり、現在は置き換えられています。
代替案 3: リポジトリ単位の設定
namespace レベルではなくリポジトリレベルで配信オーバーライドを許可します。
長所:
- より細かい制御。namespace はほとんどのリポジトリでリダイレクトを使用し、特定のリポジトリでのみプロキシを使用できます。
短所:
- 問題に対する過剰な設計: ネットワーク制約は個々のリポジトリではなく namespace のクライアント環境に適用されます。クライアントがストレージに到達できない場合、その namespace 内のどのリポジトリにも到達できません。
- 管理オーバーヘッド: 管理者はすべてのリポジトリを個別に構成する必要があります。
- 一貫しないユーザー体験: 同じ namespace 内の異なるリポジトリが異なる挙動をするのは混乱を招きます。
却下理由: ネットワーク制約は通常、リポジトリレベルではなく namespace/ネットワーク境界に適用されます。namespace ごとが適切な粒度です。具体的なユーザー需要が現れた場合、namespace 設定から継承しつつ個別にオーバーライドできるリポジトリごとのオーバーライドを将来検討できますが、これはスコープ外です。
参考資料
- Container Registry
storage.redirect.disable - GitLab モノリスの
proxy_downloadドキュメント - ADR-007: Database Schema(
namespaces.delivery_mode_overrideカラム) - ADR-008: Content-Addressable Storage(読み取りパス)
- ADR-009: API Design(ダウンロードエンドポイント)
- ADR-022: Namespace Decoupling(設定境界としての namespace)
- S01: HTTP Server and Routing(この決定の影響を受けるタイムアウトとレスポンスサイズの前提)
- S06: Storage Layer(解決アルゴリズムを実装する。
StorageConfig.delivery_modeproto フィールド、BlobStore.OpenBlobのWithDeliveryModeオプション、WithForceStreamの優先順位) - Related discussion on redirect vs proxy
- Two-axis collapse rationale(この決定を導いた MR-108 の議論)
c955a93f)