Despliegue Canary en Kubernetes #1: Gitlab CI

Usaremos Gitlab CI y GitOps manual para implementar y utilizar el despliegue Canary en Kubernetes

Despliegue Canary en Kubernetes #1: Gitlab CI

Artículos de este ciclo:

Realizaremos el despliegue Canary manualmente a través de GitOps y la creación/modificación de recursos básicos de Kubernetes. Este artículo está destinado principalmente a familiarizarse con el funcionamiento del despliegue Canary en Kubernetes, ya que hay maneras más efectivas de automatización que examinaremos en los siguientes artículos.


Despliegue Canary en Kubernetes #1: Gitlab CI

https://www.norberteder.com/canary-deployment/

Despliegue Canary

Con la estrategia Canary de actualización, primero se aplica solo para una parte de los usuarios. A través de monitoreo, datos de registros, pruebas manuales u otros canales de retroalimentación, se prueba el lanzamiento antes de aplicarlo a todos los usuarios.

Despliegue de Kubernetes (actualización progresiva)

La estrategia predeterminada para el despliegue de Kubernetes es la actualización progresiva, donde se ejecuta una cantidad determinada de pods con nuevas versiones de imágenes. Si se crean sin problemas, los pods con versiones antiguas de las imágenes se eliminan y se crean nuevos pods en paralelo.

GitOps

Utilizamos GitOps en este ejemplo, ya que:

  • usamos Git como única fuente de verdad
  • utilizamos operaciones de Git para construir y desplegar (no se necesitan comandos, excepto git tag/merge)

Ejemplo

Tomemos una buena práctica: tener un repositorio para el código de las aplicaciones y otro para la infraestructura.

Repositorio para aplicaciones

Es una API muy simple en Python+Flask que devuelve una respuesta en formato JSON. Construiremos el paquete a través de GitlabCI y subiremos el resultado al Registro de Gitlab. En el registro tenemos dos versiones diferentes de lanzamientos:

  • wuestkamp/k8s-deployment-example-app:v1
  • wuestkamp/k8s-deployment-example-app:v2

La única diferencia entre ellas es el cambio en el archivo JSON devuelto. Usamos esta aplicación para visualizar de manera simple con qué versión estamos interactuando.

Repositorio de infraestructura

En este repositorio desplegaremos a través de GitlabCI en Kubernetes, .gitlab-ci.yml se ve de la siguiente manera:

image: traherom/kustomize-docker

before_script:
   - printenv
   - kubectl version

stages:
 - deploy

deploy test:
   stage: deploy
   before_script:
     - echo $KUBECONFIG
   script:
     - kubectl get all
     - kubectl apply -f i/k8s

   only:
     - master

Para ejecutarlo por su cuenta necesitará un clúster, puede usar Gcloud:

gcloud container clusters create canary --num-nodes 3 --zone europe-west3-b

gcloud compute firewall-rules create incoming-80 --allow tcp:80

Necesita hacer un fork https://gitlab.com/wuestkamp/k8s-deployment-example-canary-infrastructure y crear una variable KUBECONFIG en GitlabCI, que contendrá la configuración para acceder kubectl a su clúster.

Sobre cómo obtener las credenciales para el clúster (Gcloud) puede leer aquí.

Yaml de infraestructura

En el repositorio de infraestructura tenemos un service:

apiVersion: v1
kind: Service
metadata:
 labels:
   id: app
 name: app
spec:
 ports:
 - port: 80
   protocol: TCP
   targetPort: 5000
 selector:
   id: app
 type: LoadBalancer

Y el deployment en deploy.yaml:

apiVersion: apps/v1
kind: Deployment
metadata:
 name: app
spec:
 replicas: 10
 selector:
   matchLabels:
     id: app
     type: main
 template:
   metadata:
     labels:
       id: app
       type: main
   spec:
     containers:
     - image: registry.gitlab.com/wuestkamp/k8s-deployment-example-app:v1
       name: app
       resources:
         limits:
           cpu: 100m
           memory: 100Mi

Y otro deployment en deploy-canary.yaml:

kind: Deployment
metadata:
 name: app-canary
