Pesë gabime gjatë vendosjes së aplikacionit të parë në Kubernetes

Pesë gabime gjatë vendosjes së aplikacionit të parë në KubernetesDështimi nga Aris Dreamer

Shumë njerëz mendojnë se është e mjaftueshme për të transferuar aplikacionin në Kubernetes (ose duke përdorur Helm ose me dorë) - dhe do të ketë lumturi. Por jo gjithçka është kaq e thjeshtë.

Ekip Mail.ru Cloud Solutions përktheu një artikull nga inxhinieri DevOps Julian Gindy. Ai tregon se me çfarë grackash u përball kompania e tij gjatë procesit të migrimit, në mënyrë që të mos shkelni në të njëjtën grabujë.

Hapi i parë: Vendosni kërkesat dhe kufijtë e pod

Le të fillojmë duke krijuar një mjedis të pastër ku do të funksionojnë podat tona. Kubernetes është i shkëlqyeshëm në planifikimin e pod dhe dështimin. Por doli që planifikuesi ndonjëherë nuk mund të vendosë një pod nëse është e vështirë të vlerësohet se sa burime i nevojiten për të punuar me sukses. Këtu shfaqen kërkesat për burime dhe kufizime. Ka shumë debate rreth qasjes më të mirë për vendosjen e kërkesave dhe kufijve. Ndonjëherë duket se ky është me të vërtetë më shumë një art sesa një shkencë. Këtu është qasja jonë.

Kërkesat për pod është vlera kryesore e përdorur nga planifikuesi për të vendosur në mënyrë optimale podin.

Nga Dokumentacioni Kubernetes: Hapi i filtrit përcakton një grup nyjesh ku mund të planifikohet një Pod. Për shembull, filtri PodFitsResources kontrollon nëse një nyje ka burime të mjaftueshme për të kënaqur kërkesat specifike të burimeve nga një pod.

Ne përdorim kërkesat e aplikacionit në mënyrë të tillë që të mund të vlerësojmë sa burime në fakt Aplikacioni ka nevojë që ai të funksionojë siç duhet. Në këtë mënyrë planifikuesi mund t'i vendosë nyjet realisht. Fillimisht, ne donim të mbi-programonim kërkesat për të siguruar burime të mjaftueshme për çdo Pod, por vumë re se koha e planifikimit u rrit ndjeshëm dhe disa Pod nuk ishin planifikuar plotësisht, sikur të mos kishte kërkesa për burime për to.

Në këtë rast, planifikuesi shpesh do t'i "shtrydhte" podet dhe nuk do të ishte në gjendje t'i riplanifikonte ato, sepse rrafshi i kontrollit nuk e kishte idenë se sa burime do t'i duheshin aplikacionit, që është një komponent kyç i algoritmit të planifikimit.

Kufijtë e pod është një kufi më i qartë për një pod. Ai përfaqëson sasinë maksimale të burimeve që grupi do t'i ndajë kontejnerit.

Përsëri, nga dokumentacion zyrtar: Nëse një kontejner ka një kufi memorie prej 4 GiB, atëherë kubelet (dhe koha e ekzekutimit të kontejnerit) do ta zbatojnë atë. Koha e ekzekutimit parandalon që kontejneri të përdorë më shumë se kufiri i burimit të specifikuar. Për shembull, kur një proces në një kontenier përpiqet të përdorë më shumë se sasia e lejuar e memories, kerneli i sistemit e përfundon procesin me një gabim "out of memory" (OOM).

Një kontejner mund të përdorë gjithmonë më shumë burime sesa specifikon kërkesa për burim, por nuk mund të përdorë kurrë më shumë se kufiri. Kjo vlerë është e vështirë të vendoset saktë, por është shumë e rëndësishme.

Në mënyrë ideale, ne duam që kërkesat për burime të një pod të ndryshojnë gjatë ciklit jetësor të një procesi pa ndërhyrë në procese të tjera në sistem - ky është qëllimi i vendosjes së kufijve.

Fatkeqësisht, nuk mund të jap udhëzime specifike se cilat vlera duhet të vendosen, por ne vetë i përmbahemi rregullave të mëposhtme:

  1. Duke përdorur një mjet testimi të ngarkesës, ne simulojmë një nivel bazë të trafikut dhe vëzhgojmë përdorimin e burimeve të pod (memoria dhe procesori).
  2. Vendosni kërkesat e pod në një vlerë arbitrare të ulët (me një kufi burimi prej rreth 5 herë më shumë se vlera e kërkesave) dhe vëzhgoni. Kur kërkesat janë në një nivel shumë të ulët, procesi nuk mund të fillojë, duke shkaktuar shpesh gabime të fshehta në kohën e ekzekutimit të Go.

