Vyf mis wanneer die eerste toepassing op Kubernetes ontplooi word

Vyf mis wanneer die eerste toepassing op Kubernetes ontplooi wordMisluk deur Aris Dreamer

Baie mense dink dat dit genoeg is om die toepassing na Kubernetes oor te dra (óf met Helm óf met die hand) - en daar sal geluk wees. Maar nie alles is so eenvoudig nie.

Span Mail.ru Wolkoplossings het 'n artikel deur DevOps-ingenieur Julian Gindy vertaal. Hy vertel watter slaggate sy maatskappy tydens die migrasieproses in die gesig gestaar het sodat jy nie op dieselfde hark trap nie.

Stap een: Stel Pod-versoeke en -limiete op

Kom ons begin deur 'n skoon omgewing op te stel waar ons peule sal loop. Kubernetes is wonderlik met peulskedulering en failover. Maar dit het geblyk dat die skeduleerder soms nie 'n peul kan plaas as dit moeilik is om te skat hoeveel hulpbronne dit nodig het om suksesvol te werk nie. Dit is waar versoeke vir hulpbronne en limiete opduik. Daar is baie debat oor die beste benadering om versoeke en limiete te stel. Soms lyk dit of dit eintlik meer 'n kuns as 'n wetenskap is. Hier is ons benadering.

Pod versoeke is die hoofwaarde wat deur die skeduleerder gebruik word om die peul optimaal te plaas.

Van Kubernetes dokumentasie: Die filterstap definieer 'n stel nodusse waar 'n Pod geskeduleer kan word. Byvoorbeeld, die PodFitsResources-filter kontroleer om te sien of 'n nodus genoeg hulpbronne het om spesifieke hulpbronversoeke van 'n peul te bevredig.

Ons gebruik aansoekversoeke op so 'n manier dat ons kan skat hoeveel hulpbronne in werklikheid Die toepassing het dit nodig om behoorlik te funksioneer. Op hierdie manier kan die skeduleerder die nodusse realisties plaas. Aanvanklik wou ons versoeke oorskeduleer om genoeg hulpbronne vir elke Pod te verseker, maar ons het opgemerk dat die skeduleringstyd aansienlik toegeneem het, en sommige Pods was nie ten volle geskeduleer nie, asof daar geen hulpbronversoeke daarvoor was nie.

In hierdie geval sal die skeduleerder dikwels die peule "uitdruk" en nie in staat wees om hulle te herskeduleer nie omdat die beheervliegtuig geen idee gehad het hoeveel hulpbronne die toepassing sou benodig nie, wat 'n sleutelkomponent van die skeduleringsalgoritme is.

Peul limiete is 'n duideliker limiet vir 'n peul. Dit verteenwoordig die maksimum hoeveelheid hulpbronne wat die groepering aan die houer sal toewys.

Weereens, van amptelike dokumentasie: As 'n houer 'n geheuelimiet van 4 GiB het, sal die kubelet (en die houerlooptyd) dit afdwing. Die looptyd verhoed dat die houer meer as die gespesifiseerde hulpbronlimiet gebruik. Byvoorbeeld, wanneer 'n proses in 'n houer probeer om meer as die toegelate hoeveelheid geheue te gebruik, beëindig die stelselkern die proses met 'n "buite geheue" (OOM)-fout.

'n Houer kan altyd meer hulpbronne gebruik as wat die hulpbronversoek spesifiseer, maar dit kan nooit meer as die limiet gebruik nie. Hierdie waarde is moeilik om korrek in te stel, maar dit is baie belangrik.

Ideaal gesproke wil ons hê dat die hulpbronvereistes van 'n peul gedurende die lewensiklus van 'n proses moet verander sonder om met ander prosesse in die stelsel in te meng - dit is die doel om perke te stel.

Ongelukkig kan ek nie spesifieke instruksies gee oor watter waardes om te stel nie, maar ons hou self by die volgende reëls:

  1. Met behulp van 'n lastoetsinstrument simuleer ons 'n basisvlak van verkeer en neem die gebruik van peulhulpbronne (geheue en verwerker) waar.
  2. Stel die pod-versoeke op 'n arbitrêr lae waarde (met 'n hulpbronlimiet van ongeveer 5 keer die versoekwaarde) en neem waar. Wanneer versoeke op 'n te laag vlak is, kan die proses nie begin nie, wat dikwels kriptiese Go-looptydfoute veroorsaak.

Ek neem kennis dat hoër hulpbronlimiete skedulering moeiliker maak omdat die peul 'n teikennodus benodig met genoeg hulpbronne beskikbaar.

Stel jou 'n situasie voor waar jy 'n liggewig webbediener het met 'n baie hoë hulpbronlimiet, soos 4 GB geheue. Hierdie proses sal waarskynlik horisontaal afgeskaal moet word, en elke nuwe peul sal op 'n nodus met ten minste 4 GB beskikbare geheue geskeduleer moet word. As daar nie so 'n nodus bestaan ​​nie, moet die groep 'n nuwe nodus instel om hierdie peul te verwerk, wat 'n rukkie kan neem. Dit is belangrik om 'n minimum verskil tussen hulpbronversoeke en limiete te bereik om vinnige en gladde skaal te verseker.

Stap twee: Stel lewenskragtigheid en gereedheidstoetse op

Dit is nog 'n subtiele onderwerp wat dikwels in die Kubernetes-gemeenskap bespreek word. Dit is belangrik om 'n goeie begrip van lewendheid- en gereedheidstoetse te hê, aangesien dit 'n meganisme bied vir stabiele werking van die sagteware en stilstand tot die minimum beperk. Dit kan egter u toepassing se werkverrigting ernstig beïnvloed as dit nie korrek opgestel is nie. Hieronder is 'n opsomming van wat beide monsters is.

Lewendigheid wys of die houer loop. As dit misluk, maak die kubelet die houer dood en die herbeginbeleid is daarvoor geaktiveer. As die houer nie toegerus is met 'n Liveness Probe nie, sal die verstektoestand sukses wees - soos in Kubernetes dokumentasie.

Lewendigheidsondersoeke moet goedkoop wees, d.w.s. nie baie hulpbronne verbruik nie, want hulle loop gereeld en moet Kubernetes inlig dat die toepassing loop.

As jy die opsie stel om elke sekonde te hardloop, sal dit 1 versoek per sekonde byvoeg, so wees bewus daarvan dat bykomende hulpbronne benodig sal word om hierdie verkeer te verwerk.

By ons maatskappy toets Liveness-toetse die kernkomponente van 'n toepassing, selfs al is die data (byvoorbeeld vanaf 'n afgeleë databasis of kas) nie ten volle beskikbaar nie.

Ons het 'n "gesondheid"-eindpunt in die toepassings opgestel wat bloot 'n 200-antwoordkode terugstuur. Dit is 'n aanduiding dat die proses aan die gang is en in staat is om versoeke te hanteer (maar nog nie verkeer nie).

toets gereedheid dui aan of die houer gereed is om versoeke te bedien. As die gereedheidsondersoek misluk, verwyder die eindpuntbeheerder die peul se IP-adres van die eindpunte van alle dienste wat by die peul pas. Dit word ook in die Kubernetes-dokumentasie vermeld.

Gereedheidsondersoeke verbruik meer hulpbronne, aangesien hulle die agterkant moet tref op so 'n manier dat dit wys dat die toepassing gereed is om versoeke te aanvaar.

Daar is baie debat in die gemeenskap oor of direk toegang tot die databasis verkry moet word. Met inagneming van die bokoste (die tjeks is gereeld, maar dit kan beheer word), het ons besluit dat vir sommige toepassings gereedheid om verkeer te bedien slegs getel word nadat gekontroleer is dat rekords van die databasis teruggestuur word. Goed ontwerpte gereedheidstoetse het hoër vlakke van beskikbaarheid verseker en stilstand tydens ontplooiing uitgeskakel.

