Kvin maltrafoj dum deplojado de la unua aplikaĵo sur Kubernetes

Kvin maltrafoj dum deplojado de la unua aplikaĵo sur KubernetesMalsukceso de Aris-Dreamer

Multaj homoj kredas, ke sufiĉas migri la aplikaĵon al Kubernetes (ĉu uzante Helm aŭ permane) kaj ili estos feliĉaj. Sed ĝi ne estas tiel simpla.

teamo Mail.ru Cloud Solutions tradukis artikolon de DevOps-inĝeniero Julian Gindi. Li dividas, kiajn malfacilaĵojn renkontis lia kompanio dum la migrada procezo, por ke vi ne tretu la saman rastilon.

Paŝo Unu: Agordi Pod-Petojn kaj Limojn

Ni komencu starigi puran medion en kiu niaj podoj funkcios. Kubernetes faras bonegan laboron por plani podojn kaj pritrakti malsukcesajn kondiĉojn. Sed montriĝis, ke la planisto foje ne povas meti pod, se estas malfacile taksi kiom da rimedoj ĝi bezonas por sukcese funkcii. Ĉi tie aperas petoj pri rimedoj kaj limoj. Estas multe da debato pri la plej bona aliro por fiksi petojn kaj limojn. Kelkfoje ĝi vere sentas, ke ĝi estas pli arto ol scienco. Jen nia aliro.

Pod-petoj - Ĉi tiu estas la ĉefa valoro uzata de la planilo por optimume meti la podon.

De Kubernetes dokumentaro: La filtra paŝo determinas la aron de nodoj, kie la podo povas esti planita. Ekzemple, la filtrilo PodFitsResources kontrolas ĉu nodo havas sufiĉajn rimedojn por kontentigi la specifajn rimedpetojn de pod.

Ni uzas aplikajn petojn por ke ili estu uzataj por taksi kiom da rimedoj fakte La aplikaĵo bezonas ĝin por funkcii ĝuste. Tiel la planisto povas meti nodojn realisme. Ni komence volis agordi petojn kun marĝeno por certigi, ke ĉiu podo havas sufiĉe grandan kvanton da rimedoj, sed ni rimarkis, ke plantempoj signife pliiĝis kaj kelkaj balgoj neniam estis plene planitaj, kvazaŭ neniuj rimedopetoj estus ricevitaj por ili.

En ĉi tiu kazo, la planisto ofte puŝus eksteren balgojn kaj estus nekapabla postdatigi ilin ĉar la kontrolaviadilo havis neniun ideon kiom multajn resursojn la aplikiĝo postulus, ŝlosilan komponenton de la planadalgoritmo.

Pod-limoj - ĉi tio estas pli klara limo por la balgo. Ĝi reprezentas la maksimuman kvanton de rimedoj, kiujn la areto asignos al la ujo.

Denove, de oficiala dokumentaro: Se ujo havas 4 GiB-memorlimon fiksitan, tiam la kubelet (kaj la ujo rultempo) devigos ĝin. La rultempo ne permesas al la ujo uzi pli ol la specifita rimeda limo. Ekzemple, kiam procezo en ujo provas uzi pli ol la permesita kvanto de memoro, la sistemkerno finas la procezon kun "elmemoro" (OOM) eraro.

Ujo ĉiam povas uzi pli da rimedoj ol specifita en la rimeda peto, sed neniam povas uzi pli ol specifita en la limo. Ĉi tiu valoro estas malfacile agordi ĝuste, sed ĝi estas tre grava.

Ideale, ni volas, ke la rimedpostuloj de balgo ŝanĝiĝu dum la vivociklo de procezo sen malhelpi aliajn procezojn en la sistemo - tio estas la celo fiksi limojn.