Vërej se kufizimet më të larta të burimeve e bëjnë planifikimin më të vështirë sepse pod ka nevojë për një nyje të synuar me burime të mjaftueshme në dispozicion.

Imagjinoni një situatë ku keni një server të lehtë në internet me një kufi shumë të lartë burimesh, si 4 GB memorie. Ky proces ka të ngjarë të duhet të zvogëlohet horizontalisht dhe çdo pod i ri do të duhet të planifikohet në një nyje me të paktën 4 GB memorie të disponueshme. Nëse nuk ekziston një nyje e tillë, grupi duhet të prezantojë një nyje të re për të përpunuar këtë pod, gjë që mund të marrë pak kohë. Është e rëndësishme të arrihet një ndryshim minimal midis kërkesave për burime dhe kufijve për të siguruar shkallëzim të shpejtë dhe të qetë.

Hapi i dytë: Vendosni testet e gjallërisë dhe gatishmërisë

Kjo është një tjetër temë delikate që diskutohet shpesh në komunitetin Kubernetes. Është e rëndësishme të keni një kuptim të mirë të testeve të gjallërisë dhe gatishmërisë pasi ato ofrojnë një mekanizëm për funksionimin e qëndrueshëm të softuerit dhe minimizojnë kohën e ndërprerjes. Megjithatë, ato mund të ndikojnë seriozisht në performancën e aplikacionit tuaj nëse nuk konfigurohen siç duhet. Më poshtë është një përmbledhje e asaj që janë të dy mostrat.

Gjallëri tregon nëse kontejneri po funksionon. Nëse dështon, kubelet vret kontejnerin dhe politika e rinisjes aktivizohet për të. Nëse kontejneri nuk është i pajisur me një sondë Liveness, atëherë gjendja e paracaktuar do të jetë e suksesshme - siç thuhet në Dokumentacioni Kubernetes.

Sondat Liveness duhet të jenë të lira, domethënë të mos konsumojnë shumë burime, sepse ato funksionojnë shpesh dhe duhet të informojnë Kubernetes se aplikacioni po funksionon.

Nëse vendosni opsionin për të ekzekutuar çdo sekondë, kjo do të shtojë 1 kërkesë për sekondë, ndaj kini parasysh se do të kërkohen burime shtesë për të përpunuar këtë trafik.

Në kompaninë tonë, testet e Liveness testojnë komponentët thelbësorë të një aplikacioni, edhe nëse të dhënat (për shembull, nga një bazë të dhënash në distancë ose cache) nuk janë plotësisht të disponueshme.

Ne kemi vendosur një pikë përfundimtare "shëndeti" në aplikacionet që thjesht kthen një kod përgjigjeje 200. Ky është një tregues se procesi është duke u ekzekutuar dhe i aftë për të trajtuar kërkesat (por jo ende trafikun).

provë gatishmëri tregon nëse kontejneri është gati për të shërbyer kërkesa. Nëse hetimi i gatishmërisë dështon, kontrolluesi i pikës fundore heq adresën IP të pod-it nga pikat fundore të të gjitha shërbimeve që përputhen me podin. Kjo thuhet edhe në dokumentacionin e Kubernetes.

Sondat e gatishmërisë konsumojnë më shumë burime, pasi ato duhet të godasin prapavijën në mënyrë të tillë që të tregojnë se aplikacioni është gati të pranojë kërkesat.

Ka shumë debate në komunitet nëse duhet të hyni drejtpërdrejt në bazën e të dhënave. Duke marrë parasysh shpenzimet e përgjithshme (kontrollet janë të shpeshta, por ato mund të kontrollohen), vendosëm që për disa aplikacione, gatishmëria për të shërbyer trafikun të llogaritet vetëm pasi të kontrollojmë që të dhënat janë kthyer nga baza e të dhënave. Provat e gatishmërisë të dizajnuara mirë siguruan disponueshmëri më të lartë dhe eliminuan kohën e ndërprerjes gjatë vendosjes.

Nëse vendosni të kërkoni bazën e të dhënave për të testuar gatishmërinë e aplikacionit tuaj, sigurohuni që të jetë sa më i lirë që të jetë e mundur. Le të marrim këtë pyetje:

SELECT small_item FROM table LIMIT 1

Këtu është një shembull se si ne i konfigurojmë këto dy vlera në Kubernetes:

livenessProbe: 
 httpGet:   
   path: /api/liveness    
   port: http 
