本文へ移動

Kubernetes v1.37 で Storage Version Migration が GA、既定で有効

Kubernetes v1.37 では StorageVersionMigration オブジェクトを作るだけで既存リソースの再書き込みが走る。旧 API 版の削除前や鍵ローテーション後の再書き込みを自前で回しているチーム向け。

Kubernetes v1.37 で、ストレージバージョン移行(Storage Version Migration、SVM)が GA になった。storagemigration.k8s.io/v1 の StorageVersionMigration API と、それを処理するコントロールプレーン側のコントローラが、v1.37 のすべてのクラスタで既定で有効になっている。出典は Kubernetes 公式ブログに2026年8月31日付で載った Michael Aspinwall(Google)の告知だ。

既定で有効といっても、クラスタを上げた瞬間に保存済みのリソースが書き換わるわけではない。移行が始まるのは StorageVersionMigration オブジェクトを作ったときだ。告知が使いどころとして挙げるのは、CRD から古い API バージョンを落とす場面と、保存時暗号化の鍵をローテーションする場面だ。この作業を kubectl get と kubectl replace を回すスクリプトや out-of-tree の kube-storage-version-migrator でこなしてきたチームは、v1.37 のクラスタなら同じことを標準 API でできる。

「v1alpha1 を落とせない」が起きる仕組み

Kubernetes は API リソースを、そのリソースに定められたストレージバージョンの表現で保存する。告知の説明では、保存済みのリソースを最新のストレージバージョンに揃えるには、リソースそのものを書き換える(mutation)しかない。ストレージバージョンを変えたいときに面倒が起きるのはここに原因がある。

典型例が CRD のバージョン整理だ。v1alpha1 を落として v1beta1 と v1 だけにしたいとき、v1 を新しいストレージバージョンに指定しただけでは足りない。以後の書き込みは v1 で保存されるが、既存のリソースは v1alpha1 や v1beta1 のまま残りうる。ストレージ上のすべてのリソースが書き直されるまで、CRD の .status.storedVersions から v1alpha1 を外すことも、serving を止めることも安全にはできない。

もう一つが保存時暗号化と鍵ローテーションだ。暗号化を設定しても、鍵を替えても、既存のリソースは API サーバー経由で書き直されるまで平文のまま、あるいは古い鍵で暗号化されたまま残る。

これまで管理者と CRD 作者は、手書きの kubectl get / kubectl replace スクリプトか、out-of-tree の kube-storage-version-migrator を入れて強制的に書き直してきた。告知はこのやり方を「面倒で、間違いやすく、監視しにくい(訳)」と評している。

v1.37 で組み込みになったもの

やることは宣言的な StorageVersionMigration オブジェクトを一つ作るだけだ。コントロールプレーンに組み込まれた StorageVersionMigrator コントローラがこのオブジェクトを監視し、対象 API の既定のストレージバージョンへ既存リソースを移行する。

告知の例は、crontabs.example.com という CRD のストレージバージョンを v1 に更新した後で、古いバージョンのまま保存されているリソースを移行するものだ。

apiVersion: storagemigration.k8s.io/v1
kind: StorageVersionMigration
metadata:
  name: crontabs-migration
spec:
  resource:
    group: example.com
    resource: crontabs
kubectl apply -f crontabs-migration.yaml

例で spec.resource に書いているのは group と resource だけで、移行元や移行先のバージョンは書いていない。移行先はその API の既定のストレージバージョンに決まる。

Succeeded を見てから storedVersions を確かめる

進捗はコントローラが StorageVersionMigration オブジェクトの status に書き込む。

kubectl get storageversionmigration.storagemigration.k8s.io/crontabs-migration -o yaml

成功すると Succeeded 条件が True になる。告知に載っている成功時の status は次の形だ。

status:
  conditions:
  - type: Running
    status: "False"
    lastUpdateTime: "2026-08-02T10:05:00Z"
    reason: StorageVersionMigrationInProgress
  - type: Succeeded
    status: "True"
    lastUpdateTime: "2026-08-02T10:05:00Z"
    reason: StorageVersionMigrationSucceeded

Succeeded が True なら、そのリソースのすべてのインスタンスが現在のストレージバージョンで保存されていると見なせる。CRD の場合はここで .status.storedVersions を見る。移行後は優先バージョンだけが残っているはずで、古いバージョンが残っていれば移行中に CRD が更新されたことを意味する。その場合は移行をやり直してから、古いストレージバージョンの廃止に進む。

.status.storedVersions をコントローラが更新するのか、管理者が手で更新するのかは、告知には書かれていない。「更新されていなければ移行中に CRD が変更された」という書き方は自動更新を示唆するが、明記ではない。どちらであっても、移行後に storedVersions を自分で確かめる手順は省かないほうがいい。

CRD のマニフェストに同梱できる

StorageVersionMigration は標準の宣言的 API なので、CRD 作者は CRD の更新と同じマニフェストに移行を入れられる。告知の例では、v1 に storage: true を付けた CustomResourceDefinition と、上と同じ StorageVersionMigration を --- で並べている。

apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
  name: crontabs.example.com
spec:
  group: example.com
  # Updated versions list where v1 has storage: true
  ...
---
apiVersion: storagemigration.k8s.io/v1
kind: StorageVersionMigration
metadata:
  name: crontabs-migration
spec:
  resource:
    group: example.com
    resource: crontabs

Operator を配布している側から見ると、「CRD を更新したら利用者側で migrator を回してもらう」という手順書の一項目をマニフェストに畳み込める。前節のとおり、移行中に CRD が更新されると古いバージョンが storedVersions に残る。同梱したからといって、移行後の確認まで省けるわけではない。

自前スクリプトや out-of-tree migrator を使っているなら

v1.37 のクラスタには、同じ目的の API とコントローラが既定で入っている。out-of-tree の kube-storage-version-migrator を運用している場合、v1.37 に上げたクラスタではこの組み込み版が使える。ただし out-of-tree 版の今後の扱いや、両方を同時に動かした場合の挙動は告知には書かれていない。フィーチャーゲートの名前や無効化の可否も書かれていないので、有効・無効を明示的に切り替えたい場合は別途の確認が要る。

CRD の旧バージョンを落とす作業に組み込み版を使うなら、順番はこうなる。

  1. CRD の versions で v1 に storage: true を付けて適用する
  2. spec.resource に group と resource を書いた StorageVersionMigration を作る
  3. Succeeded 条件が True になるのを待つ
  4. .status.storedVersions が優先バージョンだけになっていることを確かめる。古いバージョンが残っていれば手順2からやり直す
  5. その後で古いバージョンの serving を止め、CRD から落とす

鍵ローテーション後の再書き込みも同じ API で起こせると告知は位置づけているが、載っているマニフェスト例は CRD のものだけだ。コアグループのリソースを対象にするときの spec.resource の書き方は、この告知だけでは分からない。まずは検証クラスタで CRD 一つを対象に、Succeeded と storedVersions の動きを見てから本番に持ち込むのが無難だ。SIG API Machinery は採用後のフィードバックを Slack の #sig-api-machinery チャンネルで受け付けている。

出典 種別について