As jy besluit om die databasis navraag te doen om die gereedheid van jou aansoek te toets, maak seker dit is so goedkoop as moontlik. Kom ons neem hierdie navraag:

SELECT small_item FROM table LIMIT 1

Hier is 'n voorbeeld van hoe ons hierdie twee waardes in Kubernetes konfigureer:

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

U kan 'n paar bykomende konfigurasie-opsies byvoeg:

  • initialDelaySeconds - hoeveel sekondes sal verloop tussen die lansering van die houer en die begin van die lansering van die sondes.
  • periodSeconds - waginterval tussen monsterlopies.
  • timeoutSeconds — die aantal sekondes waarna die peul as noodgeval beskou word. Normale time-out.
  • failureThreshold is die aantal toetsmislukkings voordat 'n herbeginsein na die peul gestuur word.
  • successThreshold is die aantal suksesvolle proewe voordat die peul oorgaan na die gereed toestand (na 'n mislukking wanneer die peul begin of herstel).

Stap Drie: Stel die Pod se versteknetwerkbeleide op

Kubernetes het 'n "plat" netwerktopografie, by verstek kommunikeer alle peule direk met mekaar. In sommige gevalle is dit nie wenslik nie.

'n Potensiële sekuriteitsprobleem is dat 'n aanvaller 'n enkele kwesbare toepassing kan gebruik om verkeer na alle peule op die netwerk te stuur. Soos in baie gebiede van sekuriteit, geld die beginsel van minste bevoorregting hier. Ideaal gesproke moet netwerkbeleide uitdruklik aandui watter verbindings tussen peule toegelaat word en watter nie.

Byvoorbeeld, die volgende is 'n eenvoudige beleid wat alle inkomende verkeer vir 'n spesifieke naamruimte weier:

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

Visualisering van hierdie konfigurasie:

Vyf mis wanneer die eerste toepassing op Kubernetes ontplooi word
(https://miro.medium.com/max/875/1*-eiVw43azgzYzyN1th7cZg.gif)
Meer besonderhede hier.

Stap vier: Pasgemaakte gedrag met hake en inithouers

Een van ons hoofdoelwitte was om ontplooiings in Kubernetes te verskaf sonder stilstand vir ontwikkelaars. Dit is moeilik omdat daar baie opsies is om toepassings af te sluit en hul gebruikte hulpbronne vry te stel.

Besondere probleme het ontstaan ​​met Nginx. Ons het opgemerk dat wanneer hierdie Pods in volgorde ontplooi is, aktiewe verbindings onderbreek is voordat dit suksesvol voltooi is.

Na uitgebreide navorsing op die internet het dit geblyk dat Kubernetes nie wag dat Nginx-verbindings hulself uitput voordat hy die peul afskakel nie. Met die hulp van die voorstophaak het ons die volgende funksionaliteit geïmplementeer en heeltemal van die stilstand ontslae geraak:

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

Maar 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

Nog 'n uiters nuttige paradigma is die gebruik van inithouers om die bekendstelling van spesifieke toepassings te hanteer. Dit is veral nuttig as jy 'n hulpbron-intensiewe databasismigrasieproses het wat uitgevoer moet word voordat die toepassing begin. Jy kan ook 'n hoër hulpbronlimiet vir hierdie proses spesifiseer sonder om so 'n limiet vir die hooftoepassing te stel.

Nog 'n algemene skema is om toegang tot geheime in die inithouer te verkry, wat hierdie geloofsbriewe aan die hoofmodule verskaf, wat ongemagtigde toegang tot geheime vanaf die hooftoepassingsmodule self verhoed.

Soos gewoonlik, 'n aanhaling uit die dokumentasie: init-houers kan gebruikerskode of nutsprogramme veilig laat loop wat andersins die sekuriteit van die toepassing se houerbeeld in die gedrang sou bring. Deur onnodige gereedskap apart te hou, beperk jy die aanvaloppervlak van die toepassing se houerbeeld.

Stap Vyf: Kernelkonfigurasie

Laastens, kom ons praat oor 'n meer gevorderde tegniek.

Kubernetes is 'n uiters buigsame platform wat jou toelaat om werkladings uit te voer soos jy goeddink. Ons het 'n aantal hoogs doeltreffende toepassings wat uiters hulpbronintensief is. Nadat ons uitgebreide vragtoetse gedoen het, het ons gevind dat een van die toepassings dit moeilik gehad het om tred te hou met die verwagte verkeerslading toe die standaard Kubernetes-instellings in werking was.

Kubernetes laat jou egter toe om 'n bevoorregte houer te laat loop wat slegs kernparameters vir 'n spesifieke peul verander. Hier is wat ons gebruik het om die maksimum aantal oop verbindings te verander:

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

Dit is 'n meer gevorderde tegniek wat dikwels nie nodig is nie. Maar as jou toepassing sukkel om 'n swaar vrag te hanteer, kan jy probeer om sommige van hierdie instellings aan te pas. Meer inligting oor hierdie proses en die instelling van verskillende waardes - soos altyd in die amptelike dokumentasie.

Ten slotte

Alhoewel Kubernetes dalk na 'n out-of-the-box oplossing lyk, is daar 'n paar sleutelstappe wat geneem moet word om toepassings glad te laat loop.

Gedurende die migrasie na Kubernetes is dit belangrik om die "ladingstoetssiklus" te volg: hardloop die toepassing, toets dit onder lading, neem die statistieke en skaalgedrag waar, pas die konfigurasie aan gebaseer op hierdie data, en herhaal dan hierdie siklus weer.

Wees realisties oor verwagte verkeer en probeer verder gaan om te sien watter komponente eerste breek. Met hierdie iteratiewe benadering kan slegs 'n paar van die gelyste aanbevelings genoeg wees om sukses te behaal. Of dit kan meer in-diepte aanpassing vereis.

Vra jouself altyd hierdie vrae:

  1. Hoeveel hulpbronne verbruik toepassings en hoe sal hierdie bedrag verander?
  2. Wat is die werklike skaalvereistes? Hoeveel verkeer sal die toepassing gemiddeld hanteer? Wat van spitsverkeer?
  3. Hoe gereeld sal die diens moet uitskaal? Hoe vinnig moet nuwe peule aan die gang wees om verkeer te ontvang?
  4. Hoe grasieus word peule gesluit? Is dit hoegenaamd nodig? Is dit moontlik om ontplooiing te bereik sonder stilstand?
  5. Hoe om sekuriteitsrisiko's te verminder en skade van enige gekompromitteerde peule te beperk? Het enige dienste toestemmings of toegang wat hulle nie nodig het nie?

Kubernetes bied 'n ongelooflike platform wat jou toelaat om beste praktyke te gebruik om duisende dienste in 'n groep te ontplooi. Alle toepassings verskil egter. Soms verg implementering 'n bietjie meer werk.

Gelukkig bied Kubernetes die nodige instellings om alle tegniese doelwitte te bereik. Deur 'n kombinasie van hulpbronversoeke en -limiete, lewendheid- en gereedheidsondersoeke, inithouers, netwerkbeleide en pasgemaakte kerninstelling te gebruik, kan u hoë werkverrigting tesame met fouttoleransie en vinnige skaalbaarheid bereik.

Wat anders om te lees:

  1. Beste praktyke en beste praktyke vir die bestuur van houers en Kubernetes in produksie-omgewings.
  2. 90+ Nuttige nutsmiddels vir Kubernetes: ontplooiing, bestuur, monitering, sekuriteit en meer.
  3. Ons kanaal Around Kubernetes in Telegram.

Bron: will.com

Voeg 'n opmerking