readinessProbe:  
 httpGet:    
   path: /api/readiness    
   port: http  periodSeconds: 2

Mund të shtoni disa opsione shtesë të konfigurimit:

  • initialDelaySeconds - sa sekonda do të kalojnë ndërmjet nisjes së kontejnerit dhe fillimit të lëshimit të sondave.
  • periodSeconds — intervali i pritjes ndërmjet ekzekutimeve të mostrës.
  • timeoutSeconds - numri i sekondave pas të cilave pod konsiderohet emergjente. Kohëzgjatja normale.
  • failureThreshold është numri i dështimeve të provës përpara se një sinjal rinisje të dërgohet në pod.
  • successThreshold është numri i provave të suksesshme përpara se pod të kalojë në gjendjen e gatshme (pas një dështimi kur pod fillon ose rikuperohet).

Hapi i tretë: Vendosja e politikave të paracaktuara të rrjetit të Pod-it

Kubernetes ka një topografi të rrjetit "të sheshtë", si parazgjedhje të gjitha pods komunikojnë drejtpërdrejt me njëri-tjetrin. Në disa raste kjo nuk është e dëshirueshme.

Një çështje e mundshme e sigurisë është se një sulmues mund të përdorë një aplikacion të vetëm të cenueshëm për të dërguar trafikun në të gjitha pods në rrjet. Ashtu si në shumë fusha të sigurisë, këtu zbatohet parimi i privilegjit më të vogël. Në mënyrë ideale, politikat e rrjetit duhet të deklarojnë në mënyrë eksplicite se cilat lidhje midis pods lejohen dhe cilat jo.

Për shembull, sa vijon është një politikë e thjeshtë që mohon të gjithë trafikun në hyrje për një hapësirë ​​të caktuar emri:

---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:  
 name: default-deny-ingress
spec:  
 podSelector: {}  
 policyTypes:  
   - Ingress

Vizualizimi i këtij konfigurimi:

Pesë gabime gjatë vendosjes së aplikacionit të parë në Kubernetes
(https://miro.medium.com/max/875/1*-eiVw43azgzYzyN1th7cZg.gif)
Dëmet në detaje këtu.

Hapi i katërt: Sjellja e personalizuar me grepa dhe kontejnerë fillestarë

Një nga qëllimet tona kryesore ishte të siguronim vendosje në Kubernetes pa ndërprerje për zhvilluesit. Kjo është e vështirë sepse ka shumë opsione për mbylljen e aplikacioneve dhe lëshimin e burimeve të tyre të përdorura.

Vështirësi të veçanta u shfaqën me nginx. Ne vumë re se gjatë vendosjes së këtyre Pods në sekuencë, lidhjet aktive u ndërprenë përpara se të përfundonin me sukses.

Pas një kërkimi të gjerë në internet, rezultoi se Kubernetes nuk pret që lidhjet Nginx të shterojnë veten përpara se të mbyllin podin. Me ndihmën e fiksimit të parandalimit, ne zbatuam funksionalitetin e mëposhtëm dhe u çliruam plotësisht nga ndërprerja:

lifecycle: 
 preStop:
   exec:
     command: ["/usr/local/bin/nginx-killer.sh"]

Por nginx-killer.sh:

#!/bin/bash
sleep 3
PID=$(cat /run/nginx.pid)
nginx -s quit
while [ -d /proc/$PID ]; do
   echo "Waiting while shutting down nginx..."
   sleep 10
done

Një tjetër paradigmë jashtëzakonisht e dobishme është përdorimi i kontejnerëve init për të trajtuar nisjen e aplikacioneve specifike. Kjo është veçanërisht e dobishme nëse keni një proces migrimi me burime intensive të bazës së të dhënave që duhet të ekzekutohet përpara se të fillojë aplikacioni. Ju gjithashtu mund të specifikoni një kufi më të lartë burimesh për këtë proces pa vendosur një kufi të tillë për aplikacionin kryesor.

Një skemë tjetër e zakonshme është qasja në sekretet në kontejnerin fillestar, i cili i siguron këto kredenciale modulit kryesor, i cili parandalon aksesin e paautorizuar në sekretet nga vetë moduli kryesor i aplikacionit.

Si zakonisht, një citat nga dokumentacioni: init kontejnerët ekzekutojnë në mënyrë të sigurt kodin e përdoruesit ose programet ndihmëse që përndryshe do të rrezikonin sigurinë e imazhit të kontejnerit të aplikacionit. Duke i mbajtur të ndara mjetet e panevojshme, ju kufizoni sipërfaqen e sulmit të imazhit të kontejnerit të aplikacionit.

Hapi i pestë: Konfigurimi i kernelit

Së fundi, le të flasim për një teknikë më të avancuar.

Kubernetes është një platformë jashtëzakonisht fleksibël që ju lejon të ekzekutoni ngarkesat e punës siç e shihni të arsyeshme. Ne kemi një numër aplikacionesh shumë efikase që kërkojnë burime jashtëzakonisht intensive. Pasi bëmë testimin e gjerë të ngarkesës, zbuluam se një nga aplikacionet e kishte të vështirë të mbante ngarkesën e pritshme të trafikut kur ishin në fuqi cilësimet e parazgjedhura të Kubernetes.

Sidoqoftë, Kubernetes ju lejon të ekzekutoni një enë të privilegjuar që ndryshon vetëm parametrat e kernelit për një pod specifik. Ja çfarë kemi përdorur për të ndryshuar numrin maksimal të lidhjeve të hapura:

initContainers:
  - name: sysctl
     image: alpine:3.10
     securityContext:
         privileged: true
      command: ['sh', '-c', "sysctl -w net.core.somaxconn=32768"]

Kjo është një teknikë më e avancuar që shpesh nuk është e nevojshme. Por nëse aplikacioni juaj është duke luftuar për të përballuar një ngarkesë të madhe, mund të provoni të ndryshoni disa nga këto cilësime. Më shumë informacion në lidhje me këtë proces dhe vendosjen e vlerave të ndryshme - si gjithmonë në dokumentacionin zyrtar.

Në përfundim

Ndërsa Kubernetes mund të duket si një zgjidhje e disponueshme, ka disa hapa kyç që duhen ndërmarrë për të mbajtur aplikacionet të funksionojnë pa probleme.

Gjatë gjithë migrimit në Kubernetes, është e rëndësishme të ndiqni "ciklin e testimit të ngarkesës": ekzekutoni aplikacionin, testoni atë nën ngarkesë, vëzhgoni metrikat dhe sjelljen e shkallëzimit, rregulloni konfigurimin bazuar në këto të dhëna dhe më pas përsërisni këtë cikël përsëri.

Jini realist në lidhje me trafikun e pritur dhe përpiquni të shkoni përtej tij për të parë se cilët komponentë prishen së pari. Me këtë qasje përsëritëse, vetëm disa nga rekomandimet e listuara mund të jenë të mjaftueshme për të arritur sukses. Ose mund të kërkojë personalizim më të thelluar.

Bëjini vetes gjithmonë këto pyetje:

  1. Sa burime konsumojnë aplikacionet dhe si do të ndryshojë kjo shumë?
  2. Cilat janë kërkesat reale të shkallëzimit? Sa trafik do të trajtojë mesatarisht aplikacioni? Po në kulmin e trafikut?
  3. Sa shpesh do të duhet të zvogëlohet shërbimi? Sa shpejt duhet të funksionojnë dhe funksionojnë podet e reja për të marrë trafik?
  4. Me sa hijeshi mbyllen podet? A është fare e nevojshme? A është e mundur të arrihet vendosja pa ndërprerje?
  5. Si të minimizoni rreziqet e sigurisë dhe të kufizoni dëmtimin nga çdo pods i komprometuar? A ka ndonjë shërbim leje ose akses që nuk i duhen?

Kubernetes ofron një platformë të jashtëzakonshme që ju lejon të përdorni praktikat më të mira për të vendosur mijëra shërbime në një grup. Sidoqoftë, të gjitha aplikacionet janë të ndryshme. Ndonjëherë zbatimi kërkon pak më shumë punë.

Për fat të mirë, Kubernetes ofron cilësimet e nevojshme për të arritur të gjitha qëllimet teknike. Duke përdorur një kombinim të kërkesave dhe kufijve të burimeve, hetimeve të Liveness dhe Gatishmërisë, kontejnerëve fillestarë, politikave të rrjetit dhe akordimit të personalizuar të kernelit, mund të arrini performancë të lartë së bashku me tolerancën e gabimeve dhe shkallëzueshmëri të shpejtë.

Çfarë tjetër për të lexuar:

  1. Praktikat më të mira dhe praktikat më të mira për drejtimin e kontejnerëve dhe Kubernetes në mjediset e prodhimit.
  2. Mbi 90 mjete të dobishme për Kubernetes: Vendosja, Menaxhimi, Monitorimi, Siguria dhe më shumë.
  3. Kanali ynë Rreth Kubernetes në Telegram.

Burimi: www.habr.com

Shto një koment