コンテナレジストリストレージの削減
コンテナレジストリは、レジストリの使用量を管理しないと、時間とともにサイズが大きくなる可能性があります。たとえば、大量の画像やタグを追加した場合などです:
- 利用可能なタグや画像のリストの取得が遅くなります。
- サーバーのストレージスペースを大量に消費します。
不要なイメージやタグを削除し、コンテナレジストリの使用量を自動的に管理するクリーンアップポリシーを設定する必要があります。
コンテナレジストリの使用状況の確認
Usage Quotas ページ(Settings > Usage Quotas > Storage)には、Pages のストレージ使用量が表示されます。このページには、GitLab.comでのみ利用可能なコンテナレジストリの使用量も含まれています。使用量の測定は、GitLab 15.7からGitLab.comで利用できるようになった、メタデータデータベースに支えられた新しいバージョンのGitLabコンテナレジストリでのみ可能です。セルフマネージドインスタンスでの利用可能予定については、エピック5521をご覧ください。
クリーンアップポリシー
クリーンアップポリシーは、コンテナレジストリからタグを削除するために使用できるスケジュールジョブです。定義されたプロジェクトでは、正規表現パターンにマッチするタグが削除されます。基礎となるレイヤーとイメージは残ります。
タグに関連付けられていない内部レイヤーとイメージを削除するには、管理者は、-m
スイッチを使用してガベージコレクションを使用できます。
クリーンアップポリシーを有効にします
以下の例外を除いて、すべてのプロジェクトでクリーンアップポリシーを実行できます:
-
セルフマネージドGitLabインスタンスの場合、プロジェクトはGitLab 12.8以降で作成されている必要があります。しかし、管理者はGitLabアプリケーションの設定で
container_expiration_policies_enable_historic_entries
をtrueに設定することで、すべてのプロジェクト(GitLab 12.8以前に作成されたものでも)に対してクリーンアップポリシーを有効にすることができます。あるいは、Railsコンソールで以下のコマンドを実行することもできます:ApplicationSetting.last.update(container_expiration_policies_enable_historic_entries: true)
すべてのプロジェクトでクリーンアップポリシーを有効にすると、特に外部レジストリを使っている場合はパフォーマンスに影響が出る可能性があります。
クリーンアップポリシーの仕組み
クリーンアップポリシーは、コンテナレジストリ内のすべてのタグを収集し、削除したいタグだけが残るまでタグを除外します。
クリーンアップポリシーは、タグ名に基づいて画像を検索します。フルパスマッチングのサポートはイシュー281071で追跡されています。
クリーンアップポリシー:
- 指定されたリポジトリのすべてのタグをリストにまとめます。
-
latest
という名前のタグは除きます。 -
name_regex
(期限切れタグ)を評価し、一致しない名前を除外します。 -
name_regex_keep
の値 (保存するタグ) に一致するタグを除外します。 - マニフェストを持たないタグ (UI のオプションの一部ではない) を除外します。
- 残りのタグを
created_date
で並べ替えます。 -
keep_n
(保持するタグの数)の値に基づいて、N個のタグを除外します。 -
older_than
の値 (有効期限) より新しいタグを除外します。 - コンテナレジストリからリストの残りのタグを削除します。
クリーンアップポリシーのワークフロー例
クリーンアップポリシーの保持ルールと削除ルールの相互作用は複雑です。たとえば、このようなクリーンアップポリシーの設定のプロジェクトがあるとします:
- 最新のものを保持:画像名ごとに1タグ。
-
タグを一致させます:
production-.*
- 7日以上前のタグを削除します。
-
一致するタグを削除:
.*
.
そして、これらのタグを持つコンテナリポジトリ:
-
latest
2時間前に公開されました。 -
production-v44
3日前に公開されました。 -
production-v43
6日前に公開されました。 -
production-v42
11日前に公開されました。 -
dev-v44
2日前に公開されました。 -
dev-v43
5日前に公開されました。 -
dev-v42
10日前に公開されました。 -
v44
昨日公開 -
v43
12日前公開 -
v42
20日前に公開されました。
この例では、次のクリーンアップの実行で削除されるタグは、dev-v42
、v43
、v42
です。この優先順位でルールが適用されると解釈できます:
- keepルールが最も優先されます。タグは、いずれかのルールにマッチした場合、保持されなければなりません。
- タグは常に保持さ
latest
れるからlatest
です。 -
production-v44
、production-v43
、production-v42
のタグは、Keep tags マッチング・ルールに一致するため、保持する必要があります。 -
v44
タグは最新のものであり、Keep the most recentルールにマッチするため、保持する必要があります。
- タグは常に保持さ
- removeルールは優先順位が低く、すべてのルールがマッチした場合のみタグが削除されます。どの保持ルールにもマッチしないタグ (
dev-44
,dev-v43
,dev-v42
,v43
,v42
) について:-
dev-44
とdev-43
は、Remove tags older than にマッチせず、保持されます。 -
dev-v42
とv43
とv42
は、Remove tags older thanとRemove tags matchingの両方のルールに一致するので、これら3つのタグは削除できます。
-
クリーンアップポリシーの作成
APIまたはUIでクリーンアップポリシーを作成できます。
UI でクリーンアップ・ポリシーを作成するには、以下の手順に従います:
- プロジェクトの [Settings (設定)] > [Packages and registries (パッケージとレジストリ)] に進みます。
- クリーンアップ・ポリシー]セクションで、[クリーンアップ・ルールの設定]を選択します。
-
フィールドを入力します:
項目 説明 トグル ポリシーのオン/オフを切り替えます。 クリーンアップの実行 ポリシーを実行する頻度を指定します。 最新の 各画像に対して_常に_保持するタグの数。 一致するタグを保持 保持するタグを決定する正規表現パターン。 latest
タグは常に保持されます。すべてのタグには.*
を使います。他の正規表現パターンの例を参照してください。より古いタグを削除 X日より古いタグのみを削除します。 一致するタグを削除 削除するタグを決定する正規表現パターン。この値を空白にすることはできません。すべてのタグには .*
を使用します。他の正規表現パターンの例を参照してください。 - Save を選択します。
選択したスケジュール間隔でポリシーが実行されます。
正規表現パターンの例
クリーンアップ・ポリシーは正規表現パターンを使用して、UIとAPIの両方で、どのタグを保存または削除すべきかを決定します。
正規表現パターンは自動的に\A
と\Z
アンカーで内部を囲まれます。したがって、\A
、\Z
、^
、$
のトークンを正規表現パターンに含める必要はありません。
以下に使用できる正規表現パターンの例を示します:
-
すべてのタグにマッチします:
.*
このパターンは期限切れ正規表現のデフォルト値です。
-
v
で始まるタグにマッチします:v.+
-
main
というタグのみにマッチ:main
-
名前がついているか、
release
で始まるタグにマッチ:release.*
-
v
で始まるタグ、main
という名前のタグ、release
で始まるタグのいずれかにマッチ:(?:v.+|main|release.*)
リソースを節約するためのクリーンアップ制限の設定
クリーンアップ・ポリシーはバックグラウンド・プロセスとして実行されます。このプロセスは複雑で、削除するタグの数によっては、終了までに時間がかかることがあります。
次のアプリケーション設定を使用して、サーバーリソースの枯渇を防ぐことができます:
-
container_registry_expiration_policies_worker_capacity
同時に実行するクリーンアップワーカーの最大数。この値は0
.0
NET 以上である必要があります。0
低い値から開始し、バックグラウンド ワーカーが使用するリソースを監視してから増やす必要が0
あります。0
すべてのワーカーを削除してクリーンアップ ポリシーを実行しないようにするには、この値を .0
デフォルト値は4
です。 -
container_registry_delete_tags_service_timeout
: クリーンアップ プロセスがタグのバッチを削除するのにかかる最大時間 (秒)。デフォルト値は250
です。 -
container_registry_cleanup_tags_service_max_list_size
1回の実行で削除できるタグの最大数。追加のタグは別の実行で削除する必要があります。低い数値から開始し、コンテナイメージが適切に削除されることを確認した後に数値を増やす必要があります。デフォルト値は200
です。 -
container_registry_expiration_policies_caching
ポリシーの実行中にタグの作成タイムスタンプのキャッシュを有効または無効にします。キャッシュされたタイムスタンプはRedis に保存されます。デフォルトでは有効です。
セルフマネージドインスタンスの場合、これらの設定はRailsコンソールで更新できます:
ApplicationSetting.last.update(container_registry_expiration_policies_worker_capacity: 3)
管理者エリアでも利用できます:
- 左のサイドバーで、Search を選択するか、次のページに進んでください。
- Admin Areaを選択します。
- 左サイドバーで、「設定」>「CI/CD」を選択します。
- コンテナレジストリを展開します。
クリーンアップポリシーAPIを使用します。
GitLab APIを使ってクリーンアップポリシーを設定、更新、無効化することができます。
例:
-
すべてのタグを選択、画像ごとに最低1つのタグを保持、14日以上前のタグをクリーンアップ、月に1回実行、
main
という名前の画像を保存、ポリシーは有効:curl --request PUT --header 'Content-Type: application/json;charset=UTF-8' --header "PRIVATE-TOKEN: <your_access_token>" \ --data-binary '{"container_expiration_policy_attributes":{"cadence":"1month","enabled":true,"keep_n":1,"older_than":"14d","name_regex":".*","name_regex_keep":".*-main"}}' \ "https://gitlab.example.com/api/v4/projects/2"
API を使用する際のcadence
の有効な値は以下のとおりです:
-
1d
毎日 -
7d
毎週 -
14d
(2週間ごと) -
1month
毎月 -
3month
(四半期ごと)
API使用時のkeep_n
(画像名ごとに保持されるタグの数)の有効な値は以下のとおりです:
1
5
10
25
50
100
API を使用する際のolder_than
(タグが自動的に削除されるまでの日数)の有効な値は以下のとおりです:
7d
14d
30d
90d
詳細については、APIドキュメントを参照してください:プロジェクトAPIを編集します。
外部コンテナレジストリとの併用
外部コンテナレジストリを使用する場合、プロジェクトでクリーンアップポリシーを実行するとパフォーマンス上のリスクがあります。プロジェクトが何千ものタグを削除するポリシーを実行すると、GitLabバックグラウンドジョブがバックアップされたり、完全に失敗したりする可能性があります。GitLab 12.8より前に作成されたプロジェクトでは、クリーンアップされるタグの数が最小限である場合にのみ、コンテナクリーンアップポリシーを有効にする必要があります。
その他のコンテナレジストリストレージ削減オプション
プロジェクトで使用するコンテナレジストリのストレージを削減するためのその他のオプションをいくつか紹介します:
- GitLab UIを使って、個々の画像タグを削除するか、すべてのタグを含むリポジトリ全体を削除します。
- 個別の画像タグを削除するにはAPIを使います。
- API を使用して、すべてのタグを含むコンテナレジストリリポジトリ全体を削除します。
- API を使用して、レジストリリポジトリのタグを一括削除します。
クリーンアップポリシーのトラブルシューティング
Something went wrong while updating the cleanup policy.
このエラーメッセージが表示された場合は、正規表現パターンが有効であることを確認してください。
GitLab はクリーンアップポリシーの正規表現にRE2 構文を使います。regex101 regex testerで Golang
。一般的な正規表現パターンの例をご覧ください。
クリーンアップポリシーはタグを削除しません
これにはさまざまな理由が考えられます:
-
GitLab 13.6以前では、クリーンアップポリシーを実行するとタグが削除されると思っていたのに削除されないことがあります。これは、Remove tags matchingフィールドの値を編集せずにクリーンアップポリシーを保存した場合に発生します。このフィールドには、
.*
プレースホルダとして.*
灰色で表示された値があります。(または別の正規表現パターン) がフィールドに明示的に入力さ.*
れない限り.*
、nil
値が送信されます。この値は、保存されたクリーンアップ ポリシーがどのタグにも一致しないようにします。回避策として、クリーンアップ ポリシーを編集します。一致するタグの削除] フィールドに.*
を入力して保存します。この値は、すべてのタグを削除する必要があることを示します。 -
GitLab のセルフマネージドインスタンスを利用していて、コンテナリポジトリに 1000 以上のタグがある場合、コンテナレジストークンの有効期限のイシューが発生し、ログに
error authorizing context: invalid token
が表示されることがあります。これを解決するには、2つの回避策があります:
-
GitLab 13.9以降であれば、クリーンアップポリシーに制限を設定することができます。これにより、クリーンアップの実行時間を制限し、期限切れトークンのエラーを回避することができます。
-
コンテナレジストリ認証トークンの有効期限を延長します。デフォルトは5分です。Railsコンソールで
ApplicationSetting.last.update(container_registry_token_expire_delay: <integer>)
。<integer>
は希望の分数です。参考までに、GitLab.comでは有効期限遅延は15分に設定されています。この値を大きくすると、権限を取り消すのに必要な時間が長くなります。
-
あるいは、削除するタグのリストを作成し、そのリストを使ってタグを削除することもできます。リストを作成してタグを削除するには
-
以下のシェルスクリプトを実行します。
for
ループの直前のコマンドは、list_o_tags.out
ループの開始時に常に再初期化さlist_o_tags.out
れるようにします。list_o_tags.out
このコマンドを実行すると、すべてのタグの名前がlist_o_tags.out
ファイルに書き込まれます:# Get a list of all tags in a certain container repository while considering [pagination](../../../api/rest/index.md#pagination) echo -n "" > list_o_tags.out; for i in {1..N}; do curl --header 'PRIVATE-TOKEN: <PAT>' "https://gitlab.example.com/api/v4/projects/<Project_id>/registry/repositories/<container_repo_id>/tags?per_page=100&page=${i}" | jq '.[].name' | sed 's:^.\(.*\).$:\1:' >> list_o_tags.out; done
Railsのコンソールにアクセスできる場合は、以下のコマンドを入力すると、日付で限定したタグのリストを取得できます:
output = File.open( "/tmp/list_o_tags.out","w" ) Project.find(<Project_id>).container_repositories.find(<container_repo_id>).tags.each do |tag| output << tag.name + "\n" if tag.created_at < 1.month.ago end;nil output.close
この一連のコマンドは、
created_at
日付が1ヶ月以上古いタグの一覧を/tmp/list_o_tags.out
ファイルに作成します。 -
list_o_tags.out
ファイルから保持したいタグを削除します。たとえば、sed
を使用してファイルを解析し、タグを削除することができます。Linux# Remove the `latest` tag from the file sed -i '/latest/d' list_o_tags.out # Remove the first N tags from the file sed -i '1,Nd' list_o_tags.out # Remove the tags starting with `Av` from the file sed -i '/^Av/d' list_o_tags.out # Remove the tags ending with `_v3` from the file sed -i '/_v3$/d' list_o_tags.out
macOS# Remove the `latest` tag from the file sed -i .bak '/latest/d' list_o_tags.out # Remove the first N tags from the file sed -i .bak '1,Nd' list_o_tags.out # Remove the tags starting with `Av` from the file sed -i .bak '/^Av/d' list_o_tags.out # Remove the tags ending with `_v3` from the file sed -i .bak '/_v3$/d' list_o_tags.out
-
list_o_tags.out
ファイルをダブルチェックして、削除したいタグだけが含まれていることを確認します。 -
このシェル・スクリプトを実行して、
list_o_tags.out
ファイル内のタグを削除します:# loop over list_o_tags.out to delete a single tag at a time while read -r LINE || [[ -n $LINE ]]; do echo ${LINE}; curl --request DELETE --header 'PRIVATE-TOKEN: <PAT>' "https://gitlab.example.com/api/v4/projects/<Project_id>/registry/repositories/<container_repo_id>/tags/${LINE}"; sleep 0.1; echo; done < list_o_tags.out > delete.logs