Bumalik sa mga microservice kasama si Istio. Bahagi 2

Bumalik sa mga microservice kasama si Istio. Bahagi 2

Tandaan. transl.: Ang unang bahagi Ang seryeng ito ay nakatuon sa pagpapakilala ng mga kakayahan ng Istio at pagpapakita ng mga ito sa pagkilos. Ngayon ay pag-uusapan natin ang tungkol sa mas kumplikadong mga aspeto ng pagsasaayos at paggamit ng mesh ng serbisyong ito, at sa partikular, tungkol sa pinong nakatutok na pagruruta at pamamahala ng trapiko sa network.

Ipinapaalala rin namin sa iyo na ang artikulo ay gumagamit ng mga configuration (mga manifest para sa Kubernetes at Istio) mula sa repository istio-mastery.

Pamamahala ng Trapiko

Sa Istio, lumalabas ang mga bagong kakayahan sa cluster upang magbigay ng:

  • Dynamic na pagruruta ng kahilingan: canary rollouts, A/B testing;
  • Pagbalanse ng load: simple at pare-pareho, batay sa mga hash;
  • Pagbawi pagkatapos mahulog: mga timeout, muling pagsubok, mga circuit breaker;
  • Pagpasok ng mga pagkakamali: mga pagkaantala, mga bumabagsak na kahilingan, atbp.

Habang nagpapatuloy ang artikulo, ang mga kakayahan na ito ay ilalarawan gamit ang napiling aplikasyon bilang isang halimbawa at ang mga bagong konsepto ay ipakikilala sa daan. Ang unang ganoong konsepto ay magiging DestinationRules (ibig sabihin, mga panuntunan tungkol sa tatanggap ng trapiko/mga kahilingan - tinatayang transl.), sa tulong kung saan ina-activate namin ang A/B testing.

A/B testing: DestinationRules sa pagsasanay

Ginagamit ang A/B testing sa mga kaso kung saan mayroong dalawang bersyon ng isang application (karaniwan ay magkaiba ang mga ito sa paningin) at hindi kami 100% sigurado kung alin ang magpapahusay sa karanasan ng user. Samakatuwid, sabay naming pinapatakbo ang parehong bersyon at nangongolekta kami ng mga sukatan.

Upang i-deploy ang pangalawang bersyon ng frontend, kinakailangan para sa pagpapakita ng pagsubok sa A/B, patakbuhin ang sumusunod na command:

$ kubectl apply -f resource-manifests/kube/ab-testing/sa-frontend-green-deployment.yaml
deployment.extensions/sa-frontend-green created

Ang deployment manifest para sa "berdeng bersyon" ay naiiba sa dalawang lugar:

  1. Ang larawan ay batay sa ibang tag - istio-green,
  2. May label ang mga pod version: green.

Dahil may label ang parehong deployment app: sa-frontend,mga kahilingang niruruta ng virtual na serbisyo sa-external-services para sa serbisyo sa-frontend, ay ire-redirect sa lahat ng mga pagkakataon nito at ang load ay ipapamahagi sa pamamagitan ng round-robin algorithm, na hahantong sa sumusunod na sitwasyon:

Bumalik sa mga microservice kasama si Istio. Bahagi 2
Hindi nahanap ang mga hiniling na file

Hindi natagpuan ang mga file na ito dahil iba ang pangalan ng mga ito sa iba't ibang bersyon ng application. Siguraduhin natin ito:

$ 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

Nangangahulugan ito na index.html, na humihiling ng isang bersyon ng mga static na file, ay maaaring ipadala ng load balancer sa mga pod na may ibang bersyon, kung saan, para sa malinaw na mga kadahilanan, ang mga naturang file ay hindi umiiral. Samakatuwid, upang gumana ang aplikasyon, kailangan naming magtakda ng isang paghihigpit: "ang parehong bersyon ng application na nagsilbi sa index.html ay dapat maghatid ng mga kasunod na kahilingan'.

Darating tayo doon nang may pare-parehong hash-based na load balancing (Patuloy na Hash Loadbalancing)... Sa kasong ito ang mga kahilingan mula sa parehong kliyente ay ipinapadala sa parehong backend instance, kung saan ginagamit ang isang paunang natukoy na ari-arian - halimbawa, isang header ng HTTP. Ipinatupad gamit ang  DestinationRules.

