GCP Secret Managerの料金は何で決まる?|versionの破棄で減らす

鍵の付いたタグが積み上がって棒グラフが伸びる左側と、中身のない点線のタグが並ぶ右側を矢印でつないだ図。文字は GCP Secret Manager、What Drives the Cost、Disabled: Billed、Destroyed: Free データパイプライン

はじめに

GCP Secret Manager の料金が何で決まるのかを、実際に費用が増えた経験をもとに解説します。保管の費用は version の数で決まるので、version を追加し続ける処理は破棄まで作らないと費用が増え続けます。

Secret Manager は、API キーやトークンなどの秘密情報を保管する Google Cloud のサービスです。値を更新するたびに version(コンソールの表示は「バージョン」)という単位で新しい値が積まれます。

本記事のまとめ

  • 課金の対象は、active な version、アクセス操作、ローテーション通知の 3 つである
  • 無効にした version にも課金される。課金を止めるには破棄する
  • 「最新 N 版だけ残す」設定は見つからなかったので、呼び出す側で破棄する処理を書いた
  • 破棄しても一覧に行は残るので、確かめるときは行数ではなくステータスを見る

GCP Secret Managerの料金は3つの項目で決まる

課金されるのは、active な version の数、アクセス操作の回数、ローテーション通知の回数です。単価は変わることがあるので、公式の料金ページで確認してください。

項目課金数え方
active な version(有効と無効)されるlocation ごとの version 数。active だった期間に比例する
破棄した versionされない–
アクセス操作(値の読み取り)される操作の回数
管理操作されない–
ローテーション通知される通知の回数

表の語は、次の意味です。

  • active: version が有効または無効の状態にあることである
  • location: 値を保存するリージョンである
  • 管理操作: シークレットの作成や破棄、version の状態の変更などである
  • ローテーション通知: シークレットの更新時期を Pub/Sub で知らせるメッセージである

無料枠は請求先アカウント単位で数える

無料枠はプロジェクトごとではなく、請求先アカウントごとに合算します。枠は毎月リセットされます。

  • active な version: 6 版
  • アクセス操作: 10,000 回
  • ローテーション通知: 3 回

レプリケーションの設定でversionの数え方が変わる

version は location ごとに数えますが、自動レプリケーションは 1 location として数えます。レプリケーションは、値を複数のリージョンに複製する設定です。保存先を自分で選ぶ設定にすると、選んだ location の数だけ課金の対象が増えます。

versionは実行した回数だけ増えて247版になった

version を追加するだけで破棄していなかったので、1 つのシークレットが 247 版まで増えました。対象は、Cloud Run Job が 1 日 2 回更新する refresh token です。refresh token はアクセス用のトークンを取り直すための値で、私が使っている API では更新のたびに入れ替わります。

Secret Manager の version 一覧。337 から 335 が有効、334 以下が破棄で、作成日時が 13 時と 9 時で交互に並ぶ
破棄の処理を入れたあとの一覧(2026 年 11 月に撮影)。最新 3 版が有効で、古い version は破棄済み。破棄しても行は一覧に残る。プロジェクト番号とシークレット名を含む上部は切り落とした

増え方は実行した回数のとおりで、作成日時も実行時刻に沿って並んでいます。掃除する処理がリポジトリに 1 つも無かったので、増える一方でした。

実際の費用は、2026 年 9 月 7 日から 13 日までの 7 日間で 576 円、月に換算すると約 2,470 円でした。これはクレジット適用前の金額で、プロジェクト全体の Secret Manager の費用です。このシークレット以外の version も含みます。

247 版のうち 244 版を破棄し、最新 3 版を残しました。失敗は 0 件です。そのあと、課金エクスポート(利用料の明細を BigQuery に書き出す機能)で週ごとの費用を比べ、Secret Manager の費用が下がったことを確かめました。

version の保管費用は実行頻度とは別に発生します。実行回数を減らせば増える速さは落ちますが、すでに溜まった version の費用は破棄するまで減りません。

無効にしてもSecret Managerの課金は止まらない

課金が止まるのは破棄したときだけで、無効にしただけでは課金が続きます。公式ドキュメントのversion の状態の説明にも、有効と無効の両方に課金し、破棄済みには課金しないと書かれています。

状態値の中身課金
有効読めるされる
無効残っている(読めないだけ)される
破棄削除済みされない
有効、無効、破棄の予定は課金され、破棄済みは課金されないことを示す図。有効から無効へ進む経路、猶予なしで破棄済みへ直接進む経路、猶予ありで破棄の予定を経由する経路がある
猶予を設定しなければ、有効な version はすぐ破棄済みになる。設定すると破棄の予定を経由する。その間は無効の状態になるので、課金の側に置いた。公式の記述からの整理で、請求では確かめていない(筆者作図)

私は次の 3 つを思い違いしていました。

  • 無効にすれば課金が止まると思っていた。上の表のとおり止まらない
  • version_destroy_ttl を設定すれば古い version が自動で消えると思っていた。実際は、破棄を要求してから消えるまでの猶予を決める設定である
  • 「最新 N 版だけ残す」を Secret Manager の設定でできると思っていた。調べた時点では、件数で区切る設定は見つからなかった