Bedaŭrinde, mi ne povas doni specifajn instrukciojn pri kiaj valoroj agordi, sed ni mem aliĝas al la sekvaj reguloj:

  1. Uzante ŝarĝan testan ilon, ni simulas bazan nivelon de trafiko kaj kontrolas la uzon de podresursoj (memoro kaj procesoro).
  2. Ni fiksas la podpetojn al arbitre malalta valoro (kun rimeda limo de ĉirkaŭ 5 fojojn la valoro de la petoj) kaj observas. Kiam petoj estas tro malaltaj, la procezo ne povas komenci, ofte kaŭzante misterajn Go rultempajn erarojn.

Notu, ke pli altaj rimedlimoj malfaciligas la planadon ĉar la balgo bezonas celnodon kun sufiĉe daj rimedoj disponeblaj.

Imagu situacion, kie vi havas malpezan retservilon kun tre alta limo de rimedoj, ekzemple 4 GB da memoro. Ĉi tiu procezo verŝajne devos grimpi horizontale, kaj ĉiu nova modulo devos esti planita sur nodo kun almenaŭ 4 GB da disponebla memoro. Se tia nodo ne ekzistas, la areto devas enkonduki novan nodon por prilabori tiun balgon, kio povas daŭri iom da tempo. Gravas minimumigi la diferencon inter rimedpetoj kaj limoj por certigi rapidan kaj glatan skalon.

Dua paŝo: starigi testojn pri Liveness kaj Readiness

Ĉi tio estas alia subtila temo, kiu ofte estas diskutata en la Kubernetes-komunumo. Gravas havi bonan komprenon de Liveness kaj Readiness testoj ĉar ili provizas mekanismon por programaro por funkcii glate kaj minimumigi malfunkcion. Tamen, ili povas kaŭzi gravan rendimentan sukceson al via aplikaĵo se ne agordita ĝuste. Malsupre estas resumo de kiaj estas ambaŭ specimenoj.

Vivo montras ĉu la ujo funkcias. Se ĝi malsukcesas, la kubelet senvivigas la ujon kaj rekomenca politiko estas ebligita por ĝi. Se la ujo ne estas ekipita per Liveness-sondilo, tiam la defaŭlta stato sukcesos - jen kion ĝi diras Kubernetes dokumentaro.

Liveness-enketoj devus esti malmultekostaj, tio signifas, ke ili ne devus konsumi multajn rimedojn, ĉar ili funkcias ofte kaj bezonas informi Kubernetes, ke la aplikaĵo funkcias.

Se vi agordas la eblon funkcii ĉiun sekundon, ĉi tio aldonos 1 peton por sekundo, do konsciu, ke aldonaj rimedoj estos necesaj por trakti ĉi tiun trafikon.

Ĉe nia kompanio, Liveness-testoj kontrolas la kernajn komponentojn de aplikaĵo, eĉ se la datumoj (ekzemple, de fora datumbazo aŭ kaŝmemoro) ne estas plene alireblaj.

Ni agordis la apojn kun "sana" finpunkto, kiu simple resendas respondkodon de 200. Ĉi tio estas indiko, ke la procezo funkcias kaj kapablas prilabori petojn (sed ankoraŭ ne trafikon).

Specimeno Preteco indikas ĉu la ujo estas preta por servi petojn. Se la preteca sondilo malsukcesas, la finpunktoregilo forigas la IP-adreson de la pod de la finpunktoj de ĉiuj servoj egalrilatantaj al la pod. Ĉi tio ankaŭ estas deklarita en la Kubernetes-dokumentado.

Pretaj enketoj konsumas pli da rimedoj ĉar ili devas esti senditaj al la backend en maniero kiel kiu indikas ke la aplikaĵo estas preta akcepti petojn.

Estas multe da debato en la komunumo pri ĉu aliri la datumbazon rekte. Konsiderante la supran koston (kontroloj estas faritaj ofte, sed povas esti alĝustigitaj), ni decidis, ke por iuj aplikoj, la preteco servi trafikon estas nur kalkulita post kontrolado, ke rekordoj estas resenditaj el la datumbazo. Bone dizajnitaj pretecaj provoj certigis pli altajn nivelojn de havebleco kaj eliminis malfunkcion dum deplojo.

Se vi decidas pridemandi la datumbazon por testi la pretecon de via aplikaĵo, certigu, ke ĝi estas kiel eble plej malmultekosta. Ni prenu ĉi tiun peton:

SELECT small_item FROM table LIMIT 1

Jen ekzemplo de kiel ni agordas ĉi tiujn du valorojn en Kubernetes:

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

Vi povas aldoni kelkajn pliajn agordajn opciojn:

  • initialDelaySeconds — kiom da sekundoj pasos inter la lanĉo de la ujo kaj la komenco de la specimenoj.
  • periodSeconds — atendanta intervalo inter specimenaj kuroj.
  • timeoutSeconds — la nombro da sekundoj post kiuj la unuo estas konsiderata krizo. Regula tempotempo.
  • failureThreshold — la nombro da testmalsukcesoj antaŭ ol rekomencsignalo estas sendita al la pod.
  • successThreshold — la nombro da sukcesaj enketoj antaŭ ol la balgo iras en la pretan staton (post malsukceso, kiam la podo komenciĝas aŭ resaniĝas).

Paŝo tri: agordi defaŭltajn retajn politikojn por la pod

Kubernetes havas "platan" retan topografion; defaŭlte, ĉiuj balgoj komunikas rekte unu kun la alia. En iuj kazoj ĉi tio ne estas dezirinda.

Ebla sekureca problemo estas, ke atakanto povus uzi ununuran vundeblan aplikaĵon por sendi trafikon al ĉiuj podoj en la reto. Kiel ĉe multaj areoj de sekureco, la principo de malplej privilegio validas ĉi tie. Ideale, retaj politikoj devus eksplicite specifi kiuj ligoj inter podoj estas permesitaj kaj kiuj ne.

Ekzemple, malsupre estas simpla politiko, kiu neas ĉiun envenantan trafikon por specifa nomspaco:

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

Bildigo de ĉi tiu agordo:

