Slik får du tilgang til Kubernetes Pod-ressurser

Slik får du tilgang til Kubernetes Pod-ressurserBelønningen av Tohad

Når du starter med Kubernetes, er det vanlig å glemme å sette opp containerressurser. På dette tidspunktet er det nok å sikre at Docker-bildet fungerer og kan distribueres til Kubernetes-klyngen.

Men senere må applikasjonen distribueres i en produksjonsklynge sammen med andre applikasjoner. For å gjøre dette må du tildele ressurser til beholderen og sørge for at det er nok av dem til å få applikasjonen i gang, og at andre kjørende applikasjoner ikke vil oppleve problemer.

Lag Kubernetes aaS fra Mail.ru oversatte en artikkel om containerressurser (CPU & MEM), forespørsler og ressursbegrensninger. Du vil lære fordelene med disse innstillingene og hva som skjer hvis du ikke angir dem.

Dataressurser

Vi har to typer ressurser med følgende enheter:

  • Sentral prosesseringsenhet (CPU) - kjerner;
  • Minne (MEM) - byte.

Ressurser er spesifisert for hver beholder. I følgende Pod YAML-fil vil du se en ressursseksjon som inneholder de forespurte og begrensede ressursene:

  • Forespurte Pod-ressurser = summen av forespurte ressurser for alle beholdere;
  • Pod-ressursgrense = Summen av alle pod-ressursgrenser.

apiVersion: v1
kind: Pod
metadata:
  name: backend-pod-name
  labels:
    application: backend
spec:
  containers:
    — name: main-container
      image: my-backend
      tag: v1
      ports:
      — containerPort: 8080
      resources:
        requests:
          cpu: 0.2 # REQUESTED CPU: 200m cores
          memory: "1Gi" # REQUESTED MEM: 1Gi
        limits:
          cpu: 1 # MAX CPU USAGE: 1 core
          memory: "1Gi" # MAX MEM USAGE:  1Gi
    — name: other-container
      image: other-app
      tag: v1
      ports:
      — containerPort: 8000
      resources:
        requests:
          cpu: "200m" # REQUESTED CPU: 200m cores
          memory: "0.5Gi" # REQUESTED MEM: 0.5Gi
        limits:
          cpu: 1 # MAX CPU USAGE: 1 core
          memory: "1Gi" # MAX MEM USAGE:  1Gi

Eksempel på forespurte og begrensede ressurser

Feltet resources.requested fra spesifikasjonen Pod er et av elementene som brukes for å finne ønsket node. Du kan allerede planlegge Pod-distribusjon for det. Hvordan finner du en passende node?

Kubernetes består av flere komponenter, inkludert en masternode eller masternode (Kubernetes Control Plane). Hovednoden har flere prosesser: kube-apiserver, kube-controller-manager og kube-scheduler.

Kube-planleggingsprosessen er ansvarlig for å gjennomgå nyopprettede pods og finne mulige arbeidernoder som samsvarer med alle pod-forespørsler, inkludert antall forespurte ressurser. Listen over noder funnet av kube-scheduler er rangert. Poden er planlagt på noden med høyest poengsum.

Slik får du tilgang til Kubernetes Pod-ressurserHvor skal den lilla poden plasseres?

På bildet kan du se at kube-planlegger skal planlegge en ny lilla Pod. Kubernetes-klyngen inneholder to noder: A og B. Som du kan se, kan ikke kube-scheduler planlegge en Pod på node A - de tilgjengelige (uønskede) ressursene samsvarer ikke med forespørslene til den lilla Poden. Så 1 GB minne som den lilla Pod ber om, vil ikke passe på node A, siden det tilgjengelige minnet er 0,5 GB. Men node B har nok ressurser. Som et resultat bestemmer kube-planlegger at destinasjonen til den lilla Pod er node B.

Nå vet vi hvordan de forespurte ressursene påvirker valget av node for å kjøre Pod. Men hva er effekten av marginale ressurser?

