👋

Artifact Registryのイメージを自動削除する「クリーンアップポリシー」を使ってみる

2023/08/28に公開

Artifact Registryの クリーンアップポリシーを利用すると、「期間」や「最新バージョン数」などの条件に基づいて、古いイメージを自動削除することができます。従来のGCRですとGCR Cleaner等のツールを自分で実行する必要があったので、これは非常に嬉しい機能です。

ただ、まだ登場したばかりの機能ということもあってか、ポリシーの設定方法や動作確認方法には若干癖があります。本記事では、実際にポリシーを設定する際の手順について簡単にまとめてみます。

なお、本記事ではDockerイメージレジストリとしての利用法を解説します。

ポリシーの適用単位

ポリシーを適用するのはArtifact Registryの「リポジトリ」単位となります。リポジトリ内には複数のパッケージ(Dockerで言うimage repository)を格納することができますが、ポリシーはリポジトリ内のすべてのパッケージに一律で適用されます。

一応、ポリシーの条件のpackageNamePrefixesを使うことで特定のパッケージのみにポリシーを適用することは可能ですが、そもそもひとつのリポジトリに適用できるポリシーは最大10個までとなっています。このため、ポリシーを適用したいグループごとにリポジトリを分割するのが無難です。

ポリシーの種類

クリーンアップポリシーは、以下の2種類のポリシーを最大10個まで組み合わせて構成します。

「削除」ポリシー

本機能の基本となるポリシーで、自動削除を行う対象とするイメージの条件を指定します。使用できる条件は以下のとおりです。

  • イメージにタグが付いているかどうか(tagState)
  • タグのプレフィックス(tagPrefixes)
  • パッケージ名のプレフィックス(packageNamePrefixes)
  • 一定期間を経過したイメージ(olderThan)
  • 一定期間内に作成されたイメージ(newerThan)

「保持」ポリシー

「保持」ポリシーは、上記の「削除」ポリシーで削除対象となったイメージのうち一部を保護する目的で使用します。したがって、保持ポリシーのみを設定しても効果がありませんので注意してください。

保持ポリシーに設定できる条件は基本的に「削除」ポリシーと同一ですが、それに加えて最新nバージョンの保持(mostRecentVersions)を設定することができます。なお、「最新nバージョン」のカウントはパッケージごとに行われます。

ポリシーの記述

例として、以下のようなポリシーを考えます。

  • タグなしイメージは常に削除
  • タグ付きイメージは過去10バージョンのみ保持
    • ただし、過去30日以内に作成されたイメージは10バージョンを超えても削除しない

ポリシーはJSON形式で記述し、ファイルに保存する必要があります。ここではexamplePolicy.jsonという名前のファイルに保存します。

[
  {
    "name": "clean-untagged",
    "action": {"type": "Delete"},
    "condition": {
      "tagState": "untagged"
    }
  },
  {
    "name": "clean-tagged-older-than-30-days",
    "action": {"type": "Delete"},
    "condition": {
      "tagState": "tagged",
      "olderThan": "30d"
    }
  },
  {
    "name": "keep-last-10",
    "action": {"type": "Keep"},
    "mostRecentVersions": {
      "keepCount": 10
    }
  }
]

注意する必要があるのが、バージョン数による条件の制御は保持ポリシーにしか使用することができないという点です。このため、今回は「期間」を削除ポリシーの条件に、「バージョン数」を保持ポリシーの条件に使用しています。

より詳しい条件の書き方に関しては、公式ドキュメントを参照してください。

https://cloud.google.com/artifact-registry/docs/repositories/cleanup-policy?hl=ja#create

dry-runによる動作確認

これでポリシーは完成しましたが、いきなりこれを使ってイメージを削除するのは若干不安があります。dry-runモードを使うことで、実際にイメージを削除することなくポリシーをテストできます。

監査ログの有効化

dry-runモードの動作結果を確認するには、事前に監査ログを有効化する必要があります。クリーンアップポリシーはBatchDeleteVersionsAPIを呼び出すので、「データ書き込み」ログを有効化します。

dry-runの実行

先程作成したポリシーファイルをdry-runモードで適用します。

gcloud artifacts repositories set-cleanup-policies [リポジトリ名] \
    --project=[プロジェクトID] \
    --location=[リージョンまたはマルチージョンロケーション] \
    --policy=examplePolicy.json \
    --dry-run

実行すると、実際に解釈されたポリシーが出力されます。

Updated repository [xxxxxxxx].
Dry run is enabled.
[
  {
    "action": {
      "type": "DELETE"
    },
    "condition": {
      "olderThan": "2592000s",
      "tagState": "TAGGED"
    },
    "name": "clean-tagged-older-than-30-days"
  },
  {
    "action": {
      "type": "DELETE"
    },
    "condition": {
      "tagState": "UNTAGGED"
    },
    "name": "clean-untagged"
  },
  {
    "action": {
      "type": "KEEP"
    },
    "mostRecentVersions": {
      "keepCount": 10
    },
    "name": "keep-last-10"
  }
]

デフォルト値が暗黙的に挿入された場合でもここで確認できます。

これで削除ポリシーを仮適用することができたのですが、紛らわしいのがdry-runのポリシーを適用してもすぐに削除(のシミュレーション)が実行されるわけではないという点です。ポリシーに基づく削除は数時間に1回程度の頻度で実行されているものと思われ、dry-runモードであっても削除が試行されるのは同程度の頻度となります[1]。このため、ポリシーを適用してから実際にBatchDeleteVersionsの監査ログが出るまではしばらく時間がかかります。(自分は最初この挙動を認識できておらず、監査ログが全く現れなくて焦りました)

監査ログの確認

しばらく時間を置くと、クリーンアップポリシーによるバッチ削除のログが出現します。
Cloud Loggingで以下のクエリで検索すると引っ掛けることができます。

protoPayload.serviceName="artifactregistry.googleapis.com"
protoPayload.methodName="google.devtools.artifactregistry.v1.ArtifactRegistry.BatchDeleteVersions"
protoPayload.request.@type="type.googleapis.com/google.devtools.artifactregistry.v1.BatchDeleteVersionsRequest"

削除されたイメージがあれば、以下のようなログエントリが引っかかります。

namesに削除されたイメージのパスとsha256ハッシュが格納されています。なお、タグ付きイメージの場合でもイメージタグは含まれないようなのでご注意ください。また、dry-runで実行している場合、実際にはイメージを削除していないことを示すためにvalidateOnly: trueというフラグが付与されています。

特定のイメージが削除されたかどうかを確認するには、上記のクエリに以下の条件を加えます。

protoPayload.request.names:"sha256:xxxxxxx"

no-dry-runによる適用

イメージが正しく削除できていることを確認したら、no-dry-runモードに切り替えてイメージが削除されるようにします。

gcloud artifacts repositories set-cleanup-policies [リポジトリ名] \
    --project=[プロジェクトID] \
    --location=[リージョンまたはマルチージョンロケーション] \
    --policy=examplePolicy.json \
    --no-dry-run

まとめ

以上、クリーンアップポリシーを用いてイメージを自動削除する方法を見てきました。

dry-runの実行方法などに若干難はありますが、非常に便利な機能ですのでぜひ活用していきたいところです。

脚注
  1. 1日1回しかテストできないのは流石にキツい・・・ので、Googleさん何とかお願いします🙏 ↩︎

Discussion