Mga Panuntunan sa Patutunguhan

Pagkatapos VirtualService nagpadala ng kahilingan sa nais na serbisyo, gamit ang DestinationRules maaari naming tukuyin ang mga patakaran na ilalapat sa trapikong nakalaan para sa mga pagkakataon ng serbisyong ito:

Bumalik sa mga microservice kasama si Istio. Bahagi 2
Pamamahala ng trapiko gamit ang mga mapagkukunan ng Istio

Nota: Ang epekto ng mga mapagkukunan ng Istio sa trapiko sa network ay ipinakita dito sa paraang madaling maunawaan. Upang maging tumpak, ang desisyon kung saan ipapadala ang kahilingan ay ginawa ng Envoy sa Ingress Gateway na na-configure sa CRD.

Sa Mga Panuntunan sa Patutunguhan, maaari naming i-configure ang pagbalanse ng load upang gumamit ng pare-parehong mga hash at matiyak na ang parehong instance ng serbisyo ay tumutugon sa parehong user. Ang sumusunod na pagsasaayos ay nagpapahintulot sa iyo na makamit ito (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 - mabubuo ang hash batay sa mga nilalaman ng header ng HTTP version.

Ilapat ang pagsasaayos gamit ang sumusunod na utos:

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

Ngayon patakbuhin ang command sa ibaba at tiyaking makukuha mo ang mga tamang file kapag tinukoy mo ang header version:

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

Nota: Upang magdagdag ng iba't ibang mga halaga sa header at subukan ang mga resulta nang direkta sa browser, maaari mong gamitin extension na ito sa Chrome (O kasama nito para sa Firefox - tinatayang. transl.).

Sa pangkalahatan, ang DestinationRules ay may higit pang mga kakayahan sa lugar ng load balancing - tingnan ang mga detalye sa opisyal na dokumentasyon.

Bago pag-aralan pa ang VirtualService, tanggalin natin ang "berdeng bersyon" ng application at ang kaukulang tuntunin sa direksyon ng trapiko sa pamamagitan ng pagpapatakbo ng mga sumusunod na command:

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

Pagmi-mirror: Virtual na Serbisyo sa Practice

Shadowing ("pagtatangi") o Pagsasalamin (“pagsasalamin”) ginagamit sa mga kaso kung saan gusto naming sumubok ng pagbabago sa produksyon nang hindi naaapektuhan ang mga end user: para magawa ito, duplicate namin ang mga kahilingan (“mirror”) sa pangalawang pagkakataon kung saan nagawa na ang mga gustong pagbabago, at tinitingnan ang mga kahihinatnan. Sa madaling salita, ito ay kapag pinili ng iyong kasamahan ang pinaka-kritikal na isyu at gumawa ng kahilingan sa paghila sa anyo ng napakalaking bukol ng dumi na walang sinuman ang makakapag-review nito.

Upang subukan ang sitwasyong ito sa pagkilos, gumawa tayo ng pangalawang pagkakataon ng SA-Logic na may mga bug (buggy) sa pamamagitan ng pagpapatakbo ng sumusunod na utos:

$ kubectl apply -f resource-manifests/kube/shadowing/sa-logic-service-buggy.yaml
deployment.extensions/sa-logic-buggy created

At ngayon, patakbuhin natin ang command upang matiyak na ang lahat ng mga pagkakataon ay may app=sa-logic Mayroon din silang mga label na may kaukulang mga bersyon:

$ kubectl get pods -l app=sa-logic --show-labels
NAME                              READY   LABELS
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

Tools sa-logic nagta-target ng mga pod na may label app=sa-logic, kaya lahat ng mga kahilingan ay ibabahagi sa lahat ng mga pagkakataon:

Bumalik sa mga microservice kasama si Istio. Bahagi 2

... ngunit gusto naming maipadala ang mga kahilingan sa v1 instance at i-mirror sa v2 instance:

Bumalik sa mga microservice kasama si Istio. Bahagi 2

Makakamit namin ito sa pamamagitan ng VirtualService kasama ang DestinationRule, kung saan tutukuyin ng mga panuntunan ang mga subset at ruta ng VirtualService sa isang partikular na subset.

Pagtukoy ng mga Subset sa Mga Panuntunan sa Patutunguhan

Mga subset (subset) ay tinutukoy ng sumusunod na pagsasaayos (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) ay tumutukoy na ang panuntunang ito ay nalalapat lamang sa mga kaso kapag ang ruta ay papunta sa serbisyo sa-logic;
  2. Mga Pamagat (name) ang mga subset ay ginagamit kapag nagruruta sa mga subset na pagkakataon;
  3. Label (label) ay tumutukoy sa mga pares ng key-value na dapat itugma ng mga instance upang maging bahagi ng subset.

Ilapat ang pagsasaayos gamit ang sumusunod na utos:

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

Ngayong natukoy na ang mga subset, maaari na tayong magpatuloy at i-configure ang VirtualService para ilapat ang mga panuntunan sa mga kahilingan sa sa-logic upang sila ay:

  1. Idinala sa isang subset v1,
  2. Naka-mirror sa isang subset v2.

Ang sumusunod na manifesto ay nagpapahintulot sa iyo na makamit ang iyong mga plano (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

Walang paliwanag na kailangan dito, kaya tingnan na lang natin ito sa pagkilos:

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

Idagdag natin ang load sa pamamagitan ng pagtawag sa sumusunod na command:

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

Tingnan natin ang mga resulta sa Grafana, kung saan makikita mo na ang bersyon na may mga bug (buggy) ay nagreresulta sa pagkabigo para sa ~60% ng mga kahilingan, ngunit wala sa mga pagkabigo na ito ang makakaapekto sa mga end user habang tinutugunan sila ng tumatakbong serbisyo.

Bumalik sa mga microservice kasama si Istio. Bahagi 2
Mga matagumpay na tugon ng iba't ibang bersyon ng serbisyong sa-logic

Dito namin unang nakita kung paano inilalapat ang VirtualService sa mga Envoy ng aming mga serbisyo: kailan sa-web-app gumagawa ng isang kahilingan sa sa-logic, dumaan ito sa sidecar Envoy, na - sa pamamagitan ng VirtualService - ay na-configure upang iruta ang kahilingan sa v1 subset at i-mirror ang kahilingan sa v2 subset ng serbisyo sa-logic.

Alam ko, baka isipin mo na ang Virtual Services ay simple. Sa susunod na seksyon, palalawakin natin iyon sa pagsasabing talagang mahusay din sila.

Canary rollouts

Ang Canary Deployment ay ang proseso ng paglulunsad ng bagong bersyon ng isang application sa isang maliit na bilang ng mga user. Ginagamit ito upang matiyak na walang mga problema sa pagpapalabas at pagkatapos lamang nito, na may tiwala sa kalidad nito (release), ipamahagi ito sa ibang mga user.оmas malaking madla.

Para ipakita ang mga canary rollout, patuloy kaming gagana sa isang subset buggy у sa-logic.

Huwag tayong mag-aksaya ng oras sa mga maliit na bagay at agad na ipadala ang 20% ​​ng mga user sa bersyon na may mga bug (ito ay kumakatawan sa aming canary rollout), at ang natitirang 80% sa normal na serbisyo. Upang gawin ito, gamitin ang sumusunod na VirtualService (sa-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 ang timbang (weight), na tumutukoy sa porsyento ng mga kahilingan na ididirekta sa isang tatanggap o isang subset ng tatanggap.

I-update natin ang nakaraang configuration ng VirtualService para sa sa-logic gamit ang sumusunod na utos:

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

... at agad naming makikita na ang ilang kahilingan ay humahantong sa mga pagkabigo:

$ 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

Pinapagana ng VirtualServices ang mga canary rollout: Sa kasong ito, pinaliit namin ang potensyal na epekto ng mga isyu sa 20% ng user base. Kahanga-hanga! Ngayon, sa bawat kaso kapag hindi kami sigurado sa aming code (sa madaling salita - palagi...), maaari kaming gumamit ng mirroring at canary rollout.

Mga timeout at muling pagsubok

Ngunit ang mga bug ay hindi palaging napupunta sa code. Sa listahan mula sa "8 Mga Maling Palagay tungkol sa Distributed Computing"Sa unang lugar ay ang maling paniniwala na "ang network ay maaasahan." Sa katotohanan ang network hindi maaasahan, at dahil dito kailangan namin ng mga timeout (mga timeout) at muling sumubok (sinubukan muli).

Para sa pagpapakita, patuloy naming gagamitin ang parehong bersyon ng problema sa-logic (buggy), at gayahin namin ang hindi pagiging maaasahan ng network na may mga random na pagkabigo.

Hayaan ang aming serbisyo na may mga bug na magkaroon ng 1/3 na pagkakataong magtagal upang tumugon, isang 1/3 na pagkakataong magtapos sa isang Internal na Error sa Server, at isang 1/3 na pagkakataon na matagumpay na maibalik ang pahina.

Upang mapagaan ang epekto ng mga naturang problema at gawing mas mahusay ang buhay para sa mga user, maaari naming:

  1. magdagdag ng timeout kung ang serbisyo ay tumatagal ng higit sa 8 segundo upang tumugon,
  2. subukang muli kung nabigo ang kahilingan.

Para sa pagpapatupad, gagamitin namin ang sumusunod na kahulugan ng mapagkukunan (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. Ang timeout para sa kahilingan ay nakatakda sa 8 segundo;
  2. Ang mga kahilingan ay muling sinubukan nang 3 beses;
  3. At ang bawat pagtatangka ay itinuturing na hindi matagumpay kung ang oras ng pagtugon ay lumampas sa 3 segundo.

Isa itong pag-optimize dahil hindi na kailangang maghintay ng user ng higit sa 8 segundo at gagawa kami ng tatlong bagong pagtatangka upang makakuha ng tugon kung sakaling mabigo, na magpapalaki ng pagkakataon ng isang matagumpay na tugon.

Ilapat ang na-update na configuration gamit ang sumusunod na command:

$ kubectl apply -f resource-manifests/istio/retries/sa-logic-retries-timeouts-vs.yaml
virtualservice.networking.istio.io/sa-logic configured

At tingnan sa mga grap ng Grafana na tumaas ang bilang ng mga matagumpay na tugon sa itaas:

Bumalik sa mga microservice kasama si Istio. Bahagi 2
Mga pagpapabuti sa matagumpay na mga istatistika ng pagtugon pagkatapos magdagdag ng mga timeout at muling pagsubok

Bago lumipat sa susunod na seksyon (o sa halip, sa susunod na bahagi ng artikulo, dahil dito ay wala nang praktikal na mga eksperimento - tinatayang transl.), tanggalin sa-logic-buggy at VirtualService sa pamamagitan ng pagpapatakbo ng mga sumusunod na command:

$ kubectl delete deployment sa-logic-buggy
deployment.extensions “sa-logic-buggy” deleted
$ kubectl delete virtualservice sa-logic
virtualservice.networking.istio.io “sa-logic” deleted

Mga Pattern ng Circuit Breaker at Bulkhead

Pinag-uusapan natin ang tungkol sa dalawang mahalagang pattern sa arkitektura ng microservice na nagbibigay-daan sa iyong makamit ang pagbawi sa sarili (pagpapagaling sa sarili) serbisyo.

circuit breaker ("circuit breaker") ginagamit upang wakasan ang mga kahilingang dumarating sa isang instance ng isang serbisyo na itinuturing na hindi malusog at i-restore ito habang ang mga kahilingan ng kliyente ay nire-redirect sa malusog na mga pagkakataon ng serbisyong iyon (na nagpapataas sa porsyento ng mga matagumpay na tugon). (Tandaan: Ang isang mas detalyadong paglalarawan ng pattern ay matatagpuan, halimbawa, dito.)

Bulkhead ("partisyon") ibinubukod ang mga pagkabigo ng serbisyo mula sa nakakaapekto sa buong system. Halimbawa, nasira ang Serbisyo B at ang isa pang serbisyo (kliyente ng Serbisyo B) ay humiling sa Serbisyo B, na nagiging sanhi upang maubos ang thread pool nito at hindi makapagbigay ng serbisyo sa iba pang mga kahilingan (kahit na hindi sila mula sa Serbisyo B). (Tandaan: Ang isang mas detalyadong paglalarawan ng pattern ay matatagpuan, halimbawa, dito.)

Aalisin ko ang mga detalye ng pagpapatupad ng mga pattern na ito dahil madaling mahanap ang mga ito opisyal na dokumentasyon, at gusto ko rin talagang magpakita ng pagpapatunay at awtorisasyon, na tatalakayin sa susunod na bahagi ng artikulo.

PS mula sa tagasalin

Basahin din sa aming blog:

Pinagmulan: www.habr.com

Magdagdag ng komento