Kvin maltrafoj dum deplojado de la unua aplikaĵo sur Kubernetes
(https://miro.medium.com/max/875/1*-eiVw43azgzYzyN1th7cZg.gif)
Pli da detaloj tie.

Paŝo kvar: kutima konduto uzante hokojn kaj init-ujojn

Unu el niaj ĉefaj celoj estis provizi deplojojn al Kubernetes sen malfunkcio por programistoj. Ĉi tio estas malfacila ĉar ekzistas multaj ebloj por fermi aplikojn kaj liberigi la rimedojn, kiujn ili uzis.

Apartaj malfacilaĵoj ekestis kun Nginx. Ni rimarkis, ke kiam ĉi tiuj balgoj estis deplojitaj sinsekve, aktivaj konektoj estis forigitaj antaŭ sukcesa kompletigo.

Post ampleksa esplorado interrete, rezultas, ke Kubernetes ne atendas, ke Nginx-konektoj elĉerpiĝu antaŭ ol ĉesigi la balgon. Uzante antaŭ-haltigan hokon, ni efektivigis la sekvan funkcion kaj tute forigis malfunkcion:

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

Sed 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

Alia ekstreme utila paradigmo estas la uzo de init-ujoj por pritrakti la ekfunkciigon de specifaj aplikoj. Ĉi tio estas precipe utila se vi havas rimed-intensan datumbazan migradprocezon, kiu devas funkcii antaŭ ol la aplikaĵo komenciĝas. Vi ankaŭ povas specifi pli altan rimedlimon por ĉi tiu procezo sen fiksi tian limon por la ĉefa aplikaĵo.

Alia ofta skemo estas aliri sekretojn en init-ujo kiu disponigas tiujn akreditaĵojn al la ĉefmodulo, kiu malhelpas neaŭtorizitan aliron al sekretoj de la ĉefaplikmodulo mem.

Kiel kutime, citu el la dokumentaro: Init-ujoj sekure funkcias laŭmendan kodon aŭ ilojn, kiuj alie reduktus la sekurecon de la aplikaĵa ujo bildo. Tenante nenecesajn ilojn apartaj, vi limigas la ataksurfacon de la aplikaĵa ujo-bildo.

Paŝo Kvin: Agordante la Kernon

Fine, ni parolu pri pli altnivela tekniko.

Kubernetes estas ekstreme fleksebla platformo, kiu ebligas al vi ruli laborŝarĝojn kiel vi konvenas. Ni havas kelkajn alt-efikecajn aplikojn, kiuj estas ekstreme intensaj rimedoj. Post farado de ampleksa ŝarĝtestado, ni malkovris, ke unu aplikaĵo luktis por trakti la atendatan trafikan ŝarĝon kiam defaŭltaj agordoj de Kubernetes efektiviĝis.

Tamen, Kubernetes permesas al vi ruli privilegiitan ujon, kiu ŝanĝas kernajn parametrojn nur por specifa pod. Jen kion ni uzis por ŝanĝi la maksimuman nombron da malfermitaj konektoj:

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

Ĉi tio estas pli altnivela tekniko, kiu ofte ne bezonas. Sed se via aplikaĵo luktas por elteni pezan ŝarĝon, vi povas provi ĝustigi iujn ĉi tiujn agordojn. Pli da detaloj pri ĉi tiu procezo kaj agordo de malsamaj valoroj - kiel ĉiam en la oficiala dokumentaro.

En konkludo

Kvankam Kubernetes povas ŝajni preta solvo el la skatolo, estas kelkaj ŝlosilaj paŝoj, kiujn vi devas fari por ke viaj aplikoj funkcias glate.

Dum via migrado de Kubernetes, gravas sekvi la "ŝarĝan testan ciklon": lanĉu la aplikaĵon, ŝarĝu testi ĝin, observu metrikojn kaj skalo-konduton, ĝustigu la agordon surbaze de tiuj datumoj, poste ripetu la ciklon denove.

Estu realisma pri via atendata trafiko kaj provu antaŭenpuŝi ĝin por vidi kiuj komponantoj rompiĝas unue. Kun ĉi tiu ripeta aliro, nur kelkaj el la listigitaj rekomendoj povas sufiĉi por atingi sukceson. Aŭ ĝi povas postuli pli profundan personigon.

Ĉiam demandu vin ĉi tiujn demandojn:

  1. Kiom da rimedoj konsumas aplikaĵoj kaj kiel ŝanĝiĝos ĉi tiu volumo?
  2. Kio estas la realaj skalaj postuloj? Kiom da trafiko la aplikaĵo traktos averaĝe? Kio pri pinta trafiko?
  3. Kiom ofte la servo bezonos grimpi horizontale? Kiom rapide necesas enretigi novajn podojn por ricevi trafikon?
  4. Kiel ĝuste la guŝoj fermiĝas? Ĉu ĉi tio entute estas necesa? Ĉu eblas atingi deplojon sen malfunkcio?
  5. Kiel vi povas minimumigi sekurecajn riskojn kaj limigi la damaĝon de iuj kompromititaj podoj? Ĉu iuj servoj havas permesojn aŭ aliron, kiujn ili ne postulas?

Kubernetes provizas nekredeblan platformon, kiu ebligas al vi utiligi plej bonajn praktikojn por disfaldi milojn da servoj en areto. Tamen ĉiu aplikaĵo estas malsama. Kelkfoje efektivigo postulas iom pli da laboro.

Feliĉe, Kubernetes provizas la necesan agordon por atingi ĉiujn teknikajn celojn. Uzante kombinaĵon de rimedpetoj kaj limoj, Liveness kaj Readiness-enketoj, init-ujoj, retaj politikoj kaj kutima kernel-agordado, vi povas atingi altan rendimenton kune kun misfunkciado kaj rapida skaleblo.

Kion alian legi:

  1. Plej bonaj Praktikoj kaj Plej Bonaj Praktikoj por Kurado de Ujoj kaj Kubernetes en Produktaj Medioj.
  2. 90+ Utilaj Iloj por Kubernetes: Deplojo, Administrado, Monitorado, Sekureco kaj Pli.
  3. Nia kanalo Ĉirkaŭ Kubernetes en Telegramo.

fonto: www.habr.com

Aldoni komenton