Ressursgrensen er en grense som CPU/MEM ikke kan krysse. CPU-ressursen er imidlertid fleksibel, så beholdere som når CPU-grensene vil ikke føre til at Pod-en avsluttes. I stedet vil CPU-struping starte. Hvis MEM-bruksgrensen nås, vil beholderen stoppes på grunn av OOM-Killer og startes på nytt hvis tillatt av RestartPolicy-innstillingen.

Forespurte og maksimale ressurser i detalj

Slik får du tilgang til Kubernetes Pod-ressurserRessurskommunikasjon mellom Docker og Kubernetes

Den beste måten å forklare hvordan ressursforespørsler og ressursgrenser fungerer, er å introdusere forholdet mellom Kubernetes og Docker. På bildet ovenfor kan du se hvordan Kubernetes-feltene og Docker-oppstartsflaggene er relatert.

Minne: forespørsel og begrensning

containers:
...
 resources:
   requests:
     memory: "0.5Gi"
   limits:
     memory: "1Gi"

Som nevnt ovenfor måles minne i byte. Basert på Kubernetes dokumentasjon, kan vi spesifisere minne som et tall. Vanligvis er det et heltall, for eksempel 2678 - det vil si 2678 byte. Du kan også bruke suffikser G и Gi, det viktigste er å huske at de ikke er likeverdige. Den første er desimal og den andre er binær. Som eksemplet nevnt i k8s-dokumentasjonen: 128974848, 129e6, 129M, 123Mi - de er praktisk talt likeverdige.

Kubernetes-alternativ limits.memory matcher flagget --memory fra Docker. I tilfelle request.memory Det er ingen pil for Docker fordi Docker ikke bruker dette feltet. Du kan spørre, er dette i det hele tatt nødvendig? Ja trenger. Som jeg sa før, er feltet viktig for Kubernetes. Basert på informasjonen fra den, bestemmer kube-scheduler hvilken node som skal planlegges Pod.

Hva skjer hvis du angir utilstrekkelig minne for en forespørsel?

Hvis beholderen har nådd grensene for det forespurte minnet, plasseres Poden i en gruppe Pods som stopper når det ikke er nok minne i noden.

Hva skjer hvis du setter minnegrensen for lavt?

Hvis beholderen overskrider minnegrensen, vil den bli avsluttet på grunn av OOM-Killed. Og vil starte på nytt hvis mulig basert på RestartPolicy der standardverdien er Always.

Hva skjer hvis du ikke spesifiserer det forespurte minnet?

Kubernetes vil ta grenseverdien og sette den som standardverdi.

Hva kan skje hvis du ikke angir en minnegrense?

Beholderen har ingen begrensninger; den kan bruke så mye minne den vil. Hvis han begynner å bruke alt tilgjengelig minne i noden, vil OOM drepe ham. Beholderen vil deretter startes på nytt hvis mulig basert på RestartPolicy.

Hva skjer hvis du ikke angir minnegrenser?

Dette er det verste scenarioet: planleggeren vet ikke hvor mange ressurser containeren krever, og dette kan forårsake alvorlige problemer på noden. I dette tilfellet ville det være fint å ha standardgrenser på navneområdet (angitt av LimitRange). Det er ingen standardgrenser - Poden har ingen grenser, den kan bruke så mye minne den vil.

Hvis det forespurte minnet er mer enn noden kan tilby, vil ikke poden bli planlagt. Det er viktig å huske det Requests.memory - ikke minimumsverdien. Dette er en beskrivelse av mengden minne som er tilstrekkelig til å holde beholderen i gang kontinuerlig.

Det anbefales vanligvis å sette samme verdi for request.memory и limit.memory. Dette sikrer at Kubernetes ikke vil planlegge en Pod på en node som har nok minne til å kjøre Pod, men ikke nok til å kjøre den. Husk: Kubernetes Pod-planlegging tar bare hensyn requests.memoryOg limits.memory tar ikke hensyn til.

CPU: forespørsel og begrensning

containers:
...
 resources:
   requests:
     cpu: 1
   limits:
     cpu: "1200m"

