Vous êtes sur la page 1sur 8

Wykorzystanie Istio w testowaniu aplikacji opartej na mikroserwisach

Błażej Kwaśniak
Technical Leader, GCP cluster of Critical Services CoE

Zobacz, jak możesz użyć Istio, by wdrożyć Canary Release, Fault Injection, Latency Injection i Traffic Mirroring.
 7 min  09.09.2019

W ostatnich latach aplikacje oparte na architekturze mikroserwisów stały się standardem w branży IT. Nie są one jednak pozbawione wad – w miejsce doskonale
znanych nam wcześniej problemów, otrzymaliśmy po prostu zestaw zupełnie nowych „wyzwań”. Jednym z nich jest komunikacja sieciowa pomiędzy
poszczególnymi elementami. W tym aspekcie z pomocą przychodzi nam jednak Istio. Jest to niezwykle popularne rozwiązanie typu Service Mesh, które oferuje
całkiem spory zestaw możliwości w zakresie kształtowania i zarządzania ruchem sieciowym – od prostego blokowania,  aż po analizę protokołu HTTP i wielu
innych. 

Architektura tego narzędzia jest zaskakująco prosta. Całość opiera się na zastosowaniu proxy kontenerów, wstrzykiwanych do każdego Pod’a. Dzięki temu
jesteśmy w stanie zarządzać całym ruchem przychodzącym, jak i wychodzącym z naszej aplikacji. Jesteście zatem ciekawi, jak wykorzystać to narzędzie do
testowania aplikacji opartej na mikroserwisach?

Na potrzeby doświadczenia, które zamierzam razem z Wami przeprowadzić, wybrałem te funkcjonalności Istio, które są najbardziej pomocne podczas testowania
aplikacji rozproszonej. Mój poradnik jest zaadresowany do osób, które mają chociaż znikome pojęcie o zarządzaniu mikroserwisami, jak i samym Kubernetes’em.
Przed rozpoczęciem lektury polecam również zapoznać się z podstawowymi konceptami związanymi z Istio. Zaczynajmy!

Podczas naszego ćwiczenia wykorzystamy linię komend, standardowe polecenia (np. git) oraz bardziej specjalistyczne narzędzia i rozwiązania, takie jak:

Minikube v1.1.1 
Kubectl v1.15.0 
Helm v2.14.1 
Istio v1.12.0.

Zakładam że każdy z wymienionych elementów został poprawnie zainstalowany w systemie. Pamiętajcie, że wszystkie przedstawione poniżej przykłady można
wykonać używając również innej instancji Kubernetes’a, np. GKE, EKS, czy wielu innych – do czego gorąco zachęcam!

Przygotowanie środowiska
Naszą zabawę rozpoczynamy od stworzenia lokalnego klastra Kubernetes’a. W tym celu wykorzystamy narzędzie Minikube. Polecam zwiększyć domyślną ilość
pamięci RAM oraz CPU:

minikube start --cpus 4 --memory 6144

Całość instalacji potrwa parę minut. Czas na kawę! ☺

Po krótkiej przerwie instalujemy Helm tiller’a i dodajemy zewnętrzne repozytorium, w którym znajduje się Istio. W najprostszy sposób można to zrobić używając
następujących poleceń:

kubectl create serviceaccount --namespace kube-system tiller


kubectl create clusterrolebinding tiller-cluster-rule --clusterrole=cluster-admin --serviceaccount=kube-sys
helm init
helm repo add istio.io https://storage.googleapis.com/istio-release/releases/1.2.0/charts/
helm repo update

Kolejnym i zarazem ostatnim krokiem, który wykonamy, żeby stworzyć środowisko pod nasze doświadczenie, jest instalacja Istio. Na szczęście społeczność
przygotowała nam do tego celu bardzo dobre Chart’y, więc całość sprowadza się do dwóch komend:

helm install istio.io/istio-init --name istio-init --namespace istio-system


( zalecam odczekać 2 minuty )
helm install istio.io/istio --name istio --namespace istio-system

Jeżeli wszystkie operacje przebiegły zgodnie z planem, w linii komend powinniśmy zobaczyć następujący obrazek:

bash-5.0$ kubectl get pods -n istio-system


NAME READY STATUS RESTARTS AGE
istio-citadel-7695fc84d9-mb2dk 1/1 Running 0 3m42s
istio-galley-75466f5dc7-zfk56 1/1 Running 0 3m42s
istio-ingressgateway-69dfdb8d6-v5qdv 1/1 Running 0 3m42s
istio-init-crd-10-4s8hm 0/1 Completed 0 4m16s
istio-init-crd-11-b2zpw 0/1 Completed 0 4m16s
istio-init-crd-12-9j9g6 0/1 Completed 0 4m16s
istio-pilot-5dd7b5f674-dpjxh 2/2 Running 0 3m42s
istio-policy-8469ffd9df-jxjx9 2/2 Running 3 3m42s
istio-sidecar-injector-6f4c67c6cd-2frff 1/1 Running 0 3m41s
istio-telemetry-5bf99ff6df-hl2dr 2/2 Running 3 3m42s
prometheus-776fdf7479-pk72r 1/1 Running 0 3m42s
bash-5.0$

