G-gen の藤岡です。当記事では、Google Cloud (旧称 GCP) の Artifact Registry で不要になったイメージを自動削除するクリーンアップポリシーを紹介します。
前提知識
Artifact Registry
Artifact Registry は、コンテナイメージや言語パッケージを保管するサービスです。
単体で使うほかに、Google Cloud のサービス(例 : Cloud Run、Cloud Functions 等)では自動で Artifact Registry にイメージが保管される場合もあります。
保管イメージへの課金
デフォルトでは、Artifact Registry に保管されたイメージは削除しない限り残ります。ストレージ料金は $0.10/GB/月(0.5GB 超えた場合)のため、使い方によってはストレージ料金が肥大化する可能性もあります。
クリーンアップポリシーを使うことで、保管イメージの増加によるストレージ料金の肥大化への対処が自動化できます。
クリーンアップポリシーを使わずに、自前のプログラムで過去のイメージを削除する際は以下の記事をご参照ください。 blog.g-gen.co.jp
クリーンアップポリシー
クリーンアップポリシーとは
クリーンアップポリシー とは、Artifact Registry に保存されたアーティファクト(コンテナイメージ等)を、事前に設定したポリシーにもとづいて自動で削除するための機能です。
2024年4月現在では、Preview (プレビュー) 版として公開されています。
削除ポリシーと保持ポリシー
クリーンアップポリシーでは、削除ポリシーと保持ポリシーという2種類のポリシーを定義できます。これらのポリシーはリポジトリに対して設定します。削除ポリシーは削除するイメージの条件を、保持ポリシーは保持するイメージの条件を指定します。(条件については後述)
注意点は、保持ポリシーのみを設定しても、保持対象外のイメージは削除されない点です。削除ポリシーは単体で機能しますが、保持ポリシーは削除ポリシーと組み合わせる必要があります。
例として以下のクリーンアップポリシーが設定されたリポジトリの挙動は、タグの有無は問わず最新の3バージョンを保持し、それ以外のイメージは削除されます。
- タグの有無を問わずイメージを削除(削除ポリシー)
- 最新の3バージョンのみを保持(保持ポリシー)
詳細
条件
クリーンアップポリシーの対象となるイメージには以下の条件を設定できます。
- タグの状態(
tagState
)※必須条件 - タグのプレフィックス(
tagPrefixes
) - バージョンのプレフィックス(
versionNamePrefixes
) - パッケージ名のプレフィックス(
packageNamePrefixes
) - アップロードされてからの期間(
olderThan
/newerThan
) - 保持するバージョン数(
keepCount
)※保持ポリシーでのみ設定可能
制約
クリーンアップポリシーには以下の制約があります。
- クリーンアップポリシーによる削除と保持がトリガーされるのは、1回/日
- 削除ポリシーによってトリガーされる削除は、リポジトリごとに最大300,000件/日
- リポジトリあたりのクリーンアップポリシー数は10
ドライラン
クリーンアップポリシーにはドライランモードがあります。
挙動は Cloud Logging で確認できます(ドライランのためリソースに変化はない)。このログはデータアクセス監査ログとして記録されますが、デフォルトではデータアクセス監査ログが有効になっていません。
そのためドライランの結果を確認するには、Artifact Registry API のデータアクセス監査ログで データ書き込み を有効にします。
Terraform 対応
クリーンアップポリシーは Terraform の google_artifact_registry_repository
リソースでサポートされています。
適用方法
前提
ここでは、前述の例で挙げた「タグの有無は問わず最新の3バージョンを保持し、それ以外のイメージは削除する」クリーンアップポリシーを適用します。
リポジトリの作成
任意のリポジトリを作成します。
fujioka@cloudshell:~ (XXX)$ gcloud artifacts repositories create test-repo \ --repository-format=docker \ --location=asia-northeast1 Create request issued for: [test-repo] Waiting for operation [projects/XXX/locations/asia-northeast1/operations/31e7a62e-11aa-4a0e-8b7a-90e0ccdbd461] to complete...done. Created repository [test-repo]. fujioka@cloudshell:~ (XXX)$
ポリシーファイルの用意
クリーンアップポリシーはコンソールからも設定できますが、JSON ファイルを作成し、コマンドラインからも実行できます。ここでは以下の policy.json
という JSON ファイルを用意します。
[ { "name": "delete-any", "action": {"type": "Delete"}, "condition": { "tagState": "any" } }, { "name": "keep-latest-3", "action": {"type": "Keep"}, "mostRecentVersions": { "keepCount": 3 } } ]
クリーンアップポリシーの設定(ドライラン)
ドライランで適用します。
fujioka@cloudshell:~ (XXX)$ gcloud artifacts repositories set-cleanup-policies test-repo \ --location=asia-northeast1 \ --policy=policy.json \ --dry-run Updated repository [test-repo]. Dry run is enabled. [ { "action": { "type": "DELETE" }, "condition": { "tagState": "ANY" }, "name": "delete-any" }, { "action": { "type": "KEEP" }, "mostRecentVersions": { "keepCount": 3 }, "name": "keep-latest-3" } ] fujioka@cloudshell:~ (XXX)$
コンソールでは、以下のように表示されます。
イメージのプッシュ
任意のイメージをプッシュし、5つのイメージが保存されている状態にします。
ログの確認
ドライランモード(protoPayload.request.validateOnly)で実行された結果が出力されます。
今回は「タグの有無は問わず最新の3バージョンを保持し、それ以外のイメージは削除する」クリーンアップポリシーを適用しました。
実際のリソースとしては5つのイメージがリポジトリにある状態のため、削除対象として2つのイメージが記録されています(protoPayload.request.names)。
{ "protoPayload": { "@type": "type.googleapis.com/google.cloud.audit.AuditLog", "authenticationInfo": { "principalEmail": "service-00000000000@gcp-sa-artifactregistry.iam.gserviceaccount.com" }, "requestMetadata": { "callerIp": "private", "callerSuppliedUserAgent": "stubby_client", "requestAttributes": { "time": "2024-04-02T07:27:58.171276147Z", "auth": {} }, "destinationAttributes": {} }, "serviceName": "artifactregistry.googleapis.com", "methodName": "google.devtools.artifactregistry.v1.ArtifactRegistry.BatchDeleteVersions", "authorizationInfo": [ { "resource": "projects/XXXXXX/locations/asia-northeast1/repositories/test-repo/packages/-", "permission": "artifactregistry.versions.delete", "granted": true, "resourceAttributes": {} } ], "resourceName": "projects/XXXXXX/locations/asia-northeast1/repositories/test-repo/packages/-", "request": { "parent": "projects/XXXXXX/locations/asia-northeast1/repositories/test-repo/packages/-", "validateOnly": true, "@type": "type.googleapis.com/google.devtools.artifactregistry.v1.BatchDeleteVersionsRequest", "names": [ "projects/XXXXXX/locations/asia-northeast1/repositories/test-repo/packages/hello-world/versions/sha256:5d0cc9349f2e675542decde8be21c94264714a7ece91fefdb4f722b18c544510", "projects/XXXXXX/locations/asia-northeast1/repositories/test-repo/packages/hello-world/versions/sha256:cb1a3c1190265153e7b50ccfde70e3683eba5326cfae8ac68632e1a6b9985573" ] } }, "insertId": "1ndsju6d19n5", "resource": { "type": "audited_resource", "labels": { "project_id": "XXXXXX", "method": "google.devtools.artifactregistry.v1.ArtifactRegistry.BatchDeleteVersions", "service": "artifactregistry.googleapis.com" } }, "timestamp": "2024-04-02T07:27:58.162187524Z", "severity": "INFO", "logName": "projects/XXXXXX/logs/cloudaudit.googleapis.com%2Fdata_access", "operation": { "id": "projects/XXXXXX/locations/asia-northeast1/operations/29bfca3e-4a01-4895-8840-b7dfd92ad07c", "producer": "artifactregistry.googleapis.com", "first": true }, "receiveTimestamp": "2024-04-02T07:27:58.429334137Z" }
実行
ドライランモードではなく実際に削除まで行う場合は、コマンドラインで --no-dry-run
をつける、またはコンソールから アーティファクトを削除
を選択します。
- 参考 : リポジトリにポリシーを適用する
結果の確認
クリーンアップポリシーに従い、2つのイメージが削除されました。
{ "protoPayload": { "@type": "type.googleapis.com/google.cloud.audit.AuditLog", "authenticationInfo": { "principalEmail": "service-00000000000@gcp-sa-artifactregistry.iam.gserviceaccount.com" }, "requestMetadata": { "callerIp": "private", "callerSuppliedUserAgent": "stubby_client", "requestAttributes": { "time": "2024-04-02T13:28:08.653796809Z", "auth": {} }, "destinationAttributes": {} }, "serviceName": "artifactregistry.googleapis.com", "methodName": "google.devtools.artifactregistry.v1.ArtifactRegistry.BatchDeleteVersions", "authorizationInfo": [ { "resource": "projects/XXXXXX/locations/asia-northeast1/repositories/test-repo/packages/-", "permission": "artifactregistry.versions.delete", "granted": true, "resourceAttributes": {} } ], "resourceName": "projects/XXXXXX/locations/asia-northeast1/repositories/test-repo/packages/-", "request": { "parent": "projects/XXXXXX/locations/asia-northeast1/repositories/test-repo/packages/-", "names": [ "projects/XXXXXX/locations/asia-northeast1/repositories/test-repo/packages/hello-world/versions/sha256:5d0cc9349f2e675542decde8be21c94264714a7ece91fefdb4f722b18c544510", "projects/XXXXXX/locations/asia-northeast1/repositories/test-repo/packages/hello-world/versions/sha256:cb1a3c1190265153e7b50ccfde70e3683eba5326cfae8ac68632e1a6b9985573" ], "@type": "type.googleapis.com/google.devtools.artifactregistry.v1.BatchDeleteVersionsRequest" } }, "insertId": "1h9vo9pcafo", "resource": { "type": "audited_resource", "labels": { "service": "artifactregistry.googleapis.com", "project_id": "XXXXXX", "method": "google.devtools.artifactregistry.v1.ArtifactRegistry.BatchDeleteVersions" } }, "timestamp": "2024-04-02T13:28:08.644978076Z", "severity": "INFO", "logName": "projects/XXXXXX/logs/cloudaudit.googleapis.com%2Fdata_access", "operation": { "id": "projects/XXXXXX/locations/asia-northeast1/operations/7ba5387a-1dda-4390-9a4c-d100313f1c18", "producer": "artifactregistry.googleapis.com", "first": true }, "receiveTimestamp": "2024-04-02T13:28:08.883393539Z" }
藤岡 里美 (記事一覧)
クラウドソリューション部
数年前までチキン売ったりドレスショップで働いてました!2022年9月 G-gen にジョイン。ハイキューの映画を4回は見に行きたい。
Google Cloud All Certifications Engineer / Google Cloud Partner Top Engineer 2024
Follow @fujioka57621469