gcr-cleanerを使ってビルドついでにArtifact Registryの古いイメージを削除する
ふだんの開発では、Ruby on Rails のアプリをコンテナイメージとしてビルドし、それを Cloud Run へデプロイして動かしています。イメージへはタグをつけており、デプロイのたびに新しく生成されます。こうなるとイメージの数がおおくなり、保管料が無視できなくなってきます。
Artifact Registry の料金 - Storage https://cloud.google.com/artifact-registry/pricing?hl=ja#storage
おおよそ100GB程度使っており、それでも$10
なのでまだ慌てる時間ではないですが、節約できるものは積極的に削りましょう。
gcr-cleanerを Cloud Build で実行する
Artifact Registry のコンテナイメージを削除するには大きくふたつ選択肢があります。
- リポジトリのクリーンアップポリシーでライフタイムサイクルを設定する
- gcr-cleaner で削除する
こちらのスクラップで言及(というかほぼ完結)しています。
この記事でも「10個だけ残してあとは削除」ということをやりたいたいめ、gcr-cleaner で消すことにします。
イメージをビルドするトリガーに混ぜる
gcr-cleaner を実行するとして、すでにあるビルドに混ぜるか、新しくトリガーを作るか迷うところですが、すでにあるビルドに混ぜるのがオススメです。私たちが運用しているビルドでは、Cloud Runへのデプロイのために コンテナイメージのビルドと Artifact Registry へのプッシュを行っています。この状況だと、
- サービスアカウントの権限設定をひとつ追加すればOK
- イメージ名も指定しやすい
- ビルドイメージのプッシュとセットで実行されるため、確実にイメージがプッシュされたあとにクリーンアップを実行できる
という条件が揃っており、実現までの作業が少なく済みます。Cloud Build のサービスアカウントに、「Artifact Registry 管理者」のロールを追加してください。
Artifact Registry のリポジトリとCloud Buildのプロジェクトが異なる場合
補足です。プロジェクトによっては、Artifact Registry のリポジトリをひとつのプロジェクトで一元管理するシーンもあるかと思います。その場合は、Artifact Registry のリポジトリに対して、許可するIAMを設定することになります。Terraformの例ですが、以下のようにします。
# Artifact Registry リポジトリ
resource "google_artifact_registry_repository" "app" {
provider = google-beta
project = var.gcp_project_id
location = var.artifact_registry_location
repository_id = "app"
description = "アプリケーション"
format = "DOCKER"
}
# 別プロジェクトの Cloud Build からのアクセスを許可する。
resource "google_artifact_registry_repository_iam_binding" "binding_builder" {
provider = google-beta
project = var.gcp_project_id
location = var.artifact_registry_location
repository = google_artifact_registry_repository.app.name
role = "roles/artifactregistry.repoAdmin" # Cloud Build から削除できるようにここをrepoAdminとする
members = [
# CloudBuildのサービスアカウントを指定する
"serviceAccount:xxxxxxxxxxxxxxx@cloudbuild.gserviceaccount.com",
]
}
-dry-run
で試す
イメージが消えることに対して不安がある場合、-dry-run
オプションで削除対象をリストアップするのみに留めるよう、オプションを指定できます。早速試します。
- id: build-app # コンテナイメージのビルド
- id: push-app # コンテナイメージのプッシュ
- id: deploy-app # Cloud Run へのデプロイ
- id: clean-backend-images
name: asia-docker.pkg.dev/gcr-cleaner/gcr-cleaner/gcr-cleaner-cli:latest
args:
- -repo
- $_ARTIFACT_REPOSITORY_IMAGE_NAME
- -keep
- "10"
- -tag-filter-any
- "^v.*" # v1.1.234 のように、vの文字列から始まるタグを含むイメージのみ
- -dry-run # これを指定
waitFor: ["deploy-app"]
substitutions:
_ARTIFACT_REPOSITORY_IMAGE_NAME: us-central1-docker.pkg.dev/${PROJECT_ID}/apps/backend-app
トリガーを実行してみた様子です。
v
からはじまるイメージ以外も削除されるように見えますが、これはv1.101
に対応するハッシュも検出されているだけです。どちらも同じイメージを指していますので、問題なく-tag-filter-any
で指定したものだけが消えます。
実際に消す
対象が合ってそうならば、-dry-run
のオプションを外すことでイメージが削除されます。
まとめ
gcr-cleanerを Cloud Build で実行することは、以下のメリットがあります。
- ライフサイクルポリシーではなく「10個イメージを残してあとは削除」のように現実に則した指定ができる
- Cloud Build でイメージをビルド・プッシュする処理に混ぜることで、権限設定やイメージ名を指定する手間を省く
ひとつステップを追加することでストレージ料金の節約になりますので、ぜひお試しください。
Discussion