Utilizzo di Istio+Kiali per avviare e visualizzare il Canary deployment

Articoli di questo ciclo
- (questo articolo)
- Canary Deployment utilizzando Jenkins-X Istio Flagger
Deployment Canary
Speriamo che tu abbia letto , dove spiegavamo brevemente cosa sono i Canary deployments e mostravamo come implementarli utilizzando le risorse standard di Kubernetes.
Istio
E presumiamo che leggendo questo articolo tu conosca già Istio. Se non lo sai, puoi leggere di lui .
Applicazione per test

Ogni pod contiene due container: la nostra applicazione e istio-proxy.
Utilizzeremo una semplice applicazione di test con pod frontend-nginx e backend in python. Il pod con nginx reindirizzerà semplicemente ogni richiesta al pod con backend e funzionerà come proxy. I dettagli possono essere consultati nei seguenti yaml:
Avvio dell'applicazione di test autonomamente
Se vuoi seguire il mio esempio e utilizzare questa applicazione di test da solo, vedi il .
Deployment iniziale
Quando avviamo il primo Deployment vediamo che i pod della nostra applicazione hanno solo 2 container ciascuno, il che significa che il sidecar di Istio è ancora in fase di implementazione:

E vediamo anche Istio Gateway Loadbalancer nel namespace istio-system:

Creazione del traffico
Utilizzeremo il seguente IP per generare traffico, che sarà ricevuto dai pod frontend e ridiretto ai pod backend:
while true; do curl -s --resolve 'frontend.istio-test:80:35.242.202.152' frontend.istio-test; sleep 0.1; done
Aggiungeremo anche frontend.istio-test al nostro file hosts.
Visualizzazione Mesh attraverso Kiali
Abbiamo installato un'applicazione di test e Istio insieme a Tracing, Grafana, Prometheus e Kiali (maggiori dettagli su ). Pertanto, possiamo utilizzare Kiali tramite:
istioctl dashboard kiali # admin:admin

Kiali visualizza il traffico attuale attraverso la Mesh
Come possiamo vedere, il 100% del traffico raggiunge il servizio frontend, quindi al pod frontend con etichetta v1, poiché utilizziamo un semplice proxy nginx che reindirizza le richieste al servizio backend, che a sua volta le reindirizza ai pod backend con etichetta v1.
Kiali funziona perfettamente con Istio e offre una soluzione 'out of the box' per la visualizzazione della Mesh. È semplicemente fantastico.
Deployment Canary
Il nostro backend ha già due deployment k8s, uno per v1 e uno per v2. Ora dobbiamo solo dire a Istio di reindirizzare una certa percentuale di richieste a v2.
Passo 1: 10%
E tutto ciò che dobbiamo fare è regolare il peso del VirtualService in :
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 
Vediamo che il 10% delle richieste è reindirizzato a v2.
Passo 2: 50%
E ora è sufficiente aumentarlo al 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 
Passo 3: 100%
Ora il deployment Canary può dirsi completato e tutto il traffico è reindirizzato a v2:

Testare Canary manualmente
Supponiamo che al momento stiamo inviando al backend v2 il 10% di tutte le richieste. Cosa succede se vogliamo testare manualmente v2 per assicurarci che tutto funzioni come previsto?
Possiamo aggiungere una regola di corrispondenza speciale basata sugli header HTTP:
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: 10Ora, utilizzando curl possiamo forzare la richiesta a v2 inviando l'intestazione:
![]()
Le richieste senza intestazione saranno ancora gestite con un rapporto di 1/10:

Canary per due versioni dipendenti
Ora consideriamo un caso in cui abbiamo la versione v2 sia per il frontend che per il backend. Per entrambi, abbiamo specificato che il 10% del traffico dovrebbe andare a v2:

Vediamo che il frontend v1 e v2 inoltrano entrambi il traffico nel rapporto di 1/10 verso il backend v1 e v2.
E se avessimo bisogno di inoltrare il traffico da frontend-v2 solo a backend-v2, poiché non è compatibile con v1? Per questo impostiamo un rapporto di 1/10 per il frontend, che controlla quale traffico va a backend-v2 utilizzando la corrispondenza per 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: 100Di conseguenza, otteniamo ciò di cui abbiamo bisogno:

Differenze rispetto all'approccio manuale Canary
In parte uno Abbiamo eseguito il deployment Canary manualmente, utilizzando anche due deployment k8s. In quel caso, gestivamo il rapporto delle richieste modificando il numero di repliche. Questo approccio funziona, ma presenta seri svantaggi.
Istio offre la possibilità di definire il rapporto delle richieste indipendentemente dal numero di repliche. Ciò significa, ad esempio, che possiamo utilizzare gli HPA (Horizontal Pod Autoscalers — scalabilità orizzontale dei pod) e non è necessario configurarlo in base allo stato attuale del deployment Canary.
Risultato
Istio funziona ottimamente e utilizzandolo insieme a Kiali otteniamo una combinazione molto potente. Il prossimo nel mio elenco di interessi è la combinazione di Spinnaker con Istio per l'automazione e l'analisi Canary.
Fonte: habr.com
