前回の続き。Cloud Build+Cloud Runで作られた不要なイメージを削除してくれる
gcr-cleanerを試してみたときの備忘録。
とりあえず、gcloudをアップデート。
$ gcloud components update
設定の流れ
READMEに書いてある流れ。
- Google APIの有効化(GAE/Cloud Scheduler/Cloud Run)
- gcr-cleaner用のサービスアカウントの作成
- gcr-cleaner用のコンテナサービスをCloud Runにデプロイ
- サービスアカウントにCloud Storageの削除権限を付与
- デプロイしたCloud Runサービスを呼び出すサービスアカウントを作成
- Cloud SchedulerでHTTPジョブを作成

全体像としてはこんな感じで、
サービスアカウント2つと
Cloud Runのサービスが1つと
Schedulerのジョブを1つ作成する
Google APIの有効化
まずは利用するAPIたちを有効化する。
すでに有効化済みの場合は、スキップでOK
gcloud services enable --project "${PROJECT_ID}" \
appengine.googleapis.com \
cloudscheduler.googleapis.com \
run.googleapis.com
gcr-cleaner用のサービスアカウントの作成
gcr-cleaner内で利用するサービスアカウントを作成
gcloud iam service-accounts create "gcr-cleaner" \
--project "${PROJECT_ID}" \
--display-name "gcr-cleaner"

gcr-cleaner用のコンテナサービスをCloud Runにデプロイ
用意されているgcr-cleanerのサービスをデプロイ。
サービス名や--regionや--timeoutは適宜変更する。
gcloud --quiet run deploy "gcr-cleaner" \
--async \
--project ${PROJECT_ID} \
--platform "managed" \
--service-account "gcr-cleaner@${PROJECT_ID}.iam.gserviceaccount.com" \
--image "us-docker.pkg.dev/gcr-cleaner/gcr-cleaner/gcr-cleaner" \
--region "us-central1" \
--timeout "60s"

サービスアカウントにCloud Storageの削除権限を付与
デプロイしたCloud Runサービス内で、Cloud Storageの削除をするので、
サービスアカウントで書き込み権限を追加する。

gsutil acl ch -u gcr-cleaner@${PROJECT_ID}.iam.gserviceaccount.com:W \
gs://asia.artifacts.${PROJECT_ID}.appspot.com

recursiveオプションを使う場合は、参照権限も必要。
gcloud projects add-iam-policy-binding "${PROJECT_ID}" \
--member "serviceAccount:gcr-cleaner@${PROJECT_ID}.iam.gserviceaccount.com" \
--role "roles/browser"

デプロイしたCloud Runサービスを呼び出すサービスアカウントを作成
まずはサービスアカウントを作成。
gcloud iam service-accounts create "gcr-cleaner-invoker" \
--project "${PROJECT_ID}" \
--display-name "gcr-cleaner-invoker"

次に、デプロイしたCloud Runサービスの「Cloud Run起動元」権限を付与。
gcloud run services add-iam-policy-binding "gcr-cleaner" \
--project "${PROJECT_ID}" \
--platform "managed" \
--region "us-central1" \
--member "serviceAccount:gcr-cleaner-invoker@${PROJECT_ID}.iam.gserviceaccount.com" \
--role "roles/run.invoker"

Cloud SchedulerでHTTPジョブを作成
まずはGAEを作成。Firebaseを利用している場合はスキップでOK。
gcloud app create \
--project "${PROJECT_ID}" \
--region "us-central" \
--quiet
次に、Cloud Schedulerを作成する。
--scheduleや--time-zoneは好きなように変更。
以下は、日本時間の毎週土曜の0時0分に実行する例
# 対象リポジトリのパス
export REPO="asia.gcr.io/${PROJECT_ID}/gcf"
# デプロイしたCloud RunのURLを取得:
export SERVICE_URL=$(gcloud run services describe gcr-cleaner --project "${PROJECT_ID}" --platform "managed" --region "us-central1" --format 'value(status.url)')
# Cloud Schedulerを作成
gcloud scheduler jobs create http "gcrclean-myimage" \
--project ${PROJECT_ID} \
--description "Cleanup ${REPO}" \
--uri "${SERVICE_URL}/http" \
--message-body "{\"repos\":[\"${REPO}\"]}" \
--oidc-service-account-email "gcr-cleaner-invoker@${PROJECT_ID}.iam.gserviceaccount.com" \
--schedule "0 0 * * 6" \
--time-zone="Asia/Tokyo"

--message-bodyや--scheduleなどは、
GCPコンソールからでも操作できるので、
変更などはそっちからのほうが便利。

あとはジョブを実行してみて、うまく削除されてたらOK(*´ω`*)
注意点
gcr-cleanerの仕組みとして、タグがないイメージを削除する形なので、
すでにタグをなにかつけていると削除されない。
その場合は、あらかじめタグを削除しておくか、
tag_filter_anyなどで削除対象を指定しておく必要がある。
合わせて、keepオプションで、残しておく数を指定することもできる。
具体的な処理は、pkg/gcrcleaner/cleaner.goのshouldDelete ()あたり。
流れとしては、以下の感じ。
- 更新時間が所定の時間以下の場合は、false
- タグがない場合は、true
- tagFilterにマッチした場合は、true
- それ以外は、false
tag_filter_anyなどが未設定の場合は、
tagFilterにTagFilterNullが渡されるが、常にfalseを返すよう。
今までは、$COMMIT_SHAをタグにしてたけど、
leastを利用するように変更した。。
- name: docker
id: Push
args:
- push
- - "$_GCR_HOSTNAME/$PROJECT_ID/$_SERVICE_NAME:$COMMIT_SHA"
+ - "$_GCR_HOSTNAME/$PROJECT_ID/$_SERVICE_NAME:latest"
以上!! これで毎週勝手に削除してくれるように(*´ω`*)