前提
Google Cloudの Cloud Functions の第2世代ではデプロイする時には自動的に Artifact Registry にDockerイメージが作られます。
cloud.google.com
デプロイ時に自動的にDockerイメージを作ってくれるので利用者側では全然気にすることはないのですが、作られたイメージは消えないので頻繁にデプロイしているとDockerイメージが増えてArtifact Registryのストレージの費用が増えて気になっていました。
具体的にどれくらい費用かかっていたのかというと、週1回デプロイを1年間続けたらArtifact Registryだけで月1ドル前後かかるようになっていました。(Cloud Functions部分は無料枠におさまっているので0円)
業務だと全然無視していい費用感なんだけど個人プロダクトだと削りたかったので自動的に消す方法を仕込みました。
基本的にはTerraformでやる前提なので他の方法でやる場合には適宜読み替えてください。
TerraformでArtifact Registryの設定変更をするためには最初にimportする必要があります。
まずは適当なtfファイルに下記を書きます。
import {
id = "asia-northeast1/gcf-artifacts" TODO
to = google_artifact_registry_repository.gcf-artifacts
}
その後 terraform plan -generate-config-out=_generated.tf
のようにコマンドを実行すればimport結果が _generated.tf
に出力されます。
_generated.tf
の中身はこんな感じ。
resource "google_artifact_registry_repository" "gcf-artifacts" {
cleanup_policy_dry_run = true
description = "This repository is created and used by Cloud Functions for storing function docker images."
format = "DOCKER"
kms_key_name = null
labels = {}
location = "asia-northeast1"
mode = "STANDARD_REPOSITORY"
project = "XXXXXXXXXXXXXXX"
repository_id = "gcf-artifacts"
}
生成されたリソースを別のtfファイルに移動させれば_generated.tf
は削除していいです。
手順2. Artifact RegistryにCleanup Policyを適用する
Cloud FunctionsでしばらくデプロイしているとArtifact Registryのリポジトリは
のような構成になります。
そのためlatestタグだけ残して他は全部消すような Cleanup Policy のルールを適用します。
Terraformだと下記のようになります。
locals {
hex_chars = [for i in range(0, 16) : format("%x", i)]
}
resource "google_artifact_registry_repository" "gcf-artifacts" {
location = "asia-northeast1"
repository_id = "gcf-artifacts"
description = "This repository is created and used by Cloud Functions for storing function docker images."
format = "DOCKER"
mode = "STANDARD_REPOSITORY"
cleanup_policy_dry_run = false
cleanup_policies {
id = "keep-latest"
action = "KEEP"
condition {
tag_state = "TAGGED"
tag_prefixes = ["latest"]
}
}
cleanup_policies {
id = "delete-all-untagged"
action = "DELETE"
condition {
tag_state = "UNTAGGED"
}
}
cleanup_policies {
id = "delete-hex-prefix-tags"
action = "DELETE"
FIXME
condition {
tag_state = "TAGGED"
tag_prefixes = local.hex_chars
}
}
}
コメントにも書いてるけどCleanup Policyでは正規表現が使えないのでUUID形式のタグを消す部分はかなりの力技です...(UUIDで取りうるアルファベットはa〜fなのでlatestが消えずに済んでいる)
Terraform読めない人向けに一応 gcloud artifacts repositories list-cleanup-policies
コマンドの結果も載せておきます。
$ gcloud artifacts repositories list-cleanup-policies gcf-artifacts --location asia-northeast1
Listing items under project XXXXXXXXXXXXX, location asia-northeast1, repository gcf-artifacts.
Dry run is disabled.
[
{
"action": {
"type": "DELETE"
},
"condition": {
"tagState": "UNTAGGED"
},
"name": "delete-all-untagged"
},
{
"action": {
"type": "DELETE"
},
"condition": {
"tagPrefixes": [
"0",
"1",
"2",
"3",
"4",
"5",
"6",
"7",
"8",
"9",
"a",
"b",
"c",
"d",
"e",
"f"
],
"tagState": "TAGGED"
},
"name": "delete-hex-prefix-tags"
},
{
"action": {
"type": "KEEP"
},
"condition": {
"tagPrefixes": [
"latest"
],
"tagState": "TAGGED"
},
"name": "keep-latest"
}
]
他のソリューション
Artifact RegistryにCleanup Policyが導入されるまでは https://github.com/GoogleCloudPlatform/gcr-cleaner を使っていましたが、こっちはもうメンテされていないので基本的にはCleanup Policyを使うのがいいと思います。
とはいえgcr-cleanerは正規表現でタグ指定ができるのが便利なのでどうしても正規表現を使いたい場合にはこっちを使うことになりそう。(早くCleanup Policyでも正規表現対応されてほしい...)