spec:
 replicas: 0
 selector:
   matchLabels:
     id: app
     type: canary
 template:
   metadata:
     labels:
       id: app
       type: canary
   spec:
     containers:
     - image: registry.gitlab.com/wuestkamp/k8s-deployment-example-app:v2
       name: app
       resources:
         limits:
           cpu: 100m
           memory: 100Mi

Tenga en cuenta que app-deploy aún no tiene réplicas definidas.

Ejecución del despliegue inicial

Para iniciar el despliegue inicial, puede ejecutar el pipeline de GitlabCI manualmente en la rama maestra. Después de esto, kubectl debería mostrar lo siguiente:

Despliegue Canary en Kubernetes #1: Gitlab CI

Vemos app un deployment con 10 réplicas y app-canary con 0. También hay un LoadBalancer desde el cual podemos acceder a través de curl por IP externa:

while true; do curl -s 35.198.149.232 | grep label; sleep 0.1; done

Despliegue Canary en Kubernetes #1: Gitlab CI

Vemos que nuestra aplicación de prueba devuelve solo “v1”.

Ejecución del despliegue Canary

Paso 1: lanzar una nueva versión para parte de los usuarios

Hemos establecido el número de réplicas en 1 en el archivo deploy-canary.yaml y la imagen de nueva versión:

kind: Deployment
metadata:
 name: app-canary
spec:
 replicas: 1
 selector:
   matchLabels:
     id: app
     type: canary
 template:
   metadata:
     labels:
       id: app
       type: canary
   spec:
     containers:
     - image: registry.gitlab.com/wuestkamp/k8s-deployment-example-app:v2
       name: app
       resources:
         limits:
           cpu: 100m
           memory: 100Mi

En el archivo deploy.yaml hemos cambiado el número de réplicas a 9:

kind: Deployment
metadata:
 name: app
spec:
 replicas: 9
 selector:
   matchLabels:
     id: app
...

Estamos subiendo estos cambios al repositorio desde el cual se iniciará el despliegue (a través de GitlabCI) y vemos al final:

Despliegue Canary en Kubernetes #1: Gitlab CI

Nuestro Service apuntará a ambos deployments, ya que ambos tienen el selector app. Debido a la distribución aleatoria por defecto en Kubernetes, deberíamos ver diferentes respuestas en aproximadamente el 10% de las solicitudes:

Despliegue Canary en Kubernetes #1: Gitlab CI

El estado actual de nuestra aplicación (GitOps, tomado de Git como fuente única de verdad) es tener dos deployments con réplicas activas, uno para cada versión.

~10% de los usuarios se familiarizan con una nueva versión y la prueban inadvertidamente. Ahora es el momento de revisar los registros y los datos de monitoreo para detectar problemas.

Paso 2: lanzar una nueva versión para todos los usuarios

Decidimos que todo ha ido bien y ahora necesitamos desplegar la nueva versión para todos los usuarios. Para ello, simplemente actualizamos deploy.yaml instalando la nueva versión de la imagen y estableciendo el número de réplicas en 10. En deploy-canary.yaml estamos configurando el número de réplicas de nuevo en 0. Después del despliegue, el resultado será el siguiente:

Despliegue Canary en Kubernetes #1: Gitlab CI

Resumiendo

Para mí, realizar un despliegue manual de esta manera ayuda a entender lo fácil que se puede configurar con k8s. Dado que Kubernetes permite actualizar todo a través de API, estos pasos se pueden automatizar mediante scripts.

Otra cosa a implementar es un punto de entrada para el tester (LoadBalancer o a través de Ingress), a través del cual se puede acceder únicamente a la nueva versión. Esto puede ser utilizado para visualizarlo manualmente.

En los próximos artículos, revisaremos otras soluciones automatizadas que implementan la mayoría de lo que hemos hecho.

También lee otros artículos en nuestro blog:

Fuente: habr.com

Compra un hosting fiable para sitios web con protección contra DDoS, servidores VPS VDS 🔥 Compra un hosting fiable para sitios web con protección contra DDoS, servidores VPS VDS | ProHoster