Status | Authors | Coach | DRIs | Owning Stage | Created |
---|---|---|---|---|---|
implemented |
@jdrpereira
|
@glopezfernandez
|
@trizzi
@hswimelar
| devops package | 2020-09-29 |
コンテナレジストリメタデータベース
GitLabコンテナレジストリの使い方
GitLabにコンテナレジストリをインテグレーションすることで、全てのGitLabプロジェクトはDockerイメージを保存するための独自のスペースを持つことができます。レジストリを使って、Dockerクライアント、CI/CD、GitLab APIを使ってイメージをビルド、プッシュ、共有することができます。
GitLab.comでは毎日150kから200kのイメージがレジストリにプッシュされ、約700kのAPIイベントが発生しています。また、他のレジストリベンダーを利用している顧客もいますが、96%以上のインスタンスがGitLab Container Registryを利用していることも注目に値します。
GitLab.comとGitLabの顧客にとって、コンテナレジストリはソフトウェアをビルドしデプロイするための重要なコンポーネントです。
現在のアーキテクチャ
コンテナレジストリは単一のGoアプリケーションです。唯一の依存関係は、イメージとメタデータを保存するストレージ バックエンドです。
クライアントアプリケーション(GitLab RailsやDocker CLIなど)はHTTP APIを通してコンテナレジストリとやり取りします。最も一般的なオペレーションはレジストリへのイメージのプッシュとプルです。これらのオペレーションに必要なリクエストの流れは、リクエストの流れで詳しく説明しています。
レジストリでは複数のストレージバックエンドをサポートしており、GitLab.com のレジストリでは Google Cloud Storage(GCS) を使っています。ストレージバックエンドでは、イメージは blob として保存され、重複排除され、リポジトリ間で共有されます。これらのイメージは、リポジトリに依存する各リポジトリに(シンボリックリンクのように)リンクされ、中央のストレージにアクセスできるようになります。
リポジトリの名前と階層、画像マニフェストとタグも、フォルダとファイルの入れ子構造で表されるストレージバックエンドに保存されます。この動画では、レジストリ ストレージ構造の実用的な概要を説明します。
クライアント
コンテナレジストリにはGitLab RailsアプリケーションとDockerクライアント/CLIの2つの主要なクライアントがあります。
Docker
Dockerクライアント(docker
CLI)は主にログイン、プッシュ、プルコマンドを使ってGitLabコンテナレジストリとやり取りします。
ログインと認証
GitLab RailsはGitLabコンテナレジストリのデフォルトのトークンベースの認証プロバイダです。
レジストリが認証されていないDockerクライアントから送信されたリクエストを受信すると、401 Unauthorized
で返信し、GitLab Rails APIからトークンを取得するようクライアントに指示します。その後DockerクライアントはBearerトークンを要求し、すべてのリクエストのAuthorization
ヘッダに埋め込みます。レジストリは、提供されたトークンに基づいて、ユーザーがこれらのリクエストを実行するための認証/認可を受けているかどうかを判断する責任を負います。
詳細はDockerのドキュメントを参照してください。
プッシュとプル
プッシュコマンドとプルコマンドは、イメージ、より正確にはマニフェストとブロブのアップロードとダウンロードに使用されます。プッシュ/プルの流れはドキュメントで説明されています。
GitLab Rails
GitLab RailsはHTTP APIを通してレジストリとやりとりし、Webhook通知を消費します。
GitLab Railsからレジストリへ
レジストリへの唯一のエントリーポイントはHTTP APIです。GitLab Railsはすべてのオペレーションを実行するためにAPIを呼び出します:
オペレーション | UI | 背景 | 観測 |
---|---|---|---|
APIバージョンの確認 | {チェックサークル}はい | {チェックサークル}はい | レジストリがDocker Distribution V2 APIをサポートしていることを確認するためと、GitLab RailsがGitLab Container Registryと通信しているのかサードパーティのものと通信しているのかを識別するためにグローバルに使用します(前者でのみ利用可能な機能を切り替えるために使用します)。 |
リポジトリタグの一覧 | {チェックサークル}はい | {チェックサークル}はい | UI でタグを一覧表示するために使用します。クリーンアップ ポリシーと Geo レプリケーションのバックグラウンドでタグをリストするために使用します。 |
マニフェストが存在するかどうかをチェックします。 | {チェックサークル}はい | {点線円}いいえ | タグごとにマニフェストのダイジェストを取得するために使用します。これは、マニフェストをプルし、タグの詳細を UI に表示するために使用されます。 |
マニフェストをプル | {チェックサークル}はい | {点線円}いいえ | タグ詳細UIで画像サイズとマニフェストダイジェストを表示するために使用します。 |
ブロブをプル | {チェックサークル}はい | {点線円}いいえ | タグの詳細UIで設定ダイジェストと作成日を表示するために使用されます。 |
タグの削除 | {チェックサークル}はい | {チェックサークル}はい | UIとバックグラウンド(クリーンアップポリシー)からタグを削除するために使用されます。 |
有効な認証トークンはGitLab Railsで生成され、レジストリに送信する前にすべてのリクエストに埋め込まれます。
レジストリから GitLab Rails へ
レジストリでは、画像のプッシュなどのイベントが発生したときに外部アプリケーションに通知するWebhook通知をサポートしています。
GitLabの場合、レジストリは現在イメージプッシュイベントの通知をGitLab Rails APIに配信するように設定されています。これらの通知は現在、SnowplowメトリクスとGeoレプリケーションに使われています。
課題
ガベージコレクション
コンテナ・レジストリは、オフライン・マーク&スイープ・ガベージ・コレクション (GC) アルゴリズムに依存しています。これを実行するには、レジストリをシャットダウンするか読み取り専用に設定する必要があります。
マークフェーズの間、レジストリはすべてのリポジトリを分析し、それぞれのリポジトリで参照/リンクされている設定、レイヤー、およびマニフェストのリストを作成します。次に、レジストリはすべての既存の設定、レイヤー、およびマニフェストをリストアップし(中央に格納)、どのリポジトリでも参照/リンクされていないもののリストを取得します。これが削除対象の blob のリストです。
削除対象として識別されたすべてのblobをループし、ストレージバックエンドから1つずつ削除します。
巨大なレジストリでこれを実行すると、完了までに数時間/数日を要する場合があり、その間レジストリは読み取り専用モードのままでなければなりません。これは、GitLab.com のような可用性が厳しく要求されるプラットフォームでは現実的ではありません。
この制限はアップストリームのDockerディストリビューションのドキュメントにも記載されています。
パフォーマンス
現在のアーキテクチャと、リポジトリと画像のメタデータを保存するために(おそらくリモートの)ストレージバックエンドに依存しているため、リポジトリやタグの一覧表示などの最も基本的なオペレーションでさえ、法外に遅くなる可能性があります。
たとえば、どのリポジトリが存在するかを知るために、レジストリはストレージバックエンド内のすべてのフォルダを調べて、その中のリポジトリを特定しなければなりません。存在するすべてのフォルダを訪問して初めて、レジストリはクライアントにリポジトリのリストを返信することができます。リモートのストレージバックエンド(GCSやS3など)を使用している場合、パフォーマンスはさらに悪化します。
一貫性
S3のようなストレージバックエンドは、最終的な一貫性しか提供できません。例として、削除後のblobの読み取りは短時間成功する可能性があります。偶発的一貫性は、オンラインガベージコレクションと組み合わせると問題になる可能性があります。
インサイト
上記と同様の理由で、現在、リポジトリが使用している容量、どのリポジトリが最も容量を使用しているか、どのリポジトリがよりアクティビティか、各画像やタグの詳細なプッシュ/プルメトリクスなど、貴重な情報をレジストリから抽出することは不可能です。このようなインサイトやメトリクスにアクセスできないことは、製品戦略に関して十分な情報に基づいた意思決定を行う能力を著しく低下させます。
追加機能
メタデータの制限により、ページネーション、HTTP APIのフィルタリングとソート、DockerとHelmのChartイメージを区別する機能などの高度な機能のような貴重な機能を実装することは現在のところ不可能です。
このような制約があるため、これらの基本的な制約を克服するソリューションができるまで、新機能の開発を凍結することにしました。
新しいアーキテクチャ
上記のすべての課題を克服するために、私たちはレジストリのメタデータ(ブロブ、リポジトリのリスト、それぞれのマニフェスト/レイヤーが参照/リンクされているもの)をストレージバックエンドからPostgreSQLデータベースにマイグレーションする取り組みを開始しました。
新しいアーキテクチャの最終的な目標はオンライン・ガベージ・コレクション(&2313)を可能にすることですが、データベースが設置されれば、メタデータの制限によってブロックされていたすべての機能を実装することも可能になります。既存のAPIのパフォーマンスも劇的に向上するはずです。
データベースの導入はレジストリ・アーキテクチャに影響を与えます:
データベースの導入により、レジストリはメタデータの書き込みと読み取りにストレージバックエンドを使用しなくなります。代わりに、メタデータはPostgreSQLデータベース上に保存され、操作されます。ストレージバックエンドは、BLOBのアップロードとダウンロードにのみ使用されます。
GitLab RailsやDockerクライアントを含むレジストリとそのクライアントの間のやり取りは、現在のアーキテクチャのセクションで説明したように変更されません。アーキテクチャの変更とデータベースは内部のみです。レジストリのHTTP APIとWebhook通知も変更されません。
データベース
GitLabGoの標準とスタイルガイドラインに従って、データベースの管理にはORMを使用せず、Go標準ライブラリのdatabase/sql
パッケージとPostgreSQLドライバ(lib/pq
)、そしてTCPコネクションプールを介した生のSQLクエリのみを使用しています。
レジストリデータベースの設計と開発者は、GitLabデータベースガイドラインに準拠しています。Goアプリケーションであるため、データベースのマイグレーションを実行するなど、データベースをサポートするために必要なツールを開発する必要があります。
オンラインとデプロイ後マイグレーションの実行は、ドキュメントで説明されているように、レジストリ CLI ですでにサポートされています。
パーティショニング
レジストリデータベースを最初からパーティショニングすることで、パフォーマンスの向上(処理するデータ量を制限し、並列実行を可能にする)、メンテナンスの容易化(テーブルとインデックスをより小さな単位に分割する)、高可用性(パーティションの独立性)を実現します。最初からデータベースをパーティショニングしておくことで、必要に応じて後でシャーディングの実装を容易にすることもできます。
ブロブはリポジトリ間で共有されますが、マニフェストとタグのメタデータはリポジトリごとにスコープされます。これはAPIレベルでも見ることができ、すべての書き込みと読み込みリクエスト(リポジトリのリストを除く)はリポジトリによってスコープされ、その名前空間はリクエストURIの一部となります。このため、アクセスパターンを特定した後、マニフェストとタグをリポジトリごとに、ブロブをダイジェストごとにパーティショニングすることにしました。パーティショニングされたスキーマの初期バージョンはマージリクエストで文書化されました。
GitLab.com
GitLab.comのレジストリデータベースは、スケール、パフォーマンス、分離の問題から、専用のPostgreSQLクラスターを利用します。その他の状況については#93と GitLab-com/gl-infra/reliability#10109をご覧ください。
下の図は、データベース・クラスターのアーキテクチャを示しています:
予想されるレートとサイズの要件
GitLab.comデータベースのレートと サイズ要件は、dev.gitlab.org
のレジストリに基づいて推定されたもので、リンク先のイシューで入手できます。
セルフマネージド・インスタンス
デフォルトでは、セルフマネージドインスタンスの場合、レジストリはGitLabデータベースと同じPostgreSQLインスタンス/クラスターに別の論理データベースを持ちます。しかし、必要に応じてレジストリが別のインスタンス/クラスターを使うように設定することも可能です。
PostgreSQL
最初のデータベーススキーマの検討中に、私たちは他のデータベースエンジンではなくPostgreSQLを選択することに決めました:
- RDBMSのACID保証やパーティショニングなど、私たちが必要とするすべての機能を提供してくれるからです;
- GitLabですでに使われており、管理するのに必要な経験とツールがあること;
- GitLabと同じPostgreSQLインスタンスでレジストリデータベースをホスティングする可能性を、セルフマネジメントのお客様に提供したいのです。
バージョン 12
PostgreSQLはバージョン12でパーティショニングに大きな改良を加えました:
- 外部キーがパーティショニングされたテーブルを参照できるようになりました。これは、一貫性とインテグリティを保証するためだけでなく、データベースレベルでのカスケード削除を可能にするためでもあります;
- インサート、セレクト、アップデートのパフォーマンスが大幅に改善され、ロックの回数が減り、多数のパーティションで一貫したパフォーマンスが得られるようになりました(ベンチマーク);
- 多数のパーティションを持つテーブルの計画アルゴリズムが大幅に改善され、いくつかのテストでは最大10,000倍の高速化が確認されました(ソース);
- 既存のテーブルに新しいパーティションをアタッチする際に、テーブル全体をロックする必要がなくなりました;
- 一括ロード (
COPY
) で、1 行ずつ挿入する代わりに一括挿入を使用するようになりました;
これらの機能とパフォーマンスの向上を活用するには、最初からPostgreSQL 12を使う必要があります。GitLab 14.0以降では、セルフマネージドインスタンス用のPostgreSQL 12が同梱されています。PostgreSQL 12にアップグレードできないお客様には2つの選択肢があります:
- 管理者は、レジストリ用に別のPostgreSQL 12データベースを手動でプロビジョニングして設定することができます。これにより、新しいレジストリとそのメタデータ・データベースが提供する機能の恩恵を受けることができます。
- オンライン・ガベージコレクションが気にならない場合や、別のデータベースのプロビジョニングが不可能な場合は、データベースなしで現行のレジストリを使い続けてください。GitLabはセキュリティバックポートとバグフィックスで現行バージョンをサポートします。
オンラインガベージコレクションを除けば、メタデータデータベースが利用可能になることで、GitLabコンテナレジストリに要求される多くの機能の実装がブロックされなくなります。これらの機能は、メタデータデータベースによってバックアップされた新バージョンを使用するインスタンスでのみ利用可能です。
可用性
認証サービスとblobストレージのバックエンドとは別に、レジストリは新しいアーキテクチャによってもう1つの依存関係を得ました。レジストリの信頼性はその依存関係と同じであることを考えると、データベースのデプロイは高可用性のために予測されるべきです。段階的なマイグレーションアプローチは、高可用性環境の実装とリソースの制約を特定し、緩和するのに役立つはずです。
HTTP API
これは、すべてのレジストリ HTTP API オペレーションと、それらがストレージバックエンドや新しいデータベースにどのように依存しているかの一覧です。リクエストを処理する際に、依存関係が利用できない場合は、 レジストリはエラーレスポンスを返します。
オペレーション | 方法 | 経路 | データベースが必要 | ストレージが必要 | GitLab Rails * で使用します。 |
---|---|---|---|---|---|
APIバージョンの確認 | GET | /v2/ | {点線円}いいえ | {点線円}いいえ | {チェックサークル}はい |
リポジトリ一覧 | GET | /v2/_catalog | {チェックサークル}はい | {点線円}いいえ | {点線円}いいえ |
リポジトリタグの一覧 | GET | /v2/<name>/tags/list | {チェックサークル}はい | {点線円}いいえ | {チェックサークル}はい |
タグの削除 | DELETE | /v2/<name>/tags/reference/<reference> | {チェックサークル}はい | {点線円}いいえ | {チェックサークル}はい |
マニフェストが存在するかどうかをチェックします。 | HEAD | /v2/<name>/manifests/<reference> | {チェックサークル}はい | {点線円}いいえ | {チェックサークル}はい |
マニフェストをプル | GET | /v2/<name>/manifests/<reference> | {チェックサークル}はい | {点線円}いいえ | {チェックサークル}はい |
マニフェストをプッシュ | PUT | /v2/<name>/manifests/<reference> | {チェックサークル}はい | {点線円}いいえ | {点線円}いいえ |
マニフェストの削除 | DELETE | /v2/<name>/manifests/<reference> | {チェックサークル}はい | {点線円}いいえ | {点線円}いいえ |
blobが存在するかチェック | HEAD | /v2/<name>/blobs/<digest> | {チェックサークル}はい | {点線円}いいえ | {点線円}いいえ |
ブロブをプル | GET | /v2/<name>/blobs/<digest> | {チェックサークル}はい | {チェックサークル}はい | {チェックサークル}はい |
ブロブ削除 | DELETE | /v2/<name>/blobs/<digest> | {チェックサークル}はい | {点線円}いいえ | {点線円}いいえ |
ブロブアップロード開始 | POST | /v2/<name>/blobs/uploads/ | {チェックサークル}はい | {チェックサークル}はい | {点線円}いいえ |
ブロブアップロードステータスの確認 | GET | /v2/<name>/blobs/uploads/<uuid> | {チェックサークル}はい | {チェックサークル}はい | {点線円}いいえ |
ブロブチャンクをプッシュ | PATCH | /v2/<name>/blobs/uploads/<uuid> | {チェックサークル}はい | {チェックサークル}はい | {点線円}いいえ |
完全なblobアップロード | PUT | /v2/<name>/blobs/uploads/<uuid> | {チェックサークル}はい | {チェックサークル}はい | {点線円}いいえ |
ブロブアップロードのキャンセル | DELETE | /v2/<name>/blobs/uploads/<uuid> | {チェックサークル}はい | {チェックサークル}はい | {点線円}いいえ |
*
その理由と方法については、レジストリとRailsの相互作用のリストを参照してください。
失敗のシナリオ
データベースの追加に伴い、想定される障害シナリオ、そのような状況でレジストリがどのように動作するか、レジストリの可用性と機能性への影響を強調することが不可欠です。
データベースのフェイルオーバー
データベースへの接続が拒否されたり、フェイルオーバー時にタイムアウトが発生した場合、レジストリは、切断された接続を破棄し、直ちにプールから新しい接続を開こうとします。
このシナリオでは、アプリケーションはパニックを起こしません。リクエストごとに新しい接続を確立しようとします。失敗した場合、HTTP503 Service Unavailable
エラーがクライアントに返され、エラーはログに記録され、Sentryにレポートされます。再試行はありません。レジストリは、データベースアクセスを必要とする別のリクエストを受信した場合にのみ、新しい接続の確立を試みます。
また、設定可能な間隔としきい値を持つTCPヘルスチェッカーを使用して、データベースサーバーの健全性を定期的にチェックするようにレジストリを設定することも可能です(docs)。健全性チェックに失敗した場合、リクエストは HTTP503 Service Unavailable
エラーで停止します。
データベースサーバーが再び利用可能になると、 レジストリは次のリクエストで優雅に再接続し、 人手を介さずに API の全機能を復元します。
期待されるレジストリの動作は、フェイルオーバーシナリオをシミュレートするためにレジストリとデータベースサーバーの間でプログラム可能なTCPプロキシを使用するインテグレーションテストでカバーされます。
接続プールの飽和
指定されたリクエストを処理するためにプールから接続を引き出すことができない場合、レジストリはタイムアウトし、クライアントにHTTP500 Internal Server Error
エラーを返し、Sentryにエラーを報告します。これらのイシューは、プールが枯渇している理由を調査するために開発者をエスカレーションする必要があります。事前に設定されたプールサイズに対して負荷が高すぎるか、トランザクションが接続を長く保持している可能性があります。
Prometheus のメトリクスを使用してアラートを作成し、アプリケーションがエラーを返し始める前に、飽和の可能性に対処する必要があります。GitLab.comレジストリの漸進的なマイグレーションでは、これらのシナリオに特に注意を払うことになるでしょう。その過程で、使用パターンを特定し、メトリクスを観察し、負荷の増加に応じてインフラとアプリケーションの設定を微調整することができます。必要に応じて、影響を制限するためにレート制限アルゴリズムを適用することもあります。過度な制限や時期尚早の最適化を避けるため、決定は実際のデータに基づいて行われます。
予想されるレジストリの動作は、プール・サイズを操作し、APIに対して複数の同時リクエストを発生させ、プールに圧力をかけ、最終的にその容量を使い果たすことによって、インテグレーション・テストでカバーされます。
待ち時間
確立された接続における過度の待ち時間は、検出やデバッグが困難です。通常、待ち時間はアプリケーションエラーやネットワークタイムアウトを発生させませんが、その前に発生することが多いからです。
このため、HTTP API リクエストを処理するために使用されるデータベース・クエリの持続時間はメトリクスを使用して計測されるべきで、異常な変動を検出し、過剰な待ち時間がタイムアウトやサービス不能になる前に適宜アラームをトリガーすることができます。
レジストリとデータベースサーバーの間でプログラム可能なTCPプロキシを使用し、遅延が増大するシナリオをシミュレートするインテグレーションテストで、レジストリの期待される動作をカバーします。
問題のあるマイグレーション
ネットワークやシステムの異常な状態とは別に、問題のあるマイグレーションやデータ障害もデータベースの可用性に影響を与え、結果としてレジストリの可用性にも影響を与える可能性があります。
データベースのマイグレーションは GitLab Rails で使われているのと同じ開発ベストプラクティスに従いますが、レジストリは ORM を使わない Go アプリケーションであるため、マイグレーションは生の SQL 文で表現されます。とはいえ、すべての変更にはデータベースチームのレビューと承認が必要です。
データベースのマイグレーションは冪等であり、必要な場合はいつでもガード句を使用します。また、前方互換性を保証することも意図されています。クラスター環境では、N
データベーススキーマがバージョン N
+1の場合、レジストリバージョンを実行しているノードはN
何のイシューも引き起こさないはず N
です。
観測可能性
システムにもう1つコンポーネントを追加することで、レジストリの動作とその依存関係について適切な観測可能性を保証することがより重要になります。メタデータ・データベースに裏打ちされた新しいレジストリを展開する前に、必要なツールがすべて揃っていることを保証しなければなりません。
この目的のために、Sentryによるエラーレポート、改良された構造化ロギング、改良されたHTTPメトリクスがすでに実装され、リリースされています。この記事を書いている時点では、GitLab.com のロールアウトは進行中です。
さらに、Prometheusメトリクスはデータベース接続プールの詳細で補強される予定です。これらはレジストリの Grafana ダッシュボードに追加され、既存の HTTP API、デプロイ、ストレージのメトリクスに加わります。レジストリ用のデータベースクラスタにもメトリクスとアラートが追加される予定です。
これらのリソースを合わせると、レジストリのパフォーマンスと動作に関する十分なレベルのインサイトが得られるはずです。
新機能と変更点
サードパーティコンテナレジストリ
GitLabはデフォルトでGitLab Container Registryを同梱していますが、Open Container Initiative(OCI) Image Specificationに取って代わられたDocker Distribution V2 Specificationに準拠している限り、サードパーティのレジストリとも互換性があります。
これまで、新機能を追加する際には、サードパーティのレジストリとの完全な互換性を維持するように努めてきました。たとえば、12.8では、基礎となるマニフェストを削除せずに単一のタグを削除する新しいタグ削除機能を導入しました。この機能はDockerまたはOCI仕様の一部ではないため、サードパーティ製レジストリとの互換性を維持するための予備オプションとして、以前の動作を維持しました。
しかし、これは将来変更される可能性があります。オンライン・ガベージコレクションは別として、また課題で説明したように、メタデータ・データベースは中長期的にはGitLabコンテナ・レジストリに要求される多くの機能の実装をブロックしないでしょう。これらの機能のほとんどは、GitLabコンテナレジストリを使用するインスタンスでのみ利用できるようになります。これらはDockerディストリビューションやOCIの仕様の一部ではなく、互換性のあるフォールバックオプションを提供することもできません。
このため、サードパーティのレジストリがサポートされ続ける限り、GitLabコンテナレジストリを使用する必要がある機能は、サードパーティのレジストリを使用する場合は無効になります。
GitLab Rails との変更の同期
現在のところ、GitLab RailsとGitLabコンテナレジストリのリリースとデプロイは完全に独立しており、説明したタグの削除機能を除けば、新しいAPI機能や変更点は導入していません。
レジストリはGitLab Railsの変更から独立したままですが、中長期的には新機能の実装や変更点はGitLab Railsの対応する変更を意味するため、後者はレジストリの特定の最小バージョンに依存することになるでしょう。
例えば、各リポジトリのサイズを追跡するために、メタデータデータベースを拡張してその情報を保存し、GitLab Railsが消費するHTTP APIを拡張することでそれをGitLab Railsに伝搬させることができます。GitLab Rails では、この新しい情報はおそらくデータベースに保存され、UI/API レベルで新機能を提供するために処理されるでしょう。
このような変更には、GitLab RailsとGitLabコンテナレジストリのリリースとデプロイ間の同期が必要になります。
機能の切り替え
レジストリの特定のバージョンに依存するGitLab Railsの機能はすべて、レジストリのベンダーとバージョンを検証することで保護する必要があります。
これは、新しいタグ削除機能(GitLabコンテナレジストリv2.8.1+でのみ利用可能)を使ってタグを削除すべきか、それとも古い方法を使うべきかを判断するためにすでに行われています。この場合、GitLab RailsはレジストリのタグルートにOPTIONS
リクエストを送り、DELETE
メソッドがサポートされているかどうかを判断します。
あるいは、長期的な普遍的な解決策として、レジストリのベンダー、バージョン、サポートされている機能(最後の2つはベンダーがGitLabの場合にのみ適用されます)を決定し、GitLab Railsのデータベースに永続化する必要があります。そして、この情報をリアルタイムで使って機能を切り替えたり、可能であれば代替方法にフォールバックしたりすることができます。このアプローチの初期実装は#204839の一部として導入されました。現在のところ、メトリクスの目的でのみ使用されています。レジストリがホットスワップされる可能性のあるセルフマネージドインスタンスにおいて、バージョン情報が最新に保たれることを保証するためには、さらなる改善が必要です。
リリースとデプロイ
上述したように、フィーチャートグリングは同期しないリリースやデプロイに対する最後の防衛策を提供し、新機能をサポートするレジストリバージョンがまだ利用できない場合でもGitLab Railsが機能し続けることを保証します。
しかし、GitLab RailsとGitLabコンテナレジストリのリリースとデプロイは、遅延を避けるために同期させる必要があります。GitLab Railsとは逆に、レジストリのリリースとデプロイは手動で行われるため、メンテナーはGitLab Railsの変更が対応するレジストリの変更後にのみリリースとデプロイが行われるように特別な注意を払う必要があります。
このプロセスを強化するソリューションとして、GitLab Railsのコードベースにレジストリの必要最小限のバージョンを含むファイルを追加することができます。このファイルは、レジストリの特定のバージョンに依存する変更があるたびに更新する必要があります。また、GitLab Railsをリリースしてデプロイするときにもこのファイルを考慮し、指定された必要最小限のレジストリバージョンがデプロイされたときだけパイプラインが通るようにする必要があります。
イテレーション
- メタデータ・データベース・スキーマの設計
- データベースを使用したメタデータ管理のサポートを追加します;
- 小規模、中規模、大規模リポジトリのマイグレーションを促進する計画とツールの設計;
- オンラインガベージコレクションの実装
- GitLab.comのステージングとプロダクションにデータベースクラスタを作成;
- GitLab.com用の自動デプロイパイプラインの作成;
- GitLab.comの既存レジストリのデプロイと段階的マイグレーション;
- セルフマネージドインストールへのメタデータデータベースのロールアウトサポート。
すべてのタスクの詳細なリストと定期的な進捗状況の更新は、エピック&2313にあります。