Migrar APIs de Kubernetes sin perder comentarios YAML ni el git blame
Las migraciones masivas de API en Kubernetes borran los comentarios del YAML y la autoría en git blame. Un mantenedor de herramientas de migración detalla cómo evitarlo con parseo CST.
Cada vez que Kubernetes retira una API, alguien tiene que tocar cientos de manifests. Las herramientas disponibles fallan casi siempre en el mismo punto: kubectl-convert deserializa el YAML y lo vuelve a escribir, con lo que se lleva por delante el 100% de los comentarios humanos y destroza la indentación; un reemplazo por regex arregla la línea de apiVersion y se rompe en cuanto el esquema cambia de forma, ya sea añadir spec.selector en un Deployment o reestructurar rutas y servicios de un Ingress. Y cuando un script automático toca 300 manifests, git blame le adjudica cada línea al bot que lanzó la migración. Quien firma el análisis se presenta como mantenedor de una herramienta open source de migración y explica cómo lo resuelve su motor.
El problema no es nuevo. Las deprecaciones se han ido acumulando versión a versión: extensions/v1beta1 en los Ingress con la 1.22, batch/v1beta1 en los CronJob con la 1.25, autoscaling/v2beta2 con la 1.26. Hay utilidades que auditan esto bien, Pluto entre ellas, pero son de solo lectura: detectan el manifiesto obsoleto y ahí se acaban, no arreglan nada en un repositorio de GitOps. La migración sigue siendo manual o, peor, un sed masivo.
Parsear el árbol, no el diccionario
La propuesta central es no deserializar el manifiesto a un diccionario o a JSON antes de tocarlo. En su lugar se analiza como árbol de sintaxis concreto (CST), de manera que la herramienta apunta al token escalar que quiere cambiar —pasar apiVersion: batch/v1beta1 a batch/v1— y los comentarios, las líneas en blanco y la indentación se quedan exactamente como estaban. El cambio queda en el diff, no la reformateada entera.
Plantillas de Helm y autoría en git blame
El segundo problema es específico de los repositorios GitOps: las plantillas de Helm viven en el control de versiones sin renderizar. Si se ejecuta helm template, se corrige la salida renderizada y se guarda, se pierde la lógica de la plantilla, que es justamente lo que se quería conservar. La solución descrita es una etapa de lexer que enmascara temporalmente los tags de plantilla de Go ({{ ... }}) como marcadores inertes durante el recorrido del AST, aplica la migración de API y reinyecta las expresiones byte a byte.
Para el historial, Git 2.23 y GitHub admiten ignorar commits de reformateo masivo. Basta con anotar el hash del commit de migración y apuntar la configuración a ese fichero:
git log -1 --format="%H # automated k8s migration" >> .git-blame-ignore-revs
git config blame.ignoreRevsFile .git-blame-ignore-revs
Con eso, git blame sigue mostrando al autor original de cada línea y no al proceso que la reescribió. El contexto institucional de por qué un manifiesto tiene un valor raro sobrevive a la migración, que es de lo que se trata cuando se salta de la 1.16 a la 1.32 de una tacada.
Conviene leerlo como lo que es: la explicación de técnicas por parte de alguien que mantiene una herramienta para ello. No hay nombre de producto, ni repositorio, ni comparativa independiente detrás, y el enfoque sirve igual para cualquier implementación propia que se monte sobre un parser de YAML con AST.
