Rolling updates

Un rolling update (actualización continua) es una estrategia de despliegue en Kubernetes que permite actualizar las aplicaciones (normalmente los Pods dentro de un Deployment) de manera gradual y sin tiempo de inactividad (downtime). En lugar de reemplazar todos los Pods existentes al mismo tiempo, Kubernetes actualiza los Pods uno por uno (o en pequeños grupos), asegurándose de que siempre haya una cantidad mínima de Pods funcionando para mantener el servicio disponible mientras se realiza la actualización.

¿Cómo funciona un rolling update?

  1. Creación de nuevos Pods: Cuando realizas un cambio en la configuración de un Deployment (por ejemplo, actualizando la imagen de la aplicación), Kubernetes crea nuevos Pods con la nueva versión de la imagen o configuración.

  2. Reemplazo gradual: Kubernetes irá eliminando los Pods antiguos (con la versión anterior) uno por uno (o en grupos pequeños, dependiendo de la configuración), mientras va creando los nuevos Pods. De esta manera, siempre habrá Pods disponibles para manejar el tráfico y mantener el servicio activo.

  3. Monitoreo de disponibilidad: Kubernetes monitorea la salud de los nuevos Pods antes de destruir más Pods antiguos. Si detecta que los nuevos Pods no están funcionando correctamente, puede pausar la actualización, permitiéndote solucionar problemas sin interrumpir completamente el servicio.

  4. Control de velocidad de actualización: Puedes controlar cómo se lleva a cabo la actualización especificando parámetros como:

    • maxUnavailable: El número máximo o porcentaje de Pods que pueden estar fuera de servicio durante la actualización.
    • maxSurge: El número máximo de Pods adicionales que se pueden ejecutar temporalmente para manejar el tráfico mientras los nuevos Pods están siendo creados.

Ejemplo de un Deployment con un rolling update:

Cuando defines un Deployment, Kubernetes automáticamente usa la estrategia de RollingUpdate a menos que especifiques otra cosa. Aquí hay un ejemplo de cómo se configura un Deployment con la estrategia de rolling update:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
spec:
  replicas: 4
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxUnavailable: 1
      maxSurge: 1
  template:
    metadata:
      labels:
        app: my-app
    spec:
      containers:
      - name: my-app-container
        image: my-app-image:v2

En este ejemplo:

  • maxUnavailable: 1: Durante la actualización, puede haber un máximo de 1 Pod que no esté disponible en cualquier momento.
  • maxSurge: 1: Kubernetes puede crear un Pod adicional temporalmente (es decir, 5 Pods en total) mientras elimina uno de los Pods antiguos, asegurando que el servicio no sufra tiempo de inactividad.

Beneficios de un rolling update:

  • Sin downtime: Mantiene la aplicación disponible durante la actualización.
  • Actualización segura: Permite monitorear los nuevos Pods y pausar la actualización en caso de que algo salga mal.
  • Control de velocidad: Puedes ajustar el ritmo al que se despliegan los nuevos Pods y se eliminan los antiguos, lo cual es útil para grandes despliegues.

Ejemplo práctico:

Supón que tienes una aplicación con 4 réplicas (Pods), y decides actualizar la imagen del contenedor de v1 a v2. Con un rolling update:

  • Kubernetes creará un nuevo Pod con la versión v2 mientras sigue sirviendo tráfico con los 4 Pods v1.
  • Una vez que el nuevo Pod está en funcionamiento, eliminará un Pod de la versión v1.
  • Repetirá el proceso hasta que todos los Pods antiguos hayan sido reemplazados por Pods nuevos de la versión v2.

Alternativas:

Si no quieres usar un rolling update, también puedes optar por otras estrategias de despliegue como Recreate, que elimina todos los Pods antiguos de una vez y luego crea los nuevos (aunque esto provoca downtime).

En resumen, el rolling update es la estrategia predeterminada y recomendada en Kubernetes para hacer actualizaciones de manera segura y eficiente, manteniendo el servicio siempre disponible para los usuarios.

Ejercicio

Creamos el yaml

deploy.yml

apiVersion: apps/v1 # i se Usa apps/v1beta2 para versiones anteriores a 1.9.0
kind: Deployment
metadata:
  name: nginx-d
  labels:
    estado: "1"
spec:
  selector:   #permite seleccionar un conjunto de objetos que cumplan las condicione
    matchLabels:
      app: nginx
  replicas: 10 # indica al controlador que ejecute 2 pods
  strategy:
     type: RollingUpdate
  template:   # Plantilla que define los containers
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.7.9
        ports:
        - containerPort: 80

Corremos el deploy

kubectl apply -f deploy.yml

Revisamos el historial de rollout :

kubectl rollout history deploy nginx-d

Veremos algo asi:

❯ kubectl rollout history deploy nginx-d 
deployment.apps/nginx-d 
REVISION  CHANGE-CAUSE
1         <none>

REVISION 1 es porque es el primer historico que tenemos que se refiere a la creacion inicial.

Si en el archivo deploy.yml modificamos la version de la imagen de nginx y ejecutamos el apply , dispararemos un rollupadate. y veremos algo como esto:

❯ kubectl rollout history deploy nginx-d
deployment.apps/nginx-d 
REVISION  CHANGE-CAUSE
1         <none>
2         <none>

Podemos ver los detalles de las imagenes en cada REVISION con

kubectl rollout history deploy nginx-d --revision=2 


deployment.apps/nginx-d with revision #2
Pod Template:
  Labels:	app=nginx
	pod-template-hash=7d7d489dc5
  Containers:
   nginx:
    Image:	nginx:1.17.8
    Port:	80/TCP
    Host Port:	0/TCP
    Environment:	<none>
    Mounts:	<none>
  Volumes:	<none>
  Node-Selectors:	<none>
  Tolerations:	<none>

Si vemos los replica set vemos que se movieron al nuevo hash. osea al nuevo update.

❯ kubectl get rs
NAME                 DESIRED   CURRENT   READY   AGE
nginx-d-75fd5cdd7    0         0         0       7m20s
nginx-d-7d7d489dc5   10        10        10      2m53s

Rolling back

kubectl rollout undo deployment nginx-d --to-revision=1

Si hacemos :

kubectl rollout history deploy nginx-d

Veremos:

deployment.apps/nginx-d 
REVISION  CHANGE-CAUSE
2         <none>
3         <none>

Lo que hizo es mover el 1 a un nuevo revision.