Instalacja projektu demonstracyjnego


W głównym repozytorium Istio znajduje się bardzo ciekawy przykład aplikacji opartej na mikroserwisach – Bookinfo – i to właśnie ją będziemy wspólnie testować. 

git clone https://github.com/istio/istio


cd istio/
git checkout -b 1.2.0 1.2.0
cd samples/bookinfo/
kubectl label namespace default istio-injection=enabled

Ostatnie z przedstawionych poleceń to jedna z wielu metod na wstrzyknięcie kontenera Istio-proxy do naszych pod’ów.  Pomijając szczegóły – w ten
sposób Istio kontroluje cały ruch przychodzący, jak i wychodzący z aplikacji. Pamiętajcie, że istnieją również alternatywne metody na wykonanie tej części zadania,
a wybór należy do Was. Po dalsze informacje odsyłam do dokumentacji samego projektu.

Czas najwyższy na instalację naszej aplikacji na minikub’ie:


kubectl apply -f platform/kube/bookinfo.yaml

Analiza podanego pliku konfiguracyjnego wykracza poza zakres tego artykułu, dlatego też zaufamy społeczności i po prostu uruchomimy przedstawioną komendę
„w ciemno”. Niemniej gorąco zachęcam do zapoznania się z zawartością tego pliku – w szczególności osoby, które nie mają większego doświadczenia
z Kubernetes’em. 

W linii komend powinniśmy teraz zobaczyć następujące informacje:

bash-5.0$ kubectl get deployments


NAME READY UP-TO-DATE AVAILABLE AGE
details-v1 1/1 1 1 3m17s
productpage-v1 1/1 1 1 3m16s
ratings-v1 1/1 1 1 3m17s
reviews-v1 1/1 1 1 3m17s
reviews-v2 1/1 1 1 3m16s
reviews-v3 1/1 1 1 3m16s
bash-5.0$

Jak już pewnie zauważyliście, na naszym klastrze działają jednocześnie trzy różne wersje mikroserwisu Reviews – to właśnie na jego podstawie pokażę Wam
praktyczne zastosowanie Istio w testowaniu aplikacji.  

Ostatnim już elementem konfiguracyjnym jest zestaw DestinationRule. Są to reguły określające, w jaki sposób ruch ma zostać przekazywany do konkretnej
instancji serwisu.  Po raz kolejny zaufamy społeczności i uruchomimy komendę:

kubectl apply -f networking/destination-rule-all.yaml

Strona główna
Nadszedł czas na stronę główną naszej aplikacji. Istnieje kilka sposobów na przekierowanie ruchu z klastra Kubernetes’a do komputera. My skorzystamy ze
standardowej komendy port-forward, ale pamiętajcie, że istnieją również inne ciekawe narzędzia, np. telepresence.

kubectl port-forward svc/productpage 9080:9080

Teraz pozostaje nam tylko wejść na stronę:

http://127.0.0.1:9080/productpage

 
Polecam kilkukrotnie odświeżyć stronę i obserwować różnicę. W kolumnie Book Reviews możemy zauważyć zmieniające się elementy. Różnica dotyczy koloru oraz
obecności „gwiazdek” przy danej opinii. Są to odpowiednio:

Brak  – pierwsza wersja naszej aplikacji (reviews-v1),


Czarne – druga wersja (reviews-v2),
Czerwone – trzecia wersja (reviews-v3).

Niestety, na razie sytuacja nie wygląda najlepiej. Użytkownik otrzymuje losową wersję naszej strony, niezależnie od tego czy jest zalogowany czy nie. Spróbujmy
to zmienić.

Wersja pierwsza dla wszystkich, druga dla testera


Skonfigurujmy Istio tak, aby każdemu użytkownikowi zawsze wyświetlała się pierwsza wersja aplikacji:

cat << EOF | kubectl apply -f -


apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: reviews
spec:
hosts:
- reviews
http:
- route:
- destination:
host: reviews
subset: v1
EOF

Dzięki wprowadzeniu tej zmiany każdy użytkownik widzi to samo, niezależnie od tego czy jest zalogowany czy nie. Dążymy jednak do sytuacji, w której tester
będzie mógł korzystać z innego widoku niż pozostali użytkownicy.

W prawym górnym rogu naszej aplikacji znajduje się przycisk Sign in. 

Po zalogowaniu użytkownik widzi to samo co poprzednio. Spróbujmy więc zaktualizować ustawienia Istio tak, aby tester zobaczył wersję drugą.
cat << EOF | kubectl apply -f -
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: reviews
spec:
hosts:
- reviews
http:
- match:
- headers:
end-user:
exact: tester
route:
- destination:
host: reviews
subset: v2
- route:
- destination:
host: reviews
subset: v1
EOF

Teraz wystarczy odświeżyć stronę i tester jest w stanie zobaczyć nową wersję. Po kliknięciu w przycisk Sign out powracamy do pierwotnego stanu. 

Przedstawione rozwiązanie można wykorzystać na wiele sposobów –  od zwykłego testowania manualnego, poprzez testy automatyczne, aż po ciekawe strategie
wdrażania zmian na środowisko produkcyjne, potocznie zwane Canary Release. 

Fault injection
Kolejną ciekawą funkcjonalnością, którą możemy wykorzystać w kontekście testowania naszej aplikacji, jest wstrzykiwanie losowych błędów http. Pozwoli nam to
prześledzić, jak zachowają się wówczas poszczególne części systemu oraz czy taka sytuacja zostanie poprawnie obsłużona. Wdrożenie takiego scenariusza
w Istio jest niesamowicie proste i sprowadza się do zaaplikowania poniższej konfiguracji, a następnie kilkukrotnym odświeżeniu strony.
cat << EOF | kubectl apply -f –
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: reviews
spec:
hosts:
- reviews
http:
- match:
- headers:
end-user:
exact: tester
fault:
abort:
percentage:
value: 50.0
httpStatus: 500
route:
- destination:
host: reviews
subset: v2
- route:
- destination:
host: reviews
subset: v2
EOF

W tym przykładzie tester powinien zobaczyć 50% błędów. Jak widać na przykładzie poniżej, nasza aplikacja nie jest zbyt dobrze przygotowana na taka sytuację.

Latency injection
Istio pozwala na wstrzykiwanie innego rodzaju błędów. Tym razem do naszego sprawnie działającego systemu wstrzykujemy opóźnienia na poziomie komunikacji
sieciowej. W podanym przykładzie za każdym razem dodajemy stałe, 5-sekundowe opóźnienie. 
cat << EOF | kubectl apply -f -
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: reviews
spec:
hosts:
- reviews
http:
- match:
- headers:
end-user:
exact: tester
fault:
delay:
percentage:
value: 100.0
fixedDelay: 5s
route:
- destination:
host: reviews
subset: v2
- route:
- destination:
host: reviews
subset: v2
EOF

Niestety i w tym przypadku aplikacja nie radzi sobie najlepiej. Strona internetowa ładuje się stosunkowo długo, a na sam koniec otrzymujemy niezbyt zachęcający
komunikat błędu. Cała sytuacja spowodowana jest przez jeden, nieco mniej istotny komponent i z pewnością możemy dużo lepiej przygotować się na taką
ewentualność, np. wyświetlając losową reklamę.

Traffic mirroring
Ostatnią już funkcjonalnością, którą chciałbym zaprezentować, jest Traffic Mirroring. W tym ćwiczeniu cały ruch sieciowy jest przekazywany nie tylko do głównego ,
ale również do innego, wskazanego przez nas serwisu.

cat << EOF | kubectl apply -f -


apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: v1-all
spec:
hosts:
- reviews
http:
- route:
- destination:
host: reviews
subset: v2
mirror:
host: reviews
subset: v3
EOF

Warto pamiętać, że nie będziemy w stanie zobaczyć odpowiedzi zwróconej przez testowany serwis. Są one odrzucane na poziomie istio-proxy. Zostają jednak w
pełni obsłużone przez naszą aplikację, co możemy zaobserwować m.in. w logach. Dzięki tej funkcjonalności jesteśmy w stanie w prosty sposób przetestować nową
wersję aplikacji na rzeczywistych zapytaniach pochodzących od klientów. Oczywiście używasz na własną odpowiedzialność ;) 

Podsumowanie
Przedstawiony zestaw funkcjonalności to zaledwie wycinek możliwości, jakie daje nam Istio. Każda z nich może okazać się bardzo przydatna nie tylko podczas
testowania nowych rozwiązań, ale również w codziennej pracy z naszym systemem. Gorąco zachęcam do samodzielnego przetestowania i dokładniejszego
zapoznania się z przykładami znajdującymi się w oficjalnym repozytorium oraz z samą dokumentacją. Mam nadzieję, że zainspiruję Was to do dalszej pracy
z Istio i  poszukiwania nowych ciekawych zastosowań dla tej technologii.

O autorze
Błażej Kwaśniak to pasjonat DevOps z ponad 6-letnim doświadczeniem w różnych obszarach. Przeszedł drogę od "oldschoolowego" Sysadmina i magika
OpenStack z domieszką SDN, SDS etc., do DevOps Technical Leadera, który koncentruje się na dostarczaniu wysoce skalowalnych rozwiązań opartych na
platformach chmury publicznej i popularyzowaniu obszaru DevOps na świecie. Wierzy w automatyzację oraz podejścia All as a Code and cloud first.