Zpět k mikroservisům s Istio. Část 2

Zpět k mikroservisům s Istio. Část 2

Pozn. přek.: První část Tento cyklus byl věnován seznámení s možnostmi Istio a jejich praktické ukázce. Teď se zaměříme na složitější aspekty konfigurace a použití této service mesh, konkrétně na jemně nastavitelné směrování a správu síťového provozu.

Připomínáme také, že v článku jsou použity konfigurace (manifesty pro Kubernetes a Istio) z repozitáře istio-mastery.

Správa provozu

S Istio v clusteru se objevují nové možnosti, které umožňují zajistit:

  • Dynamické směrování požadavků: kanárkové nasazení, A/B testování;
  • Vyvážení zátěže: jednoduché a konzistentní, založené na hashech;
  • Obnovení po selhání: časové limity, opakování pokusů, obvodové přepínače;
  • Zavádění poruch: zpoždění, přerušení požadavků atd.

V pokračování článku budou tyto možnosti ukázány na příkladu vybrané aplikace a zároveň budou představeny nové koncepty. Prvním takovým konceptem budou DestinationRules (tj. pravidla pro příjemce provozu/požadavků — pozn. překl.), pomocí kterých aktivujeme A/B testování.

A/B testování:  DestinationRules v praxi

A/B testování se používá v případech, kdy existují dvě verze aplikace (obvykle se liší vizuálně) a nejsme si jisti, která z nich zlepší interakci s uživateli. Proto obě verze spouštíme současně a shromažďujeme metriky.

Pro nasazení druhé verze frontendu, potřebné k demonstraci A/B testování, proveďte následující příkaz:

$ kubectl apply -f resource-manifests/kube/ab-testing/sa-frontend-green-deployment.yaml
departement.extensions/sa-frontend-green vytvořen

Manifest nasazení pro „zelenou verzi“ se liší na dvou místech:

  1. Obraz je založen na jiném tagu — istio-green,
  2. Pody mají label verze: green.

Protože oba nasazení mají label app: sa-frontend, požadavky směrované virtuální službou sa-external-services na službu sa-frontend, budou přesměrovány na všechny její instance a zatížení se rozdělí pomocí algoritmu round-robin, což povede k následující situaci:

Zpět k mikroservisům s Istio. Část 2
Požadované soubory nebyly nalezeny

Tyto soubory nebyly nalezeny, protože mají různé názvy v různých verzích aplikace. Ujistěme se o tom:

$ curl --silent http://$EXTERNAL_IP/ | tr '"' 'n' | grep main
/static/css/main.c7071b22.css
/static/js/main.059f8e9c.js
$ curl --silent http://$EXTERNAL_IP/ | tr '"' 'n' | grep main
/static/css/main.f87cd8c9.css
/static/js/main.f7659dbb.js

To znamená, že index.html, požadavek na jednu verzi statických souborů může být odeslán vyrovnávačem zátěže na podů, které mají jinou verzi, kde z pochopitelných důvodů takové soubory neexistují. Proto, aby aplikace fungovala, musíme stanovit omezení: „stejná verze aplikace, která vrátila index.html, by měla obsluhovat i následné požadavky».

Cíle dosáhneme pomocí konzistentního vyrovnávání zátěže založeného na hashe (Konzistentní Hash Loadbalancing). V tomto případě požadavky od jednoho klienta jsou odesílány do stejného instance backendu, k čemuž se používá předem definovaný prvek — například HTTP hlavička. To se implementuje pomocí DestinationRules.

DestinationRules

Jakmile je VirtualService odeslal požadavek na správnou službu, pomocí DestinationRules můžeme definovat politiky, které budou uplatněny na provoz určený instancím této služby:

Zpět k mikroservisům s Istio. Část 2
Správa provozu s prostředky Istio

Poznámka: Vliv prostředků Istio na síťový provoz je zde zjednodušeně znázorněn. Pokud chceme být přesní, rozhodnutí o tom, na kterou instanci odeslat požadavek, činí Envoy v Ingress Gateway nastaveném v CRD.

Pomocí Destination Rules můžeme nastavit vyrovnávání zátěže tak, aby byly používány konzistentní hashe a aby byla zaručena odpověď stejné instance služby stejnému uživateli. Následující konfigurace to umožňuje (destinationrule-sa-frontend.yaml):

apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: sa-frontend
spec:
  host: sa-frontend
  trafficPolicy:
    loadBalancer:
      consistentHash:
        httpHeaderName: version   # 1

1 — hash bude generován na základě obsahu HTTP hlavičky version.

Aplikujte konfiguraci následujícím příkazem:

$ kubectl apply -f resource-manifests/istio/ab-testing/destinationrule-sa-frontend.yaml
destinationrule.networking.istio.io/sa-frontend vytvořen

A nyní spusťte níže uvedený příkaz a ujistěte se, že dostáváte požadované soubory, když zadáte hlavičku version:

$ curl --silent -H "version: yogo" http://$EXTERNAL_IP/ | tr '"' 'n' | grep main

Poznámka: Chcete-li přidávat různá hodnoty do hlavičky a testovat výsledky přímo v prohlížeči, můžete využít tento rozšíření pro Chrome (nebo tento pro Firefox — pozn. překl..

Obecně mají DestinationRules více možností v oblasti vyrovnávání zátěže — pro podrobnosti se informujte v oficiální dokumentaci.

Než se podíváme na VirtualService dále, odstraníme «zelenou verzi» aplikace a odpovídající pravidlo pro směrování provozu pomocí následujících příkazů:

$ kubectl delete -f resource-manifests/kube/ab-testing/sa-frontend-green-deployment.yaml
deployment.extensions “sa-frontend-green” bylo odstraněno
$ kubectl delete -f resource-manifests/istio/ab-testing/destinationrule-sa-frontend.yaml
destinationrule.networking.istio.io “sa-frontend” bylo odstraněno

Zrcadlení: Virtual Services v praxi

Zastiňování („maskování“) nebo Mirroring („zrcadlení“) se používá v případech, kdy chceme otestovat změnu v produkci, aniž bychom zasáhli koncové uživatele: k tomu duplikujeme („zrcadlíme“) požadavky na druhý exemplář, kde byly provedeny požadované změny, a sledujeme následky. Jednoduše řečeno, když váš kolega vybere nejkritičtější problém a udělá pull request jako obrovský nepořádek, že nikdo ho vlastně nemůže přezkoumat.

Abychom tento scénář ověřili v akci, vytvoříme druhý exemplář SA-Logic s chybami (buggy), vybereme následující příkaz:

$ kubectl apply -f resource-manifests/kube/shadowing/sa-logic-service-buggy.yaml
deployment.extensions/sa-logic-buggy bylo vytvořeno

A nyní provedeme příkaz, abychom se ujistili, že všechny exempláře s app=sa-logic mají také štítky s odpovídajícími verzemi:

$ kubectl get pods -l app=sa-logic --show-labels
NÁZEV                              PŘIPRAVENO   ŠTÍTKY
sa-logic-568498cb4d-2sjwj         2/2     app=sa-logic,version=v1
sa-logic-568498cb4d-p4f8c         2/2     app=sa-logic,version=v1
sa-logic-buggy-76dff55847-2fl66   2/2     app=sa-logic,version=v2
sa-logic-buggy-76dff55847-kx8zz   2/2     app=sa-logic,version=v2

SA-Frontend sa-logic cílí na pod’y se štítkem app=sa-logic, a proto budou všechny požadavky rozděleny mezi všechny exempláře:

Zpět k mikroservisům s Istio. Část 2

… ale chceme, aby požadavky byly směrovány na exempláře s verzí v1 a zrcadlily se na exempláře s verzí v2:

Zpět k mikroservisům s Istio. Část 2

Toho dosáhneme prostřednictvím VirtualService v kombinaci s DestinationRule, kde pravidla určují podmnožiny a trasy VirtualService k určité podmnožině.

Definice podmnožin v Destination Rules

Podmnožiny (subsets) jsou definovány následující konfigurací (sa-logic-subsets-destinationrule.yaml):

apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: sa-logic
spec:
  host: sa-logic    # 1
  subsets:
  - name: v1        # 2
    labels:
      version: v1   # 3
  - name: v2
    labels:
      version: v2

  1. Host (host) určuje, že toto pravidlo se použije pouze v případech, kdy směrování směřuje k službě sa-logic;
  2. Jména (name) podmnožin se používají při směrování na exempláře podmnožin;
  3. Štítek (label) určuje páry klíč-hodnota, jímž musí odpovídat instance, aby se staly součástí podmnožiny.

Aplikujte konfiguraci následujícím příkazem:

$ kubectl apply -f resource-manifests/istio/shadowing/sa-logic-subsets-destinationrule.yaml
destinationrule.networking.istio.io/sa-logic vytvořen

Nyní, když jsou podmnožiny definovány, můžeme pokračovat a nastavit VirtualService tak, aby aplikoval pravidla na požadavky na sa-logic, aby:

  1. Byly směrovány na podmnožinu v1,
  2. Byly zrcadleny na podmnožinu v2.

Následující manifest umožňuje dosáhnout zamýšleného (sa-logic-subsets-shadowing-vs.yaml):

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: sa-logic
spec:
  hosts:
    - sa-logic          
  http:
  - route:
    - destination:
        host: sa-logic  
        subset: v1      
    mirror:             
      host: sa-logic     
      subset: v2

Vysvětlování zde není třeba, takže se jen podíváme na akci:

$ kubectl apply -f resource-manifests/istio/shadowing/sa-logic-subsets-shadowing-vs.yaml
virtualservice.networking.istio.io/sa-logic vytvořen

Přidáme zátěž zavoláním následujícího příkazu:

$ while true; do curl -v http://$EXTERNAL_IP/sentiment 
    -H "Content-type: application/json" 
    -d '{"sentence": "Miluji yogobellu"}'; 
    sleep .8; done

Podíváme se na výsledky v Grafaně, kde můžeme vidět, že verze s chybami (buggy) způsobuje selhání přibližně 60 % požadavků, ale žádné z těchto selhání se netýká koncových uživatelů, protože odpovídá fungující služba.

Zpět k mikroservisům s Istio. Část 2
Úspěšnost odpovědí různých verzí služby sa-logic

Zde jsme poprvé viděli, jak se VirtualService aplikuje na envoye našich služeb: když sa-web-app provádí požadavek na sa-logic, prochází přes sidecar Envoy, který je přes VirtualService nakonfigurován na směrování požadavku na podmnožinu v1 a zrcadlení požadavku na podmnožinu v2 služby. sa-logic.

Vím: už jste si pomysleli, že Virtual Services jsou jednoduché. V následující části toto mínění rozšíříme tím, že jsou také opravdu skvělé.

Kanárkové nasazení

Canary Deployment — proces zavádění nové verze aplikace pro malé množství uživatelů. Používá se k tomu, aby se ujistilo, že v releasu nejsou žádné problémy, a teprve poté, co je dostatečně přesvědčen o kvalitě (releasu), se rozšíří na širší publikum.oAbychom demonstrovali kanárková nasazení, budeme pokračovat s podmnožinou.

Nebudeme šetřit a hned pošleme 20 % uživatelů na verzi s chybami (ta bude představovat naše kanárkové nasazení), zatímco zbytek 80 % na normální službu. K tomu použijeme následující VirtualService ( buggy u sa-logic.

sa-logic-subsets-canary-vs.yamlsa-logic-subsets-canary-vs.yaml):

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: sa-logic
spec:
  hosts:
    - sa-logic    
  http:
  - route: 
    - destination: 
        host: sa-logic
        subset: v1
      weight: 80         # 1
    - destination: 
        host: sa-logic
        subset: v2
      weight: 20 # 1

1 — to je váha (váha), která určuje procento požadavků, které budou směrovány na příjemce nebo podmnožinu příjemce.

Aktualizujeme minulou konfiguraci VirtualService pomocí sa-logic následujícího příkazu:

$ kubectl apply -f resource-manifests/istio/canary/sa-logic-subsets-canary-vs.yaml
virtualservice.networking.istio.io/sa-logic nakonfigurován

… a hned vidíme, že část požadavků selhává:

$ while true; do 
   curl -i http://$EXTERNAL_IP/sentiment 
   -H "Content-type: application/json" 
   -d '{"sentence": "I love yogobella"}' 
   --silent -w "Time: %{time_total}s t Status: %{http_code}n" 
   -o /dev/null; sleep .1; done
Time: 0.153075s Status: 200
Time: 0.137581s Status: 200
Time: 0.139345s Status: 200
Time: 30.291806s Status: 500

VirtualServices aktivují kanárková nasazení: v tomto případě jsme omezili potenciální dopady problémů na 20 % uživatelské základny. Skvělé! Nyní, kdykoli si nejsme jisti svým kódem (jinými slovy — vždy…), můžeme použít zrcadlení a kanárková nasazení.

Časové limity a opakování

Ale ne vždy jsou chyby v kódu. V seznamu "8 mýtů o distribuovaných výpočtech" je na prvním místě mylný dojem, že „síť je spolehlivá“. Ve skutečnosti je síť ne spolehlivá, a proto potřebujeme časové limity (timeouts) a opakování (retries).

Pro demonstraci budeme i nadále používat stejný problém verze sa-logic (buggy), přičemž nespolehlivost sítě budeme simulovat náhodnými selháními.

Předpokládejme, že náš služba s chybami má 1/3 pravděpodobnost příliš dlouhé odpovědi, 1/3 pravděpodobnost chyby Internal Server Error a 1/3 pravděpodobnost úspěšného vrácení stránky.

Abychom zmírnili následky těchto problémů a zlepšili uživatelský zážitek, můžeme:

  1. přidat časové limity, pokud služba odpovídá déle než 8 sekund,
  2. pokusit se o opakování, pokud dojde k chybě žádosti.

Pro implementaci použijeme takovou definici zdroje (sa-logic-retries-timeouts-vs.yaml):

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: sa-logic
spec:
  hosts:
    - sa-logic
  http:
  - route: 
    - destination: 
        host: sa-logic
        subset: v1
      weight: 50
    - destination: 
        host: sa-logic
        subset: v2
      weight: 50
    timeout: 8s           # 1
    retries:
      attempts: 3         # 2
      perTryTimeout: 3s # 3

  1. Časové limity pro požadavek jsou nastaveny na 8 sekund;
  2. Požadavky jsou opakovány 3krát;
  3. A každá pokus se považuje za neúspěšný, pokud doba odezvy překročí 3 sekundy.

Tak jsme dosáhli optimalizace, protože uživatel nebude muset čekat déle než 8 sekund a podnikneme tři nové pokusy o získání odpovědi v případě selhání, čímž zvýšíme šanci na úspěšnou odpověď.

Použijte aktualizovanou konfiguraci následujícím příkazem:

$ kubectl apply -f resource-manifests/istio/retries/sa-logic-retries-timeouts-vs.yaml
virtualservice.networking.istio.io/sa-logic je nakonfigurován

A zkontrolujte v grafech Grafana, že počet úspěšných odpovědí vzrostl nad:

Zpět k mikroservisům s Istio. Část 2
Zlepšení ve statistikách úspěšných odpovědí po přidání časových limitů a opakovaných pokusů

Před tím, než přejdeme k další části (přesněji k další části článku, protože v této již nebudou praktické experimenty — pozn. red.), odstraňte sa-logic-buggy a VirtualService tímto příkazem:

$ kubectl delete deployment sa-logic-buggy
deployment.extensions "sa-logic-buggy" bylo smazáno
$ kubectl delete virtualservice sa-logic
virtualservice.networking.istio.io "sa-logic" bylo smazáno

Vzory Circuit Breaker a Bulkhead

Jedná se o dva důležité vzory v mikroslužbové architektuře, které umožňují dosažení autonomního zotavení (self-healing) služeb.

Circuit Breaker („automatický vypinač“) se používá k přerušení požadavků, které přicházejí na instanci služby, kterou označujeme jako nezdravou, a jejímu obnovení, zatímco požadavky klientů jsou přesměrovány na zdravé instance této služby (což zvyšuje procento úspěšných odpovědí). (Pozn. red.: Podrobnější popis vzoru lze nalézt například zde.)

Bulkhead („přepážka“) izoluje selhání ve službách od ovlivnění celého systému. Například, pokud je služba B porouchaná a jiná služba (klient služby B) posílá požadavek na službu B, tím dojde k vyčerpání jejího vlákna a nebude schopna obsluhovat další požadavky (i když se netýkají služby B). (Pozn. red.: Podrobnější popis vzoru lze nalézt například zde.)

Omlouvám se za detaily implementace těchto vzorů, protože je snadné je najít v oficiální dokumentaci, a také už bych chtěl ukázat autentizaci a autorizaci, o čemž bude řeč v následující části článku.

P.S. od překladatele

Přečtěte si také náš blog:

Zdroj: habr.com

Koupit spolehlivý hosting pro webové stránky s ochranou proti DDoS, VPS VDS servery 🔥 Koupit spolehlivý hosting pro webové stránky s ochranou proti DDoS, VPS VDS servery | ProHoster