Kubernetes9 min de lectura

Migración a Kubernetes: un plan verificable de cutover y rollback

Un método práctico para migrar workloads a Kubernetes por oleadas, validar el comportamiento real y conservar una salida segura si producción falla.

David González
David GonzálezCEO · Cloud y DevOps
Diagrama editorial de una plataforma Kubernetes con componentes conectados

Una migración a Kubernetes no se vuelve segura porque el manifiesto pase una validación YAML o porque el primer Pod llegue a Running. Termina cuando la aplicación atiende tráfico real dentro de sus objetivos, los datos siguen siendo correctos, el equipo puede operarla y existe una salida practicable si el comportamiento empeora.

El error habitual es tratar el cutover como el último paso de un proyecto de infraestructura. En realidad, es una decisión de riesgo que conecta aplicación, datos, red, identidad, observabilidad y operación. Si uno de esos elementos no tiene criterio de aceptación, el cambio depende de intuiciones durante la ventana de producción.

Esta guía propone un plan por puertas de decisión. Cada puerta exige evidencia antes de avanzar. No presupone EKS, AKS, GKE, OKE, OpenShift ni un proveedor concreto.

1. Define la unidad de migración antes de elegir la oleada

“Migrar la aplicación” suele ocultar varias unidades distintas:

  • proceso web, workers y tareas programadas;
  • base de datos, colas, cachés y almacenamiento de objetos;
  • DNS, certificados, ingress y dependencias externas;
  • secretos, identidades de workload y permisos cloud;
  • dashboards, alertas, logs, trazas y runbooks;
  • pipelines de build, despliegue y reversión.

La primera oleada debe ser suficientemente representativa para descubrir incompatibilidades, pero con un radio de impacto controlable. Un servicio sin estado que use la misma identidad, red y observabilidad que las cargas críticas suele enseñar más que una aplicación de laboratorio aislada.

Campo Evidencia necesaria
Propietario Persona que acepta comportamiento y riesgo
Dependencias Entradas, salidas, DNS, puertos, certificados y terceros
Estado Datos persistentes, consistencia, RPO y RTO
Perfil CPU, memoria, concurrencia, arranque y apagado
Operación SLI/SLO, alertas, runbook y escalado
Cambio Ventana, estrategia de tráfico y punto de no retorno

Puerta 1: no entra en una oleada ninguna carga sin propietario, dependencias conocidas y criterio de aceptación.

2. Valida compatibilidad contra el clúster real

Un manifiesto válido para un clúster no tiene por qué funcionar en otro. Cambian las versiones servidas de la API, admission policies, StorageClasses, IngressClasses, controladores, identidad, DNS, CNI y políticas de seguridad.

Antes de desplegar:

# Usa el esquema y las políticas del clúster destino
kubectl apply --server-side --dry-run=server -f k8s/

# Revisa qué puede hacer la identidad de la aplicación
kubectl auth can-i --as=system:serviceaccount:payments:api \
  --list --namespace=payments

kubectl get storageclass
kubectl get ingressclass
kubectl get crd

La guía oficial de APIs obsoletas permite comprobar recursos que el destino ya no sirve. kubectl auth can-i consulta la capa de autorización mediante SelfSubjectRulesReview, según la documentación de autorización.

El dry-run de servidor no demuestra que una imagen pueda descargarse, que el CSI pueda montar un volumen, que el DNS externo resuelva ni que exista conectividad hacia una dependencia privada. Esas condiciones necesitan pruebas dentro del destino.

Puerta 2: manifiestos aceptados por el API server, permisos mínimos comprobados y dependencias de plataforma resueltas.

3. Haz que el workload diga cuándo puede recibir tráfico

Running describe el estado del contenedor. No garantiza que la aplicación haya cargado configuración, conectado con sus dependencias o calentado sus cachés.

Kubernetes usa la readinessProbe para decidir si un Pod debe recibir tráfico de un Service. Una startupProbe retrasa las sondas de readiness y liveness hasta que el arranque termina, según la documentación oficial de probes.

Ejemplo orientativo: sustituye REPLACE_ME por el digest real de tu imagen e implementa los endpoints de salud indicados. Los valores de recursos y tiempos necesitan validación en tu entorno.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: payments-api
spec:
  replicas: 3
  selector:
    matchLabels:
      app: payments-api
  minReadySeconds: 30
  progressDeadlineSeconds: 600
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxUnavailable: 0
      maxSurge: 1
  template:
    metadata:
      labels:
        app: payments-api
    spec:
      terminationGracePeriodSeconds: 45
      containers:
        - name: api
          image: registry.example/payments-api@sha256:REPLACE_ME
          ports:
            - containerPort: 8080
          startupProbe:
            httpGet: { path: /health/startup, port: 8080 }
            periodSeconds: 5
            failureThreshold: 24
          readinessProbe:
            httpGet: { path: /health/ready, port: 8080 }
            periodSeconds: 5
            failureThreshold: 2
          resources:
            requests: { cpu: 250m, memory: 256Mi }
            limits: { memory: 512Mi }
---
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
  name: payments-api
spec:
  minAvailable: 2
  selector:
    matchLabels:
      app: payments-api

Las contrapartidas importan:

  • maxUnavailable: 0 necesita capacidad para el Pod adicional; sin margen, el rollout puede bloquearse.
  • Una readiness superficial admite tráfico antes de tiempo; una que dependa de todos los terceros puede retirar todas las réplicas durante un fallo externo.
  • Los requests influyen en el scheduling y deben partir de mediciones. Kubernetes explica la relación en Resource Management for Pods and Containers.
  • Un PodDisruptionBudget limita disrupciones voluntarias concurrentes. No evita fallos de nodo ni garantiza disponibilidad por sí solo, como aclara la guía de disrupciones.

