Introducción

Si administrás un cluster de Kubernetes con CRDs que arrastran versiones v1alpha1 o v1beta1 en sus .status.storedVersions, probablemente ya viviste el momento en que querés deprecar una API vieja pero no podés hacerlo porque todavía hay objetos serializados en ese esquema dentro de etcd. Hasta la versión 1.36, resolver eso implicaba escribir scripts de kubectl get + kubectl replace sobre cada namespace, o desplegar el componente externo kube-storage-version-migrator y rezar para que no se cortara a mitad de la migración. Con Kubernetes v1.37, ese problema tiene una solución declarativa, nativa y activada por defecto.

La migración de storage version (SVM) ahora es un controlador del plano de control que observa objetos StorageVersionMigration y reescribe automáticamente los recursos almacenados en versiones obsoletas hacia la storage version activa. No requiere herramientas externas, no necesita que el administrador recorra namespace por namespace, y su estado es observable desde kubectl. Para los equipos de seguridad que rotan claves de encriptación en reposo, esto cierra una brecha concreta: recursos que quedaban sin cifrar bajo la nueva clave hasta que alguien los tocara.

Qué ocurrió

El SIG API Machinery de Kubernetes graduó la API storagemigration.k8s.io/v1 y su controlador asociado a General Availability en la release v1.37. Esto significa que el componente ya no requiere flags experimentales, no tiene feature gate desactivable y se instancia automáticamente en todo cluster que despliegue el control plane de v1.37. Antes de esta graduación, la funcionalidad existía como Alpha desde v1.27 y pasó por Beta en v1.30, con correcciones iterativas en el manejo de conflictos de concurrencia, timeouts en migraciones masivas y actualización del campo .status.storedVersions del CRD.

El anuncio oficial se publicó el 31 de agosto de 2026 en el blog de Kubernetes. El equipo de SIG API Machinery confirmó que el controlador cubre tanto recursos nativos como Custom Resources, y que la migración es idempotente: si se interrumpe por un restart del control plane o un eviction del pod del controlador, retoma desde donde quedó sin duplicar escrituras ni dejar inconsistencias en etcd.

Impacto para DevOps / Infraestructura / Cloud / Seguridad

Desde la perspectiva operativa, el cambio más directo es que eliminás un componente externo del cluster. Si hoy tenés el kube-storage-version-migrator desplegado como un Deployment adicional en kube-system, podés eliminarlo tras la actualización a v1.37. Eso reduce superficie de ataque (un pod menos con permisos de get, list, update sobre recursos de todo el cluster) y simplifica el runbook de actualización.

Para equipos de seguridad, el impacto concreto está en la encriptación en reposo y la rotación de claves. Cuando rotás una EncryptionConfiguration en etcd, los objetos ya persistidos no se re-encifran bajo la nueva clave hasta que se reescriben a través del API server. Sin SVM, esa reescritura dependía de scripts ad-hoc que podían dejar miles de objetos sin cifrar durante horas o días. Con el controlador nativo, creás un StorageVersionMigration por cada grupo de recursos, monitoreás el progreso desde el status, y confirmás que la migración terminó antes de dar por completada la rotación.

Para operadores de CRDs en producción (operadores de bases de datos, service meshes, plataformas internas), la capacidad de bundlear la migración junto con el upgrade del CRD reduce el riesgo de que un administrador aplique la nueva definición de la CRD pero olvide migrar los recursos existentes, quedando con un estado mixto donde v1alpha1 y v1 coexisten en storage.

Detalles técnicos

La API storagemigration.k8s.io/v1 define un único tipo: StorageVersionMigration. El control plane instancia un controlador que hace watch sobre estos objetos y, al detectar uno nuevo, itera sobre todos los recursos del spec.resource especificado, leyendo cada objeto y reescribiéndolo para que el API server lo persista con la storage version actual. El manifest mínimo es:

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

El campo spec.resource apunta al recurso objetivo. El controlador no necesita que le indiques de qué versión viene: identifica automáticamente los objetos almacenados con esquemas distintos a la storage version activa del grupo.

Para verificar el progreso:

kubectl get storagemigrations.storagemigration.k8s.io -A
kubectl get storagemigrations.storagemigration.k8s.io crontabs-example-com-migration -o yaml

Un estado exitoso se manifiesta como:

status:
conditions:
– type: Succeeded
status: «True»
reason: MigrationSucceeded
message: «migration completed successfully»

Si tras una migración exitosa el CRD todavía muestra v1alpha1 en .status.storedVersions, eso indica que el CRD se modificó durante la migración (alguien agregó o removió una versión de API mientras el controlador trabajaba). En ese caso, la migración debe reintentarse antes de deprecar la versión vieja. El controlador no borra entradas de .status.storedVersions por sí solo; esa limpieza sigue siendo responsabilidad del operador que actualiza el CRD.

El controlador opera con un rate limit interno para no saturar el API server en clusters con millones de objetos. En clusters grandes (más de 500k recursos por tipo), la migración completa puede tomar varias horas. El timeout por objeto individual y el batch size son configurables vía flags del control-plane-controller-manager, aunque los valores por defecto cubren la mayoría de los escenarios productivos.

Qué deberían hacer los administradores y equipos técnicos

Primero, confirmá la versión exacta del cluster: kubectl version –short debe mostrar v1.37.x. Si todavía estás en v1.36 o anterior, el controlador no existe y necesitás el componente externo.

Segundo, auditá los CRDs del cluster para identificar recursos con storage versions obsoletas:

kubectl get crds -o jsonpath='{range .items[*]}{.metadata.name}{«\t»}{.status.storedVersions}{«\n»}{end}’

Si algún CRD lista más de una versión en storedVersions y alguna de ellas no coincide con la storage designada, ese CRD tiene recursos que necesitan migración.

Tercero, creá un StorageVersionMigration por cada recurso afectado. Si gestionás los CRDs vía Helm o Kustomize, agregá el manifest de migración como un recurso post-install o post-upgrade dentro del mismo chart. Así, cada vez que un operador actualice el CRD, la migración se dispara automáticamente.

Cuarto, si usás encriptación en reposo, después de aplicar una nueva EncryptionConfiguration y reiniciar el API server, creá migraciones para los recursos sensibles (Secrets, ConfigMaps con datos de configuración) y verificá que el status llegue a Succeeded antes de considerar la rotación como completada.

Quinto, remové el kube-storage-version-migrator externo si lo tenías desplegado. Verificá que no haya RBAC residuals:

kubectl get clusterrolebinding | grep storage-version-migrator
kubectl delete clusterrolebinding kube-storage-version-migrator

Conclusión

La graduación de SVM a GA en v1.37 no agrega una feature nueva al cluster, pero elimina una clase de deuda operativa que arrastraban los equipos desde que existen los CRDs con múltiples versiones. El paso de un script manual propenso a errores a un controlador declarativo con status observable cambia la ecuación de riesgo: la migración ahora es auditable, idempotente y parte del ciclo de vida normal del cluster. Para los equipos que rotan claves de cifrado o deprecian versiones de API con regularidad, este es el momento de incorporar el flujo de migración al runbook estándar y verificar que no queden recursos huérfanos en esquemas obsoletos.

Fuentes

  • https://kubernetes.io/blog/2026/08/31/kubernetes-v1-37-storage-version-migration-ga/

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *