Diversity w polskim IT
Błażej Kwaśniak
SoftServe
Błażej KwaśniakTechnical Leader, GCP cluster of Critical Services CoE @ SoftServe

Wykorzystanie Istio w testowaniu aplikacji opartej na mikroserwisach

Zobacz, jak możesz użyć Istio, by wdrożyć Canary Release, Fault Injection, Latency Injection i Traffic Mirroring.
9.09.20198 min
Wykorzystanie Istio w testowaniu aplikacji opartej na mikroserwisach

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:


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-system:tiller
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.

<p>Loading...</p>