Użycie Istio+Kiali do uruchamiania i wizualizacji wdrożenia Canary

Artykuły z tej serii
- (ten artykuł)
- Wdrożenie Canary z użyciem Jenkins-X Istio Flagger
Canary Deployment
Mamy nadzieję, że czytaliście , w której krótko wyjaśniliśmy, co to są wdrożenia Canary oraz pokazaliśmy, jak je zrealizować za pomocą standardowych zasobów Kubernetes.
Istio
Zakładamy, że czytając ten artykuł, już wiecie, czym jest Istio. Jeśli nie, możecie przeczytać o nim .
Aplikacja do testów

Każdy pod zawiera dwa kontenery: naszą aplikację i istio-proxy.
Użyjemy prostej aplikacji testowej z podami frontend-nginx i backend w Pythonie. Pod z nginx będzie po prostu przekazywał każde żądanie do podu z backendem i działał jako proxy. Szczegóły można znaleźć w poniższych plikach yaml:
Uruchomienie aplikacji testowej samodzielnie
Jeśli chcesz podążać moim przykładem i używać tej aplikacji testowej samodzielnie, zobacz .
Początkowe wdrożenie
Przy uruchamianiu pierwszego wdrożenia widzimy, że pody naszej aplikacji mają po dwa kontenery, co oznacza, że Istio sidecar dopiero zaczyna być wdrażany:

Widzimy również Istio Gateway Loadbalancer w przestrzeni nazw istio-system:

Generowanie ruchu
Będziemy używać następującego adresu IP, aby wygenerować ruch, który będzie przyjmowany przez pody frontendowe i przekazywany do podów backendowych:
while true; do curl -s --resolve 'frontend.istio-test:80:35.242.202.152' frontend.istio-test; sleep 0.1; done
Dodamy również frontend.istio-test do naszego pliku hosts.
Podgląd Mesh przez Kiali
Zainstalowaliśmy aplikację testową oraz Istio razem z Tracing, Grafana, Prometheus i Kiali (więcej informacji znajdziesz w ). W związku z tym możemy korzystać z Kiali przez:
istioctl dashboard kiali # admin:admin

Kiali wizualizuje bieżący ruch przez Mesh
Jak widzimy, 100% ruchu trafia na usługę frontend, a następnie na pod frontendu z etykietą v1, ponieważ używamy prostego proxy nginx, które przekazuje żądania na usługę backendową, która z kolei kieruje je do backendowych podów z etykietą v1.
Kiali działa doskonale z Istio i zapewnia gotowe rozwiązanie do wizualizacji Mesh. Po prostu wspaniale.
Canary Deployment
Nasz backend już ma dwa wdrożenia k8s, jedno dla v1 i jedno dla v2. Teraz musimy po prostu powiedzieć Istio, aby przekierowywało określony procent żądań na v2.
Krok 1: 10%
A wszystko, co musimy zrobić, to dostosować wagę VirtualService w :
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 
Widzimy, że 10% zapytań przekierowano na v2.
Krok 2: 50%
A teraz wystarczy zwiększyć to do 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 
Krok 3: 100%
Teraz wdrożenie Canary można uznać za zakończone, a cały ruch jest przekierowany na v2:

Ręczne testowanie Canary
Załóżmy, że teraz wysyłamy na backend v2 10% wszystkich zapytań. Co, jeśli chcemy ręcznie przetestować v2, aby upewnić się, że wszystko działa zgodnie z oczekiwaniami?
Możemy dodać specjalną regułę dopasowania opartą na nagłówkach 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: 10Teraz używając curl możemy wymusić żądanie v2 wysyłając nagłówek:
![]()
Żądania bez nagłówka będą nadal zarządzane w proporcji 1/10:

Canary dla dwóch zależnych wersji
Teraz rozważymy scenariusz, w którym mamy wersję v2 zarówno dla frontend, jak i backend. Dla obu wskazaliśmy, że 10% ruchu powinno iść do v2:

Widzimy, że frontend v1 i v2 oba kierują ruch w proporcji 1/10 na backend v1 i v2.
A co, jeśli musielibyśmy kierować ruch z frontend-v2 tylko na backend-v2, ponieważ nie jest on kompatybilny z v1? W tym celu ustalimy proporcję 1/10 dla frontend, która kontroluje, jaki ruch trafia na backend-v2, używając zgodności według 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: 100W efekcie otrzymujemy to, czego potrzebujemy:

Różnice w porównaniu do ręcznego podejścia Canary
W pierwszej części Ręcznie przeprowadzaliśmy wdrożenie Canary, również używając dwóch wdrożeń k8s. Tam zarządzaliśmy proporcją zapytań, zmieniając liczbę replik. Takie podejście działa, ale ma poważne wady.
Istio umożliwia definiowanie proporcji zapytań niezależnie od liczby replik. Oznacza to, że na przykład możemy korzystać z HPA (Horizontal Pod Autoscalers — poziome skalowanie podów) i nie trzeba go konfigurować zgodnie z aktualnym stanem wdrożenia Canary.
Podsumowanie
Istio działa doskonale, a jego połączenie z Kiali daje bardzo potężną kombinację. Następnym punktem moich zainteresowań jest połączenie Spinnaker z Istio w celu automatyzacji i analityki Canary.
Źródło: habr.com
