Objetivos

Al finalizar el tutorial el estudiante estará en capacidad de:

Pasos previos

En particular se utilizarán los siguientes recursos:

  1. Repositorio privado con la imagen de contenedor de la aplicación suma, el cual fue publicado en el tutorial Container Registry. Por favor realice ese tutorial antes de continuar con el desarrollo de esta guía.
  2. gcloud SDK para acceder a los servicios del proveedor Google Cloud Platform a partir de la consola. En caso de no tenerla instalada puede consultar el siguiente manual de instalación:https://cloud.google.com/sdk/docs/install
  3. Herramienta de control de Kubernetes, kubectl. En caso de no tenerla instalada puede consultar el siguiente manual de instalación:https://kubernetes.io/docs/tasks/tools/

Para los siguientes pasos se recomienda trabajar con un ambiente sin contenedoras en ejecución. Para ello puede destruir los despliegues y los servicios haciendo uso del comando delete:

kubectl delete all --all -n default
kubectl delete ingress <gateway-name>

Para este tutorial manejaremos el repositorio de calculadora-numeros usado en los tutoriales pasados, en caso de no tenerlo clonado aún, puede consultarlo en el siguiente enlace. Trabajaremos sobre rama feature/deployment-strategy, para ello cambie la rama del repositorio actual a la respectiva rama, para hacerlo ejecute en su terminal:

user@192 ~ % git checkout feature/deployment-strategy

Si ya se encuentra en esta rama, haga caso omiso al comando presentado anteriormente.

El despliegue mediante Rolling deployment es la estrategia de implementación predeterminada en Kubernetes. Si usted desea cambiar de versión una contenedora, kubernetes listará las contenedoras que se están ejecutando con la versión anterior e inicia un proceso de reemplazo uno por uno, sin tiempo de inactividad del clúster. Puede ver un ejemplo de cómo sucede el paso a paso en este link.

La actualización de pods usa una check de preparación para verificar si el nuevo pod está listo, antes de comenzar a reducir/eliminar progresivamente los pods con la versión anterior. Si hay un problema, puede detener una actualización y revertirla, sin detener todo el clúster.

Si se fija en el archivo k8s-service.yml de la carpeta suma, encontrará que está definido explícitamente, aunque como ya comentamos es la implementación predeterminada.

Modifique la uri de la imagen por la de su repositorio.

Hemos modificado el valor de réplicas a 2, para que sean más evidentes los cambios.

spec:
  replicas: 2
...
strategy:
    rollingUpdate:
      maxSurge: 2
      maxUnavailable: 1
    type: RollingUpdate

Los atributos allí expuestos corresponden a:

Si desea ajustar alguno de los dos parámetros, simplemente actualice el archivo YML de sus pods usando la imagen establecida de kubectl. Esto activará automáticamente el Rolling update.

Despliegue la aplicación en su cluster

user@192 ~ % kubectl apply -f service.yml

Revise el estado de sus pods y encontrará que hay dos réplicas

user@192 ~ % kubectl get pods                
NAME                                   READY   STATUS    RESTARTS   AGE
suma-7858bc9694-5mx6v                 1/1     Running   0          10s
suma-7858bc9694-wpdrw                 1/1     Running   0          10s

Cambie el valor de CPU en el archivo k8s-service.yml, en la línea 47, por 260m y ejecute nuevamente.

user@192 ~ % kubectl apply -f k8s-service.yml

Inmediatamente revise los pods y podrá ver cómo se encuentra recrea una a una las contenedoras. Recuerde que configuramos que máximo podríamos tener una no disponible.

user@192 ~ % kubectl get pods                
NAME                                   READY   STATUS    RESTARTS   AGE
suma-7858bc9694-5mx6v                  0/1     ContainerCreating   0          1s
suma-7858bc9694-wpdrw                  0/1     ContainerCreating   0          1s
suma-8696dbb58-zfrql                   1/1     Running             0          105s

Este es un patrón de implementación básico que en lugar de hacer el cambio de versiones de manera progresiva uno por uno, apaga todos los contenedores antiguos y los reemplaza por otros nuevos [1]. Se define en el archivo YML de la siguiente manera:

spec:
  replicas: 1
  selector:
       matchLabels:
           app: suma
  strategy:
    type: Recreate
...

Antes de aplicar el cambio valide los pods desplegados actualmente:

user@192 ~ % kubectl get pods                
NAME                                   READY   STATUS    RESTARTS   AGE
suma-7858bc9694-5mx6v                  1/1     Running   0          10s
suma-7858bc9694-wpdrw                  1/1     Running   0          10s

Cambie el valor de CPU en el archivo k8s-service.yml, en la línea 47, por 270m, posterior a esto ejecute el comando:

user@192 ~ % kubectl apply -f k8s-service.yml

Si ejecuta el comando kubectl get pods, podrá ver cómo el sistema no esperó a levantar un nuevo pod, este fue reemplazado directamente sin esperar a un posible "rolling" por un error al desplegar el nuevo. Luego de ejecutarlo podrá ver como el nuevo pod está corriendo hace 49 segundos (Este tiene el cambio de CPU que asignó en el punto anterior).

user@192 ~ % kubectl get pods                
NAME                            READY   STATUS              RESTARTS   AGE
suma-8696dbb58-68bj6            0/1     ContainerCreating   0          0s
suma-8696dbb58-l9qjf            0/1     ContainerCreating   0          0s

Esta estrategia escala porcentualmente el despliegue de pods, esta implementación es rápida pero con la compensación de un mayor riesgo al despliegue, al tolerar un cierto porcentaje de tiempo de inactividad entre sus nodos [1]. Para poder configurar este tipo de despliegue debe:

Esto se hace con el propósito de reemplazar rápidamente los contenedores, lo más rápido posible, al tiempo que garantiza una cantidad limitada de contenedores inactivos en un momento dado. Ajuste el archivo YML en la sección de strategy de la siguiente manera:

selector:
    matchLabels:
      app: suma
  strategy:
    rollingUpdate:
      maxSurge: 0
      maxUnavailable: 20%
    type: RollingUpdate
...   

Si ejecuta el comando kubectl get pods podrá ver cómo se inicializa una nueva instancia desde cero, eliminando el pod anterior hasta que la nueva esté desplegada, manejando cierto porcentaje de tiempo de inactividad entre los contenedores.

user@192 ~ % kubectl get pods                
NAME                            READY   STATUS              RESTARTS   AGE
suma-7858bc9694-mbjf4           0/1     ContainerCreating   0          0s
suma-7858bc9694-ns4s2           1/1     Running             0          5s
suma-8696dbb58-l9qjf            1/1     Terminating         0          3m59s

Si desea profundizar más en el tema puede consultar el siguiente link https://kubernetes.io/es/docs/concepts/workloads/controllers/deployment/

¡Éxitos en el desarrollo del tutorial y nos vemos en una próxima oportunidad!

[1] 5 kubernetes deployment strategies: Roll out like the pros: Spot (2021) Spot by NetApp. Available at: https://spot.io/resources/kubernetes-autoscaling/5-kubernetes-deployment-strategies-roll-out-like-the-pros/ (Accessed: November 26, 2022).