2 つ目の猶予は費用を下げる機能ではありません。公式ドキュメントによると、猶予を設定した version は破棄を要求すると無効になり、期間が過ぎてから破棄されます。無効の version は課金の対象なので、費用が下がる時期はその分遅くなると考えられます。猶予中の課金は請求では確かめていません。設定しなければ、破棄はすぐに実行されます。

破棄は取り消せません。誤って消したときに戻す余地が要るなら猶予を設定し、費用を優先するなら設定しない、という判断になります。

古いversionは呼び出す側で破棄する

件数で区切る設定が見つからなかったので、有効な version を新しい順に並べ、残す数より古いものを破棄する処理を書きました。手作業で破棄するなら、次のコマンドです。

gcloud secrets versions destroy SECRET_VERSION_ID --secret=SECRET_ID

処理に組み込むと次の形になります。実際に動かしているコードから、該当するメソッドを抜き出しました。

def prune_secret_versions(self, secret: str, keep: int = KEEP_ENABLED_VERSIONS) -> list[str]:
    if keep < 1:
        raise ValueError("keep must be >= 1 so that the newest version always survives.")

    parent = self.secret_resource_name(secret)
    enabled = [
        version
        for version in self._client.list_secret_versions(request={"parent": parent})
        if version.state == secretmanager.SecretVersion.State.ENABLED
    ]

    enabled.sort(key=lambda version: version.create_time, reverse=True)

    destroyed: list[str] = []
    for version in enabled[keep:]:
        self._client.destroy_secret_version(request={"name": version.name})
        destroyed.append(version.name)
    return destroyed

このメソッドは、新しい version の保存に成功したあとで呼びます。破棄を先にすると、保存が失敗したときに使える値を失うためです。また、対象は有効な version だけなので、すでに無効にした version は残り、課金も続きます。

残す数は 3 版にしました。入れ替わるトークンでは使用済みの値に戻せないので 1 版でも足りますが、誤操作への猶予として残しています。静的な API キーのように古い値へ戻す可能性があるなら、残す数は別に考えてください。

破棄の権限はバージョンのマネージャーで渡す

version を追加するだけのロールでは破棄できないので、実行するサービスアカウントのロールを変える必要があります。ロールは権限をまとめたもので、サービスアカウントはプログラムが使う Google Cloud の ID です。公式ドキュメントは、version の破棄に roles/secretmanager.secretVersionManager を案内しています。

ロールの一覧。シークレット アクセサーとシークレット バージョンのマネージャーの 2 つが並び、継承の欄は空である
Job のサービスアカウントに付けた 2 つのロール。継承の欄が空なので、シークレット単位の付与と分かる。プリンシパルとプロジェクト ID の列は切り落とした

破棄だけを持つ事前定義ロールは無く、カスタムロールを作らない方針にしているので、追加・破棄・無効化・有効化をまとめて持つこのロールを選びました。値を読む権限は含まれないので、読むためのロールとは分かれたままです。付与する範囲も、プロジェクト全体ではなくシークレット 1 つに絞りました。

破棄できているかはステータスで確かめる

破棄しても version の行は一覧に残るので、行数ではなくステータスの列を見てください。行数だけを見ると、消えていないように見えます。確かめる段階では、ほかにも 2 つ引っかかりました。

テストが通っても掃除が呼ばれていないことがある

テストは 14 件とも通っていたのに、掃除の処理は一度も呼ばれていませんでした。テスト用の差し替え部品に掃除のメソッドが無く、そこで出た AttributeError を except Exception が受け止めていたためです。

掃除の失敗で本来の処理を止めたくないので、広い例外の受け方そのものは残しました。そのうえで差し替え部品にメソッドを足し、呼ばれた順番を確かめるテストに直しています。広く例外を受ける箇所では、テストがその経路を通っているかを別に確かめてください。

動作確認でversionが増えることがある

入れ替わるトークンでは、疎通を見るために使うだけで新しい version が 1 つ増えます。そこで破棄の前は API を呼ばず、Job の実行履歴と version の作成時刻を突き合わせました。

Job の実行    開始    09-17 04:00:01 UTC
version 247  作成    09-17 04:00:22 UTC

成功した実行の開始から 21 秒後に新しい version ができているので、最新の version はその実行が書いたものと判断できます。対象のトークンを使わずに確かめられます。

まとめ

GCP Secret Manager の保管の費用は active な version の数で決まり、無効にしても止まりません。私の環境では、破棄していなかったために 1 つのシークレットが 247 版まで増えました。

version を追加する処理を持っているなら、まず一覧でステータスごとの version の数を確かめてください。増え続けているなら、古い version を破棄する処理と、破棄できるロールを用意します。

なお、単価、無料枠の数量、課金の対象、コンソールの構成は変わります。実際に設定するときは、件数で区切る設定の有無も含めて、最新を公式ドキュメントで確認してください。