Canary Deployment in Kubernetes #1: Gitlab CI

Utilizzeremo Gitlab CI e GitOps manuale per implementare e utilizzare il Canary deployment in Kubernetes

Canary Deployment in Kubernetes #1: Gitlab CI

Articoli di questo ciclo:

Effettueremo il Canary deployment manualmente attraverso GitOps e la creazione/modifica delle risorse principali di Kubernetes. Questo articolo è principalmente destinato a introdurre come funziona il Canary deployment in Kubernetes, poiché ci sono metodi più efficienti di automazione che discuteremo nei prossimi articoli.


Canary Deployment in Kubernetes #1: Gitlab CI

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

Deployment Canary

Con la strategia Canary, gli aggiornamenti vengono applicati inizialmente solo a una parte degli utenti. Attraverso il monitoraggio, i dati dai log, i test manuali o altri canali di feedback, il rilascio viene testato prima di essere applicato a tutti gli utenti.

Kubernetes Deployment (rolling update)

La strategia predefinita per il Kubernetes Deployment è il rolling-update, dove viene eseguito un certo numero di pod con nuove versioni delle immagini. Se vengono creati senza problemi, i pod con le versioni precedenti delle immagini vengono terminati e nuovi pod vengono creati in parallelo.

GitOps

Utilizziamo GitOps in questo esempio, poiché noi:

  • utilizziamo Git come unica fonte di verità
  • utilizziamo Git Operations per la build e il deploy (nessun comando necessario tranne git tag/merge)

Esempio

Prendiamo una buona pratica: avere un repository per il codice delle applicazioni e uno per l'infrastruttura.

Repository per le applicazioni

Questa è una semplice API su Python+Flask, che restituisce una risposta in formato JSON. Creeremo un pacchetto tramite GitlabCI e caricheremo il risultato nel Gitlab Registry. Nel registry abbiamo due diverse versioni di release:

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

L'unica differenza tra di esse è la modifica del file JSON restituito. Utilizziamo questa applicazione per una visualizzazione massima e semplice di quale versione stiamo interagendo.

Repository infrastrutturale

In questo repository faremo il deploy tramite GitlabCI in Kubernetes, .gitlab-ci.yml si presenta nel seguente modo:

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

Per eseguirlo da solo avrai bisogno di un cluster, puoi utilizzare Gcloud:

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

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

È necessario fare un fork https://gitlab.com/wuestkamp/k8s-deployment-example-canary-infrastructure e creare una variabile KUBECONFIG in GitlabCI che conterrà la configurazione per l'accesso kubectl al tuo cluster.

Informazioni su come ottenere le credenziali per il cluster (Gcloud) possono essere lette qui.

Yaml infrastrutturale

Nel repository infrastrutturale abbiamo service:

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

E deployment in 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

E un altro deployment in 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

Nota che app-deploy attualmente non ha repliche definite.

Esecuzione del deployment iniziale

Per avviare il deployment iniziale, puoi avviare manualmente il pipeline GitlabCI nel ramo master. Dopo di che kubectl dovrebbe restituire quanto segue:

Canary Deployment in Kubernetes #1: Gitlab CI

Vediamo app il deployment con 10 repliche e app-canary con 0. C'è anche un LoadBalancer da cui possiamo accedere tramite curl l'IP esterno:

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

Canary Deployment in Kubernetes #1: Gitlab CI

Vediamo che la nostra applicazione di test restituisce solo “v1”.

Esecuzione del deploy Canary

Passo 1: rilasciare una nuova versione per una parte degli utenti

Abbiamo impostato il numero di repliche a 1 nel file deploy-canary.yaml e l'immagine della nuova versione:

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

Nel file deploy.yaml abbiamo cambiato il numero di repliche a 9:

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

Stiamo inviando queste modifiche nel repository da cui verrà eseguito il deploy (tramite GitlabCI) e alla fine vediamo:

Canary Deployment in Kubernetes #1: Gitlab CI

Il nostro Service punterà a entrambi i deploy, poiché entrambi hanno il selettore app. A causa della distribuzione casuale per impostazione predefinita in Kubernetes, dovremmo vedere risposte diverse su circa il 10% delle richieste:

Canary Deployment in Kubernetes #1: Gitlab CI

Lo stato attuale della nostra applicazione (GitOps, preso da Git come Single Source Of Truth) consiste nella presenza di due deployments con repliche attive, una per ogni versione.

~10% degli utenti si familiarize con la nuova versione e la testano involontariamente. È ora di controllare la presenza di errori nei log e nei dati di monitoraggio per identificare eventuali problemi.

Passo 2: rilasciare la nuova versione per tutti gli utenti

Abbiamo deciso che tutto è andato bene e ora dobbiamo distribuire la nuova versione a tutti gli utenti. Per farlo, aggiorniamo semplicemente deploy.yaml installando la nuova versione dell'immagine e impostando il numero di repliche a 10. In deploy-canary.yaml impostiamo il numero di repliche a 0. Dopo il deployment, il risultato sarà il seguente:

Canary Deployment in Kubernetes #1: Gitlab CI

In sintesi

Per me, avviare il deployment manualmente in questo modo aiuta a capire quanto possa essere semplice configurarlo con k8s. Poiché Kubernetes consente di aggiornare tutto tramite API, questi passaggi possono essere automatizzati tramite script.

Un'altra cosa da implementare è il punto di ingresso per il tester (LoadBalancer o tramite Ingress), attraverso il quale è possibile accedere solo alla nuova versione. Può essere utilizzato per una visualizzazione manuale.

Negli articoli successivi esploreremo altre soluzioni automatizzate che implementano la maggior parte di ciò che abbiamo fatto.

Leggi anche altri articoli nel nostro blog:

Fonte: habr.com

Acquista hosting affidabile per siti web con protezione DDoS, VPS VDS server 🔥 Acquista hosting affidabile per siti web con protezione DDoS, VPS VDS server | ProHoster