Artifact Registry ADR 005: アーティファクト配信モード
コンテキスト
クライアントがアーティファクト(コンテナレイヤー、Maven JAR、npm tarball)をダウンロードするとき、Artifact Registry はそのコンテンツをオブジェクトストレージからどのように提供するかを決定しなければなりません。業界および GitLab 内には、確立された 2 つのパターンが存在します。
- リダイレクトモード: サービスは、事前に署名されたオブジェクトストレージ URL への HTTP リダイレクト(302/307)で応答します。クライアントはストレージバックエンドから直接コンテンツを取得します。サービスはダウンロードパス上でアーティファクトのバイトを一切扱いません。
- プロキシモード: サービスがオブジェクトストレージからコンテンツを取得し、それをクライアントへストリーミングします。すべてのアーティファクトのバイトがサービスを経由して流れます。
GitLab モノリスとコンテナレジストリは、現在どちらも両方のモードをサポートしています。
- コンテナレジストリ:
storage.redirect.disable(boolean、デフォルトfalse)。リダイレクトが無効化されている場合、レジストリはストレージバックエンドへリダイレクトする代わりに、クライアントへ直接コンテンツをストリーミングします。 - GitLab モノリス: すべてのオブジェクトストレージを基盤とする機能(アーティファクト、LFS、パッケージ、アップロード)にわたる
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 に対しては引き続きリダイレクトできなければなりません。
このため、グローバル(インスタンスレベル)のリダイレクトまたはプロキシのトグルでは不十分です。同一インスタンスまたは同一 organization 内の異なる 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 organization のオーナーによって管理されます。粒度は namespace ごとであり、organization ごと、リポジトリごと、アーティファクトごとではありません。
この二軸の形式が、サービスが公開する唯一のつまみの形状です。別個の「ハイブリッド」インスタンスモードは存在しません。オーバーライドはすべてのインスタンスで同じカラムであり、オペレーターは必要な組み合わせを選択します。
メタデータドキュメント
二軸で決定するのは、コンテナレイヤー、Maven アーティファクト、npm tarball など、不透明なペイロードバイトであるアーティファクトコンテンツの配信方法です。これらには application/octet-stream が正しいメディアタイプであり、署名付き URL で忠実に配信できます。
クライアントが宣言されたメディアタイプを検証する形式メタデータドキュメントは、二軸の解決結果にかかわらず、常にストリーミングします。 各形式の仕様に、該当するドキュメントが列挙されています。この基準は、その一覧を決める指針であり、それ自体が例外を認めるものではありません。ドキュメントが例外になるのは、その形式の仕様に列挙されている場合だけであり、列挙されていないドキュメントはアーティファクトコンテンツと同様に配信します。
署名付き URL はオブジェクトに保存された Content-Type で配信し、ストレージレイヤーはすべての blob についてこれを application/octet-stream に設定します。blob は形式の区別なしにダイジェストで重複排除されるため、2 つの形式からアクセスできる 1 つのダイジェストが 2 つの正しいメディアタイプを保持することはできません。タイプはオブジェクトではなく、形式メタデータに属します。ストリーミングレスポンスでは、サービスがヘッダーを直接設定できます。リダイレクトで正しいタイプを伝えられるかどうかは、バックエンドと CDN の組み合わせ(ADR-013)によって異なり、下記の署名付き URL による上書きの検討で扱います。
コストは、列挙されたドキュメントのサイズに比例します。列挙されたドキュメントが大きい形式については、下記の再検討条件で扱います。仕組みとしては、二軸のどちらよりも優先されるストレージレイヤーのストリーミング強制読み取りオプションを使用します。namespace オーバーライドは、引き続きアーティファクトコンテンツを制御します。
署名付き URL でメディアタイプを上書きしない理由
メタデータドキュメントをリダイレクトパスに残し、ストレージバックエンドの response-content-type URL パラメーターを通じて、リクエストごとにメディアタイプを設定します。対応状況は組み合わせによって異なります。
| バックエンドと CDN の組み合わせ | 上書きの挙動 |
|---|---|
| GCS の署名付き URL | URL の署名に含めた場合のみ動作します。署名されていないクエリパラメーターがあると、リクエストは失敗します。 |
| S3 の署名付き URL | URL の署名に含めた場合のみ動作します。上書きには署名されたリクエストが必要で、匿名では使用できません。 |
| Cloud CDN の背後にある GCS | 動作しません。URL プレフィックス署名は、すでにクエリ文字列を持つ URL を拒否するため、サービスはパラメーターを署名に含められません。署名後に追加すると、パラメーターは受け入れられますが無視され、デフォルトではキャッシュキーからも除外されます(2026-09-08 にこのサービスのステージングゾーンで検証済み)。 |
| CloudFront の背後にある S3 | 未解決です。パラメーターがオリジンやキャッシュキーに届くかはディストリビューションの設定次第であり、エンドツーエンドの挙動はベンダーの文書にもなく、ここでのテストも行っていません。 |
リダイレクト後、サービスが制御できるのは渡した URL だけであり、クライアントがリダイレクトに従う際に送るヘッダーは制御できません。そのため、上書きはサービス自身が作成するストレージ署名の中でしか伝達できません。直接アクセスするパスにはその署名がありますが、CDN の背後ではクライアントが持つのは CDN の署名であり、バックエンドには何も伝達しません。
長所:
- メタデータの読み取りでは CDN への負荷分散を維持でき、サービスの帯域幅予算を消費しません。
- 両方の軸が引き続きすべてのダウンロードを制御するため、文書化すべき例外がありません。
短所:
- 移植性がありません。 上の表が示すように、組み合わせごとに仕組みが異なり、ある組み合わせでは不可能で、別の組み合わせでは未検証です。正しく処理できない組み合わせでは、誤ったタイプで配信されますが、そのことを示す情報はレスポンスにありません。CDN をバイパスして、メタデータの読み取りをストレージの直接署名付き URL にリダイレクトすれば動作しますが、アクセス頻度が最も高く最も小さいオブジェクトに対する CDN キャッシュを失い、3 つ目の配信モードを追加することになります。
- 節約できる量には限りがあります。 リダイレクトパスから外れるのは列挙されたドキュメントだけであり、サービスの制約の規模を決めるのはリクエスト数ではなくバイト数です。
却下理由: ストリーミングは、現在と将来のどのバックエンドと CDN の組み合わせでも同じように動作します。メタデータドキュメントが大きく、かつメディアタイプに敏感な形式(たとえば RPM リポジトリのメタデータ)が登場した場合には、再検討します。
書き込み時にコンテンツタイプを設定しない理由
メタデータドキュメントをリダイレクトパスに残し、各ドキュメントを正しい Content-Type で保存します。
長所:
- URL 署名と CDN のレイヤーを変更しません。
- ストレージレイヤーの 1 か所から適用できます。
短所:
- 1 つのオブジェクトは 2 つの正しいタイプを保持できません(上記の重複排除の議論)。
- すでに保存されているものは修復できず、不変のドキュメントは決して書き換えられません。
却下理由: 変更にコストがかからなかったとしても、最初の短所が決定要因です。
この形式が表現するシナリオ
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 モードの形式が表現するすべてのシナリオは
(instance default, override)で表現可能です。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: データベーススキーマ(
namespaces.delivery_mode_overrideカラム) - ADR-008: コンテンツアドレス指定ストレージ(読み取りパス)
- ADR-009: API 設計(ダウンロードエンドポイント)
- ADR-022: namespace の分離(設定境界としての namespace)
- Artifact Registry Issue 362(リダイレクトされた OCI マニフェストの GET が
application/octet-streamを返したこと。マニフェストのストリーミングを強制するきっかけとなった報告) - Artifact Registry Issue 1128(npm packument に関する同様の報告)
a1f3c26a)