Puerta 3: arranque, readiness, apagado y recursos probados bajo carga representativa.

4. Separa el rollback de aplicación del rollback de datos

kubectl rollout undo puede restaurar una revisión de un Deployment. No revierte una migración de esquema, mensajes consumidos, escrituras producidas en el destino ni cambios de un servicio externo.

Cambio Reversión posible Condición
Imagen Volver al digest anterior Contrato de datos compatible
Configuración Restaurar versión anterior Secretos y dependencias válidos
Tráfico Devolver peso al origen Origen sano y sincronizado
Esquema No asumir reversión automática Cambios compatibles N/N+1
Datos escritos Reconciliar o restaurar Procedimiento probado contra RPO/RTO

Para bases de datos, favorece cambios expand/contract: añade estructuras compatibles, despliega código capaz de convivir con ambas versiones, migra o reconcilia datos y elimina lo antiguo en una entrega posterior. El punto de no retorno debe estar escrito; puede ser el inicio de escrituras exclusivas en el nuevo sistema, no el cambio de DNS.

Los VolumeSnapshot representan instantáneas de volúmenes, según la documentación de almacenamiento. No conviertas esa capacidad en una promesa de consistencia de aplicación: una base de datos puede requerir coordinación, backup lógico, replicación o mecanismos propios. La prueba útil es una restauración completa y medida contra el RPO/RTO.

Puerta 4: rollback ensayado hasta el último punto reversible y tratamiento explícito de las escrituras posteriores.

5. Decide el cutover con señales de usuario

CPU, memoria y Pods disponibles son señales necesarias, pero no responden si el servicio funciona para el cliente. Define antes de la ventana:

  • tasa de éxito del recorrido principal;
  • latencia por percentil;
  • errores por clase, no solo total de 5xx;
  • backlog o retraso de workers;
  • consistencia de datos;
  • saturación de dependencias;
  • una comprobación sintética desde fuera del clúster.

Establece tres criterios: avance, pausa y rollback.

Ventana de observación: 30 minutos por escalón
Avance: éxito y latencia dentro del objetivo; sin divergencia de datos
Pausa: degradación sin superar el límite acordado
Rollback: incumplimiento sostenido, pérdida de datos o error sin diagnóstico
Escalones: tráfico interno -> 5% -> 25% -> 50% -> 100%

Los porcentajes y tiempos no son universales. Deben reflejar volumen, estacionalidad y capacidad para detectar una regresión. Con poco tráfico, cinco minutos pueden no producir una muestra útil; en una operación crítica, esperar treinta puede ser demasiado.

Puerta 5: dashboards, consultas y responsables listos antes de enviar tráfico.

6. Mantén el origen operable durante la estabilización

Blue/green solo facilita el rollback si el entorno anterior permanece sano y compatible. Apagarlo inmediatamente después del 100% elimina la principal ventaja del patrón.

Durante la estabilización:

  • congela cambios no relacionados;
  • conserva imágenes y configuración por digest o versión;
  • registra quién puede ordenar pausa y rollback;
  • distingue origen y destino en logs y trazas;
  • vigila colas, cronjobs y procesos que podrían ejecutarse dos veces;
  • documenta cuándo deja de ser válido volver atrás.

Kubernetes controla disponibilidad durante un rolling update con maxUnavailable y maxSurge, descritos en Deployments. Eso protege el rollout dentro de un clúster. Una migración entre entornos sigue necesitando un mecanismo externo de tráfico y una política explícita de datos.

Puerta 6: el 100% de tráfico abre el periodo de estabilización; no cierra la migración.

7. Cierra con una prueba operativa

Antes de retirar el origen, el equipo receptor debería poder:

  • desplegar y revertir sin ayuda del equipo de migración;
  • localizar logs, métricas y trazas de una petición;
  • drenar un nodo respetando disponibilidad;
  • renovar certificados y credenciales;
  • recuperar un dato o volumen desde backup;
  • explicar capacidad, coste y próximos límites;
  • ejecutar el runbook de una dependencia caída.

Las topology spread constraints permiten repartir réplicas entre zonas o nodos, pero deben alinearse con la topología real y la capacidad disponible.

Puerta 7: operación aceptada, restauración demostrada y deuda residual registrada con propietario.

Checklist de go/no-go

  • La oleada tiene propietario técnico y de negocio.
  • Dependencias, certificados, DNS, identidad y egress están comprobados.
  • El API server del destino acepta los manifiestos.
  • Probes, recursos, apagado y distribución se han probado.
  • El plan distingue aplicación, esquema y datos.
  • El origen sigue disponible durante la ventana de rollback.
  • Los criterios de avance, pausa y rollback son observables.
  • Existe una persona autorizada para detener el cambio.
  • Backups y restauración cumplen el objetivo acordado.
  • El equipo receptor puede desplegar, diagnosticar y revertir.

Si una casilla crítica depende de “lo veremos durante la ventana”, todavía no hay un plan de migración: hay una apuesta.

La migración correcta reduce incertidumbre en cada oleada

Kubernetes puede estandarizar despliegues y operación, pero no elimina las decisiones sobre datos, dependencias y responsabilidad. Un buen plan usa la primera oleada para convertir incógnitas en evidencia y hacer que cada cambio posterior sea más predecible.

Antes de ejecutar, también conviene responder si Kubernetes es la plataforma adecuada. La guía cuándo no migrar a Kubernetes cubre ese paso. Si la decisión ya está tomada, el objetivo no es “mover Pods”: es construir un cutover observable, reversible y operable.

Consulta el enfoque de migración Cloud y Kubernetes de Nubyron para convertir inventario, dependencias y restricciones en oleadas verificables.