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?
-
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.
-
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.
-
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.
-
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 Podsv1
. - 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.