Med en CPU er alt litt mer komplisert. Når du går tilbake til bildet av forholdet mellom Kubernetes og Docker, kan du se det request.cpu соответствует --cpu-shares, mens limit.cpu matcher flagget cpus i Docker.

CPU-en som Kubernetes ber om, multipliseres med 1024, andelen CPU-sykluser. Hvis du vil be om 1 full kjerne, må du legge til cpu: 1som vist ovenfor.

Å be om en full kjerne (proporsjon = 1024) betyr ikke at beholderen din vil motta den. Hvis vertsmaskinen din bare har én kjerne og du kjører mer enn én beholder, må alle beholderne dele den tilgjengelige CPU-en mellom seg. Hvordan skjer dette? La oss se på bildet.

Slik får du tilgang til Kubernetes Pod-ressurser
CPU-forespørsel - Single Core System

La oss forestille oss at du har et vertssystem med én kjerne som kjører containere. Mamma (Kubernetes) bakte en pai (CPU) og vil dele den mellom barn (beholdere). Tre barn vil ha en hel pai (proporsjon = 1024), et annet barn vil ha en halv pai (512). Mamma vil være rettferdig og gjør et enkelt regnestykke.

# Сколько пирогов хотят дети?
# 3 ребенка хотят по целому пирогу и еще один хочет половину пирога
cakesNumberKidsWant = (3 * 1) + (1 * 0.5) = 3.5
# Выражение получается так:
3 (ребенка/контейнера) * 1 (целый пирог/полное ядро) + 1 (ребенок/контейнер) * 0.5 (половина пирога/половина ядра)
# Сколько пирогов испечено?
availableCakesNumber = 1
# Сколько пирога (максимально) дети реально могут получить?
newMaxRequest = 1 / 3.5 =~ 28%

Ut fra beregningen vil tre barn få 28 % av kjernen, og ikke hele kjernen. Det fjerde barnet vil få 14 % av hele kjernen, ikke halvparten. Men ting vil være annerledes hvis du har et flerkjernesystem.

Slik får du tilgang til Kubernetes Pod-ressurser
CPU-forespørsel - Multi-Core (4) System

På bildet over kan du se at tre barn vil ha en hel pai, og ett vil ha halvparten. Siden mamma bakte fire paier, vil hvert av barna hennes få så mange de vil. I et flerkjernesystem er prosessorressurser fordelt på alle tilgjengelige prosessorkjerner. Hvis en beholder er begrenset til mindre enn én full CPU-kjerne, kan den fortsatt bruke den på 100 %.

Beregningene ovenfor er forenklet for å forstå hvordan CPU er fordelt mellom containere. Foruten selve containerne er det selvfølgelig andre prosesser som også bruker CPU-ressurser. Når prosesser i én beholder er inaktive, kan andre bruke ressursen. CPU: "200m" соответствует CPU: 0,2, som betyr omtrent 20 % av én kjerne.

La oss nå snakke om limit.cpu. CPU-en som Kubernetes begrenser multipliseres med 100. Resultatet er hvor lang tid beholderen kan bruke hver 100 µs (cpu-period).

limit.cpu samsvarer med Docker-flagget --cpus. Dette er en ny kombinasjon av gammelt --cpu-period и --cpu-quota. Ved å sette den, indikerer vi hvor mange tilgjengelige CPU-ressurser beholderen maksimalt kan bruke før struping begynner:

  • CPUer - kombinasjon cpu-period и cpu-quota. cpus = 1.5 tilsvarende innstilling cpu-period = 100000 и cpu-quota = 150000;
  • CPU-periode - periode CPU CFS-planlegger, standard 100 mikrosekunder;
  • cpu-kvote - antall mikrosekunder inne cpu-period, som er avgrenset av beholderen.

Hva skjer hvis du ikke installerer nok forespurt CPU?

Hvis beholderen trenger mer enn den har installert, vil den stjele CPU fra andre prosesser.

Hva skjer hvis du setter CPU-grensen for lavt?

