Brug af Istio+Kiali til at køre og visualisere Canary deployment

Artikler i denne cyklus
- (denne artikel)
- Canary Deployment ved hjælp af Jenkins-X Istio Flagger
Canary Deployment
Vi håber, at du har læst , hvor vi kort forklarede, hvad Canary deployments er, og viste, hvordan man implementerer det ved hjælp af de standard Kubernetes-ressourcer.
Istio
Og vi antager, at når du læser denne artikel, allerede ved, hvad Istio er. Hvis ikke, kan du læse om det .
Testapplikation

Hver pod indeholder to containere: vores applikation og istio-proxy.
Vi vil bruge en simpel testapplikation med pods frontend-nginx og backend på python. Pod'en med nginx vil bare omdirigere hver anmodning til pod'en med backend og fungere som proxy. Detaljer kan ses nærmere i de følgende yaml-filer:
Kør testapplikationen selv
Hvis du vil følge mit eksempel og bruge denne testapplikation selv, se .
Oprindelig Deployment
Når vi starter det første Deployment, ser vi, at vores applikations pods kun har 2 containere, hvilket betyder, at Istio sidecar lige nu kun implementeres:

Og vi ser også Istio Gateway Loadbalancer i namespace istio-system:

Oprettelse af trafik
Vi vil bruge følgende IP for at generere trafik, som vil blive modtaget af frontend pods og omdirigeret til backend pods:
while true; do curl -s --resolve 'frontend.istio-test:80:35.242.202.152' frontend.istio-test; sleep 0.1; done
Vi vil også tilføje frontend.istio-test til vores hosts-fil.
Vis Mesh gennem Kiali
Vi har installeret testapplikationen og Istio sammen med Tracing, Grafana, Prometheus og Kiali (se nærmere på ). Derfor kan vi bruge Kiali via:
istioctl dashboard kiali # admin:admin

Kiali visualiserer den aktuelle trafik gennem Mesh
Som vi ser, modtager 100% af trafikken frontend servicen, derefter til frontend pod'en med label v1, da vi bruger en simpel nginx-proxy, der omdirigerer anmodninger til backend servicen, der igen omdirigerer dem til backend pods med label v1.
Kiali fungerer fremragende sammen med Istio og tilbyder en out-of-the-box løsning til visualisering af Mesh. Simpelthen fantastisk.
Canary Deployment
Vores backend har allerede to k8s deployments, en til v1 og en til v2. Nu skal vi blot fortælle Istio at omdirigere en bestemt procentdel af anmodningerne til v2.
Trin 1: 10%
Og det eneste, vi skal gøre, er at justere vægten af VirtualService i :
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: backend
namespace: default
spec:
gateways: []
hosts:
- "backend.default.svc.cluster.local"
http:
- match:
- {}
route:
- destination:
host: backend.default.svc.cluster.local
subset: v1
port:
number: 80
weight: 90
- destination:
host: backend.default.svc.cluster.local
subset: v2
port:
number: 80
weight: 10 
Vi ser, at 10% af anmodningerne omdirigeres til v2.
Trin 2: 50%
Og nu er det let at øge det til 50%:
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: backend
namespace: default
spec:
...
- destination:
host: backend.default.svc.cluster.local
subset: v1
port:
number: 80
weight: 50
- destination:
host: backend.default.svc.cluster.local
subset: v2
port:
number: 80
weight: 50 
Trin 3: 100%
Nu kan Canary-udrulningen betragtes som afsluttet, og al trafik omdirigeres til v2:

Manuel test af Canary
Lad os antage, at vi i øjeblikket sender 10% af alle anmodninger til backend v2. Hvad hvis vi ønsker at teste v2 manuelt for at sikre, at alt fungerer som forventet?
Vi kan tilføje en speciel match-regel baseret på HTTP-overskrifter:
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: backend
namespace: default
spec:
gateways: []
hosts:
- "backend.default.svc.cluster.local"
http:
- match:
- headers:
canary:
exact: "canary-tester"
route:
- destination:
host: backend.default.svc.cluster.local
subset: v2
port:
number: 80
weight: 100
- match:
- {}
route:
- destination:
host: backend.default.svc.cluster.local
subset: v1
port:
number: 80
weight: 90
- destination:
host: backend.default.svc.cluster.local
subset: v2
port:
number: 80
weight: 10Nu kan vi bruge curl til at tvinge en anmodning til v2 ved at sende overskriften:
![]()
Anmodninger uden overskrift vil stadig blive håndteret med forholdet 1/10:

Canary for to afhængige versioner
Nu ser vi på et tilfælde, hvor vi har version v2 både for frontend og backend. For begge har vi angivet, at 10% af trafikken skal gå til v2:

Vi ser, at frontend v1 og v2 begge videresender trafik i forholdet 1/10 til backend v1 og v2.
Hvad hvis vi skulle videresende trafik fra frontend-v2 kun til backend-v2, fordi den ikke er kompatibel med v1? Til dette vil vi indstille 1/10-forholdet for frontend, der styrer, hvilken trafik der går til backend-v2 ved hjælp af match baseret på sourceLabels :
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: backend
namespace: default
spec:
gateways: []
hosts:
- "backend.default.svc.cluster.local"
http:
...
- match:
- sourceLabels:
app: frontend
version: v2
route:
- destination:
host: backend.default.svc.cluster.local
subset: v2
port:
number: 80
weight: 100Som resultat får vi det, vi har brug for:

Forskelle fra den manuelle Canary-tilgang
I første del udførte vi Canary deployment manuelt, samtidig med at vi brugte to k8s deployments. Der styrede vi forholdet mellem anmodninger ved at ændre antallet af replikaer. Denne tilgang fungerer, men har alvorlige ulemper.
Istio giver mulighed for at definere forholdet mellem anmodninger uden at tage højde for antallet af replikaer. Det betyder for eksempel, at vi kan bruge HPAs (Horizontal Pod Autoscalers) og ikke behøver at konfigurere det i henhold til den aktuelle tilstand af Canary-deploy.
Resultat
Istio fungerer fremragende, og når vi bruger det sammen med Kiali, får vi en meget kraftfuld kombination. Næste punkt på min interesse liste er kombinationen af Spinnaker med Istio til automatisering og Canary-analyse.
Kilde: habr.com
