Kas yra Istio ir kodėl jis svarbus moderniam programų diegimui
Kubernetes jau seniai tapo standartu konteinerizuotų aplikacijų valdymui, bet kartu su juo atėjo ir nauji iššūkiai. Kaip valdyti tūkstančius mikroservisų? Kaip užtikrinti saugų komunikaciją tarp jų? Kaip diegti naujas versijas be rizikos sugadinti visą sistemą? Čia ir ateina į pagalbą Istio – service mesh platforma, kuri tampa tarsi nervų sistema jūsų Kubernetes klasteriui.
Istio leidžia valdyti trafiko srautus tarp servisų be jokių pakeitimų pačiame aplikacijos kode. Tai reiškia, kad galite diegti sudėtingas trafiko valdymo strategijas, stebėti servisų elgesį ir užtikrinti saugumą visiškai nepriklausomai nuo to, kokia kalba parašyta jūsų aplikacija. Ir viena iš galingiausių Istio funkcijų – canary deployments, arba kaip mes sakytume lietuviškai – palaipsnis diegimas su testavimu mažoje vartotojų grupėje.
Canary deployments filosofija: kodėl angliakasiams reikėjo kanarėlių
Terminas „canary deployment” kilo iš senos anglių angliakasiams praktikos – jie į šachtas pasiimtų kanarėles, kurios buvo jautrios nuodingioms dujoms. Jei paukštelis nustotų čiulbėti, tai buvo signalas evakuotis. Panašiai veikia ir canary deployments IT pasaulyje.
Vietoj to, kad naują programos versiją iš karto diegtumėte visiems vartotojams, jūs pirmiausia nukreipiate tik mažą dalį trafiko (pavyzdžiui, 5-10%) į naują versiją. Jei viskas veikia sklandžiai – metrikose nematyti klaidų, atsakymo laikas nepablogėjo, vartotojai nesiskundžia – galite palaipsniui didinti trafiko dalį. Jei kažkas ne taip – greitai grąžinate visą trafiką atgal į seną, stabilią versiją.
Skirtumas nuo tradicinio blue-green deployment yra tas, kad čia neturite dviejų pilnai atskirų aplinkų. Abi versijos veikia kartu, o jūs tiesiog kontroliuojate, kiek trafiko gauna kiekviena. Tai efektyviau naudoja resursus ir leidžia tiksliau įvertinti naujos versijos elgesį realiomis sąlygomis.
Kaip Istio valdo trafiką: VirtualService ir DestinationRule
Istio trafiko valdymas remiasi keliais pagrindiniais Custom Resource Definition (CRD) objektais. Svarbiausi iš jų – VirtualService ir DestinationRule. Supratę šiuos du komponentus, jūs suprasite 80% Istio trafiko valdymo logikos.
VirtualService apibrėžia, kaip užklausos yra nukreipiamos į jūsų servisus. Galvokite apie jį kaip apie trafiko policininką, kuris stovi sankryžoje ir rodo, kur važiuoti. Jis gali priimti sprendimus remiantis URL keliu, HTTP antraštėmis, slapukais ir kitais kriterijais.
DestinationRule apibrėžia, kas nutinka po to, kai trafiko policininkas nusprendė, kur siųsti užklausą. Čia apibrėžiami subsets (pogrupiai) – pavyzdžiui, „v1” ir „v2” versijos jūsų serviso. Taip pat čia konfigūruojami load balancing algoritmai, connection pool nustatymai ir kiti detalūs parametrai.
Praktiškai tai atrodo taip: sukuriate deployment su nauja versija, pažymite jį atitinkamu label (pavyzdžiui, version: v2), tada per DestinationRule apibrėžiate šį subset, o per VirtualService nurodote, kiek procentų trafiko turėtų eiti į kiekvieną subset. Viskas be aplikacijos kodo keitimo!
Praktinis canary deployment pavyzdys su Istio
Pažiūrėkime į konkretų pavyzdį. Tarkime, turite paprastą web aplikaciją „myapp”, kuri šiuo metu veikia v1 versijoje, ir norite ją atnaujinti į v2. Pirmiausia jums reikia dviejų Kubernetes deployments:
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp-v1
spec:
replicas: 3
selector:
matchLabels:
app: myapp
version: v1
template:
metadata:
labels:
app: myapp
version: v1
spec:
containers:
- name: myapp
image: myapp:1.0
ports:
- containerPort: 8080
Analogiškai sukuriate myapp-v2 deployment su atitinkamais labels. Dabar ateina Istio magija. Pirmiausia apibrėžkite DestinationRule su dviem subsets:
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
name: myapp
spec:
host: myapp
subsets:
- name: v1
labels:
version: v1
- name: v2
labels:
version: v2
Dabar sukuriate VirtualService, kuris pradžioje nukreipia 90% trafiko į v1 ir tik 10% į v2:
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: myapp
spec:
hosts:
- myapp
http:
- match:
- headers:
user-agent:
regex: ".*Mobile.*"
route:
- destination:
host: myapp
subset: v2
weight: 100
- route:
- destination:
host: myapp
subset: v1
weight: 90
- destination:
host: myapp
subset: v2
weight: 10
Šiame pavyzdyje dar įtraukiau papildomą taisyklę – visi mobile vartotojai automatiškai nukreipiami į v2. Tai dažna praktika, kai norite testuoti naują versiją specifinėje vartotojų grupėje.
Monitoringas ir metrikų stebėjimas canary deployment metu
Diegti naują versiją – tai tik pusė darbo. Svarbiausia dalis – stebėti, kaip ji veikia. Istio automatiškai renka daugybę metrikų apie kiekvieną užklausą: atsakymo laiką, klaidų kiekį, trafiko apimtį ir t.t. Šios metrikos eksportuojamos Prometheus formatu, todėl lengvai integruojasi su populiariausiomis monitoringo sistemomis.
Rekomenduoju stebėti bent šiuos rodiklius:
- Error rate – klaidų procentas. Jei v2 versijoje jis staiga išauga, tai aiškus signalas grįžti atgal.
- Latency percentiles – ypač p95 ir p99. Vidutinis atsakymo laikas gali atrodyti gerai, bet jei 5% vartotojų patiria lėtą veikimą, tai problema.
- Request volume – įsitikinkite, kad trafiko paskirstymas atitinka jūsų nustatytus svorius.
- CPU ir memory naudojimas – nauja versija gali būti funkcionali, bet neefektyvi resursų naudojimo požiūriu.
Grafana dashboardai su Istio metrikomis yra beveik būtinybė. Istio projektas pateikia paruoštus dashboard šablonus, kuriuos galite importuoti ir pritaikyti savo poreikiams. Taip pat verta nustatyti alertus – pavyzdžiui, jei error rate viršija 1% arba p95 latency padidėja daugiau nei 50%, automatiškai gaunate pranešimą.
Automatizuotas canary deployment su Flagger
Rankiniu būdu keisti VirtualService konfigūraciją ir stebėti metrikos – tai veikia, bet nėra labai efektyvu. Čia ateina į pagalbą Flagger – Kubernetes operatorius, specialiai sukurtas automatizuoti canary deployments su Istio (ir kitomis service mesh platformomis).
Flagger veikia taip: jūs apibrėžiate Canary resource, kuriame nurodote, kaip turėtų vykti deployment procesas – kokiais žingsniais didinti trafiką, kokias metrikos stebėti, kokios ribos priimtinos. Tada, kai atnaujinate deployment image, Flagger automatiškai:
- Sukuria naują versiją su mažu trafiko kiekiu
- Stebi metrikos nustatytą laiką
- Jei viskas gerai – didina trafiko dalį
- Kartoja, kol 100% trafiko eina į naują versiją
- Jei bet kuriame etape metrikos blogos – automatiškai rollback
Flagger konfigūracijos pavyzdys:
apiVersion: flagger.app/v1beta1
kind: Canary
metadata:
name: myapp
spec:
targetRef:
apiVersion: apps/v1
kind: Deployment
name: myapp
service:
port: 8080
analysis:
interval: 1m
threshold: 5
maxWeight: 50
stepWeight: 10
metrics:
- name: request-success-rate
thresholdRange:
min: 99
interval: 1m
- name: request-duration
thresholdRange:
max: 500
interval: 1m
webhooks:
- name: load-test
url: http://flagger-loadtester/
timeout: 5s
metadata:
cmd: "hey -z 1m -q 10 -c 2 http://myapp:8080/"
Ši konfigūracija sako: kas minutę didink trafiką 10%, bet ne daugiau nei iki 50%. Jei success rate nukrenta žemiau 99% arba request duration viršija 500ms, sustabdyk procesą. Taip pat paleisk load testą kiekviename etape, kad gautume pakankamai duomenų metrikoms.
Sudėtingesni scenarijai: A/B testing ir header-based routing
Canary deployments – tai tik pradžia. Istio leidžia įgyvendinti daug sudėtingesnius trafiko valdymo scenarijus. Pavyzdžiui, A/B testingą, kai skirtingi vartotojai gauna skirtingas funkcijas ne pagal atsitiktinumą, o pagal tam tikrus kriterijus.
Tarkime, norite naują UI dizainą rodyti tik premium vartotojams. Jūsų aplikacija gali pridėti custom header x-user-tier: premium, o Istio VirtualService gali naudoti šį header routing sprendimams:
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: myapp
spec:
hosts:
- myapp
http:
- match:
- headers:
x-user-tier:
exact: premium
route:
- destination:
host: myapp
subset: v2
- route:
- destination:
host: myapp
subset: v1
Kitas populiarus scenarijus – dark launches. Čia nauja versija gauna tikrą production trafiką, bet jos atsakymai nėra grąžinami vartotojams – jie tik logginami ir analizuojami. Istio tai gali padaryti su mirroring funkcija:
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: myapp
spec:
hosts:
- myapp
http:
- route:
- destination:
host: myapp
subset: v1
weight: 100
mirror:
host: myapp
subset: v2
mirrorPercentage:
value: 10
Šis konfigūracija siunčia 10% užklausų į v2 kaip „šešėlinį” trafiką. Vartotojai gauna atsakymus tik iš v1, bet v2 apdoroja tikras užklausas ir galite stebėti jos elgesį be jokios rizikos.
Dažniausios klaidos ir kaip jų išvengti
Per kelerius metus dirbdamas su Istio, mačiau daug įvairių klaidų. Štai dažniausios iš jų:
Nepakankamas resursų planavimas. Kai paleidžiate canary deployment, kurį laiką veikia abi versijos vienu metu. Jei jūsų klasteris jau dirba ties limitu, nauja versija gali neturėti kur „nusileisti”. Visada planuokite papildomus resursus canary fazei.
Per greitas trafiko didinimas. Žmonės būna nekantrūs ir nori kuo greičiau pasiekti 100%. Bet canary deployment tikslas – aptikti problemas anksti. Jei per greitai didinate trafiką, galite praleisti subtilias problemas, kurios pasireiškia tik esant didesniam load.
Nepakankami testai prieš deployment. Canary nėra pakeičiamas staging aplinkai. Baziniai funkciniai testai turi būti atlikti prieš bet kokį deployment į production. Canary padeda aptikti problemas, kurios pasireiškia tik production aplinkoje su tikru trafiku.
Ignoruojamos metrikos. Matau komandas, kurios nustato canary deployment, bet realiai nežiūri į metrikos. Tai kaip turėti dūmų detektorių be baterijų. Jei nestebite, kokia prasmė turėti canary?
Stateful aplikacijų problemos. Canary deployments gerai veikia su stateless aplikacijomis. Jei jūsų aplikacija laiko state (sesijas, cache), turite labai atidžiai planuoti, kaip tai veiks su dviem versijomis vienu metu. Kartais reikia papildomų mechanizmų, kaip sticky sessions arba shared cache.
Kai viskas suveikia: nuo eksperimento iki production standarto
Istio su canary deployments iš pradžių gali atrodyti kaip per didelė kanonas mažam žvirbliui. Setup’as nėra trivialus, reikia išmokti naujų koncepcijų, sukonfigūruoti monitoring sistemą. Bet kai viskas suveikia, tai keičia žaidimo taisykles.
Komandos, kurios įdiegė šią praktiką, pastebi kelis esminius pokyčius. Pirma, deployments tampa daug dažnesni – kai nebijote sugadinti production, galite diegti naujoves kasdien ar net kelis kartus per dieną. Antra, incidentų dėl blogų deployments sumažėja drastiškai – problemos aptinkamos anksti ir automatiškai išsprendžiamos. Trečia, komandos jaučiasi labiau pasitikintys – žinote, kad turite safety net.
Svarbu suprasti, kad Istio ir canary deployments nėra silver bullet. Tai įrankiai, kurie veikia geriausia tam tikrame kontekste – mikroservisų architektūroje, Kubernetes aplinkoje, su komanda, kuri supranta šių technologijų principus. Jei jūsų aplikacija – vienas monolitas ant VM, tikriausiai yra paprastesnių būdų pasiekti panašius rezultatus.
Bet jei jau esate Kubernetes pasaulyje su keliais ar keliolika servisų, Istio tampa natūralia evoliucija. Pradėkite mažai – vienas servisas, paprastas canary deployment, stebėkite kaip veikia. Palaipsniui plėskite į kitus servisus, eksperimentuokite su sudėtingesniais routing scenarijais. Ir svarbiausia – automatizuokite. Kas veikia rankiniu būdu, neveiks ilgalaikėje perspektyvoje.
Technologijos kaip Istio rodo, kur juda cloud native ekosistema – link didesnės abstrakcijos, automatizacijos ir patikimumo. Canary deployments su Istio – tai ne tik techninė praktika, bet ir kultūrinis pokytis link continuous delivery, kur deployment nėra stresą keliantis įvykis, o įprasta kasdienė operacija.
