Vom folosi Gitlab CI și GitOps manual pentru implementarea și utilizarea Canary deployment-ului în Kubernetes

Articole din acest ciclu:
- (acest articol)
- Canary Deployment cu Istio
- Canary Deployment cu Jenkins-X Istio Flagger
Vom realiza Canary deployment manual prin GitOps și crearea/modificarea resurselor esențiale Kubernetes. Acest articol este destinat în special pentru a familiariza cititorii cu modul în care funcționează Canary deployment în Kubernetes, deoarece există metode mai eficiente de automatizare pe care le vom explora în articolele următoare.

Canary Deployment
În strategia Canary de actualizare, modificările sunt aplicate inițial doar pentru o parte a utilizatorilor. Prin monitorizare, date din jurnale, teste manuale sau alte canale de feedback, versiunea este testată înainte de a fi aplicată tuturor utilizatorilor.
Kubernetes Deployment (actualizare continuă)
Strategia implicită pentru Kubernetes Deployment este actualizarea continuă, unde un anumit număr de poduri cu noi versiuni de imagini sunt lansate. Dacă acestea sunt create fără probleme, podurile cu versiunile vechi ale imaginilor sunt terminate, iar noile poduri sunt create în paralel.
GitOps
Folosim GitOps în acest exemplu, deoarece:
- folosim Git ca sursă unică de adevăr
- folosim Git Operations pentru construire și implementare (nu sunt necesare comenzi, cu excepția git tag/merge)
Exemplu
Să adoptăm o bună practică — să avem un singur repo pentru codul aplicațiilor și unul pentru infrastructură.
Repozitoriu pentru aplicații
Aceasta este o API foarte simplă pe Python+Flask, care returnează un răspuns în format JSON. Vom construi pachetul prin GitlabCI și vom trimite rezultatul în Gitlab Registry. În registru avem două versiuni diferite de release-uri:
wuestkamp/k8s-deployment-example-app:v1wuestkamp/k8s-deployment-example-app:v2
Singura diferență dintre ele este modificarea fișierului JSON returnat. Folosim această aplicație pentru a vizualiza cât se poate de simplu cu ce versiune comunicăm.
Repozitoriu de infrastructură
În acest repo vom implementa prin GitlabCI în Kubernetes, .gitlab-ci.yml arată în următorul mod:
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
Pentru a-l rula local, aveți nevoie de un cluster, puteți folosi Gcloud:
gcloud container clusters create canary --num-nodes 3 --zone europe-west3-b
gcloud compute firewall-rules create incoming-80 --allow tcp:80Trebuie să faceți un fork și să creați o variabilă KUBECONFIG în GitlabCI, care va conține configurația de acces kubectl la clusterul dvs.
Despre cum să obțineți acreditivele pentru cluster (Gcloud) se poate citi .
Yaml de infrastructură
În repository-ul de infrastructură avem service:
apiVersion: v1
kind: Service
metadata:
labels:
id: app
name: app
spec:
ports:
- port: 80
protocol: TCP
targetPort: 5000
selector:
id: app
type: LoadBalancerȘi deployment în 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Și un alt deployment în 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: 100MiObservați că app-deploy nu are încă replici definite.
Executarea deployment-ului inițial
Pentru a iniția deployment-ul inițial, puteți rula manual pipeline-ul GitlabCI pe ramura master. După aceasta kubectl ar trebui să afișeze următoarele:

Vedem app deployment cu 10 replici și app-canary cu 0. De asemenea, există un LoadBalancer de pe care putem accesa prin curl prin IP-ul extern:
while true; do curl -s 35.198.149.232 | grep label; sleep 0.1; done

Observăm că aplicația noastră de testare returnează doar "v1".
Executarea deployment-ului Canary
Pasul 1: lansați o nouă versiune pentru o parte dintre utilizatori
Am setat numărul de replici la 1 în fișierul deploy-canary.yaml și imaginea noii versiuni:
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În fișierul deploy.yaml am schimbat numărul de replici la 9:
kind: Deployment
metadata:
name: app
spec:
replicas: 9
selector:
matchLabels:
id: app
...Facem push aceste modificări în repository-ul din care va fi lansat deployment-ul (prin GitlabCI) și observăm în final:

Serviciul nostru va indica ambele deployment-uri, deoarece ambele au selectorul app. Datorită distribuției aleatoare implicite în Kubernetes, ar trebui să vedem răspunsuri diferite la aproximativ 10% dintre cereri:

Starea actuală a aplicației noastre (GitOps, luată din Git ca sursă unică de adevăr) este că există două deployment-uri cu replici active, câte unul pentru fiecare versiune.
~10% dintre utilizatori se familiarizează cu noua versiune și o testează fără să vrea. Acum este timpul să verificăm erorile din jurnale și datele de monitorizare pentru a căuta probleme.
Pasul 2: lansați o nouă versiune pentru toți utilizatorii
Am decis că totul a decurs bine și acum trebuie să implementăm o nouă versiune pentru toți utilizatorii. Pentru aceasta, pur și simplu actualizăm deploy.yaml instalând o nouă versiune a imaginii și un număr de replici egal cu 10. În deploy-canary.yaml stabilim numărul de replici înapoi la 0. După desfășurare, rezultatul va fi următorul:

În concluzie
Pentru mine, lansarea desfășurării manual în acest mod ajută să înțeleg cât de ușor poate fi configurată prin k8s. Deoarece Kubernetes permite actualizarea totul prin API, acești pași pot fi automatizați prin scripturi.
Încă un lucru care trebuie implementat este punctul de intrare al testerului (LoadBalancer sau prin Ingress), prin care se poate accesa doar noua versiune. Aceasta poate fi folosită pentru vizualizare manuală.
În următoarele articole vom verifica alte soluții automatizate care implementează majoritatea a ceea ce am realizat.
Citiți și alte articole de pe blogul nostru:
Sursa: habr.com