Siden CPU-ressursen er justerbar, slås gassen på.

Hva skjer hvis du ikke spesifiserer en CPU-forespørsel?

Som med minne er forespørselsverdien lik grensen.

Hva skjer hvis du ikke spesifiserer en CPU-grense?

Beholderen vil bruke så mye CPU som den trenger. Hvis en standard CPU-policy (LimitRange) er definert i navneområdet, brukes denne grensen også for beholderen.

Hva skjer hvis du ikke spesifiserer verken en forespørsel eller en CPU-grense?

Som med hukommelse, er dette det verste tilfellet. Planleggeren vet ikke hvor mange ressurser beholderen din trenger, og dette kan forårsake alvorlige problemer på noden. For å unngå dette må du angi standardgrenser for navneområder (LimitRange).

Husk: hvis du ber om mer CPU enn nodene kan gi, vil ikke poden bli planlagt. Requests.cpu - ikke minimumsverdien, men en verdi tilstrekkelig til å starte Poden og fungere uten feil. Hvis applikasjonen ikke utfører komplekse beregninger, er det beste alternativet å installere request.cpu <= 1 og lanser så mange replikaer som nødvendig.

Ideell mengde forespurte ressurser eller ressursgrense

Vi lærte om begrensningene til dataressurser. Nå er det på tide å svare på spørsmålet: "Hvor mange ressurser krever Pod-en min for å kjøre applikasjonen uten problemer? Hva er den ideelle mengden?

Dessverre er det ingen klare svar på disse spørsmålene. Hvis du ikke vet hvordan applikasjonen din fungerer eller hvor mye CPU eller minne den trenger, er det beste alternativet å gi applikasjonen mye minne og CPU og deretter kjøre ytelsestester.

I tillegg til ytelsestester, overvåk applikasjonens oppførsel ved overvåking i en uke. Hvis grafene indikerer at applikasjonen din bruker færre ressurser enn du ba om, kan du redusere mengden CPU eller minne som kreves.

Se dette som eksempel Grafana dashbord. Den viser forskjellen mellom de forespurte ressursene eller ressursgrensen og gjeldende ressursbruk.

Konklusjon

Å be om og begrense ressurser bidrar til å holde Kubernetes-klyngen sunn. Riktig grensekonfigurasjon minimerer kostnadene og holder applikasjoner i gang til enhver tid.

Kort sagt, det er et par ting å huske på:

  1. Forespurte ressurser er en konfigurasjon som tas i betraktning ved oppstartstid (når Kubernetes planlegger å være vert for applikasjonen). I motsetning til dette er det viktig å begrense ressurser under kjøring – når applikasjonen allerede kjører på noden.
  2. Sammenlignet med minne er CPU en regulert ressurs. Hvis det ikke er nok CPU, vil ikke Pod-en slå seg av og strupemekanismen slås på.
  3. Forespurte ressurser og ressursgrense er ikke minimums- og maksimumsverdier! Ved å definere ressursene som forespørres, sikrer du at applikasjonen kjører uten problemer.
  4. En god praksis er å sette minneforespørselen lik minnegrensen.
  5. Ok installering forespurt CPU <=1, hvis applikasjonen ikke utfører komplekse beregninger.
  6. Hvis du ber om flere ressurser enn det som er tilgjengelig på en node, vil Poden aldri bli planlagt til den noden.
  7. For å bestemme riktig mengde forespurte ressurser/ressursgrenser, bruk belastningstesting og overvåking.

Jeg håper denne artikkelen hjelper deg å forstå det grunnleggende konseptet med ressursbegrensning. Og du vil kunne bruke denne kunnskapen i arbeidet ditt.

Lykke til!

Hva annet å lese:

  1. SRE observerbarhet: navnerom og metrisk struktur.
  2. 90+ nyttige verktøy for Kubernetes: distribusjon, administrasjon, overvåking, sikkerhet og mer.
  3. Vår kanal Around Kubernetes i Telegram.

Kilde: www.habr.com

Legg til en kommentar