Så här kommer du åt Kubernetes Pod-resurser

Så här kommer du åt Kubernetes Pod-resurserBelöningen av Tohad

När man börjar med Kubernetes är det vanligt att man glömmer att ställa in containerresurser. Vid det här laget räcker det för att säkerställa att Docker-avbildningen fungerar och kan distribueras till Kubernetes-klustret.

Men senare måste applikationen distribueras i ett produktionskluster tillsammans med andra applikationer. För att göra detta måste du allokera resurser för behållaren och se till att det finns tillräckligt många för att få igång applikationen och att andra applikationer som körs inte kommer att uppleva problem.

Team Kubernetes aaS från Mail.ru översatt en artikel om containerresurser (CPU & MEM), förfrågningar och resursbegränsningar. Du kommer att lära dig fördelarna med dessa inställningar och vad som händer om du inte ställer in dem.

Datorresurser

Vi har två typer av resurser med följande enheter:

  • Central processing unit (CPU) - kärnor;
  • Minne (MEM) - byte.

Resurser anges för varje behållare. I följande Pod YAML-fil kommer du att se en resurssektion som innehåller de begärda och begränsade resurserna:

  • Begärda podresurser = summan av begärda resurser för alla behållare;
  • Pod-resursgräns = Summan av alla pod-resursgränser.

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

Exempel på begärda och begränsade resurser

Fält resources.requested från specifikationen Pod är ett av elementen som används för att hitta den önskade noden. Du kan redan planera Pod-distribution för det. Hur hittar man en lämplig nod?

Kubernetes består av flera komponenter, inklusive en masternod eller masternod (Kubernetes Control Plane). Masternoden har flera processer: kube-apiserver, kube-controller-manager och kube-scheduler.

Kube-scheduler-processen är ansvarig för att granska nyskapade pods och hitta möjliga arbetarnoder som matchar alla pod-förfrågningar, inklusive antalet begärda resurser. Listan över noder som hittats av kube-scheduler rankas. Podden är schemalagd på noden med de högsta poängen.

Så här kommer du åt Kubernetes Pod-resurserVar ska den lila podden placeras?

På bilden kan du se att kube-scheduler bör schemalägga en ny lila Pod. Kubernetes-klustret innehåller två noder: A och B. Som du kan se kan kube-scheduler inte schemalägga en Pod på nod A - de tillgängliga (obegärda) resurserna matchar inte förfrågningarna från den lila Pod. Så den 1 GB minne som begärs av den lila Pod kommer inte att passa på nod A, eftersom det tillgängliga minnet är 0,5 GB. Men nod B har tillräckligt med resurser. Som ett resultat bestämmer kube-scheduler att destinationen för den lila Poden är nod B.

Nu vet vi hur de begärda resurserna påverkar valet av nod för att köra Pod. Men vad är effekten av marginalresurser?

Resursgränsen är en gräns som CPU/MEM inte kan passera. CPU-resursen är dock flexibel, så behållare som når sina CPU-gränser kommer inte att få Poden att avslutas. Istället börjar CPU-strypningen. Om MEM-användningsgränsen nås kommer behållaren att stoppas på grund av OOM-Killer och startas om om det tillåts av RestartPolicy-inställningen.

Begärda och maximala resurser i detalj

Så här kommer du åt Kubernetes Pod-resurserResurskommunikation mellan Docker och Kubernetes

Det bästa sättet att förklara hur resursbegäranden och resursbegränsningar fungerar är att introducera relationen mellan Kubernetes och Docker. I bilden ovan kan du se hur Kubernetes-fälten och Docker-startflaggor är relaterade.

Minne: begäran och begränsning

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

Som nämnts ovan mäts minnet i byte. Baserat på Kubernetes dokumentation, kan vi ange minne som ett tal. Vanligtvis är det ett heltal, till exempel 2678 - det vill säga 2678 byte. Du kan också använda suffix G и Gi, det viktigaste är att komma ihåg att de inte är likvärdiga. Den första är decimal och den andra är binär. Som exemplet som nämns i k8s-dokumentationen: 128974848, 129e6, 129M, 123Mi - de är praktiskt taget likvärdiga.

Kubernetes-alternativ limits.memory matchar flaggan --memory från Docker. I fall att request.memory Det finns ingen pil för Docker eftersom Docker inte använder det här fältet. Du kan fråga dig, är detta ens nödvändigt? Ja behöver. Som jag sa tidigare är fältet viktigt för Kubernetes. Baserat på informationen från den bestämmer kube-scheduler vilken nod som ska schemaläggas för Poden.

Vad händer om du ställer in otillräckligt minne för en begäran?

Om behållaren har nått gränserna för det begärda minnet, placeras Poden i en grupp Pods som stannar när det inte finns tillräckligt med minne i noden.

Vad händer om du ställer in minnesgränsen för lågt?

Om behållaren överskrider minnesgränsen kommer den att avslutas på grund av OOM-Killed. Och kommer att starta om om möjligt baserat på RestartPolicy där standardvärdet är Always.

Vad händer om du inte anger det begärda minnet?

Kubernetes tar gränsvärdet och ställer in det som standardvärde.

Vad kan hända om du inte anger en minnesgräns?

Behållaren har inga begränsningar, den kan använda så mycket minne som den vill. Om han börjar använda allt tillgängligt minne i noden, kommer OOM att döda honom. Behållaren kommer sedan att startas om om möjligt baserat på RestartPolicy.

Vad händer om du inte anger minnesgränser?

Detta är det värsta scenariot: schemaläggaren vet inte hur många resurser behållaren kräver, och detta kan orsaka allvarliga problem på noden. I det här fallet skulle det vara trevligt att ha standardgränser för namnutrymmet (inställt av LimitRange). Det finns inga standardgränser - Podden har inga gränser, den kan använda så mycket minne den vill.

Om det begärda minnet är mer än vad noden kan erbjuda, kommer podden inte att schemaläggas. Det är viktigt att komma ihåg det Requests.memory - inte minimivärdet. Detta är en beskrivning av mängden minne som är tillräcklig för att hålla behållaren igång kontinuerligt.

Det rekommenderas vanligtvis att ställa in samma värde för request.memory и limit.memory. Detta säkerställer att Kubernetes inte kommer att schemalägga en Pod på en nod som har tillräckligt med minne för att köra Pod men inte tillräckligt för att köra den. Kom ihåg: Kubernetes Pod-planering tar bara hänsyn requests.memoryOch limits.memory tar inte hänsyn till.

CPU: begäran och gräns

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

Med en CPU är allt lite mer komplicerat. Återgå till bilden av förhållandet mellan Kubernetes och Docker, du kan se det request.cpu motsvarar --cpu-shares, medan limit.cpu matchar flaggan cpus i Docker.

CPU:n som Kubernetes begär multipliceras med 1024, andelen CPU-cykler. Om du vill begära 1 hel kärna måste du lägga till cpu: 1som visas ovan.

Att begära en fullständig kärna (proportion = 1024) betyder inte att din behållare kommer att ta emot den. Om din värddator bara har en kärna och du kör mer än en behållare, måste alla behållare dela den tillgängliga CPU:n mellan sig. Hur går det till? Låt oss titta på bilden.

Så här kommer du åt Kubernetes Pod-resurser
CPU-begäran - Single Core System

Låt oss föreställa oss att du har ett enkärnigt värdsystem som kör containrar. Mamma (Kubernetes) bakade en paj (CPU) och vill dela den mellan barn (containrar). Tre barn vill ha en hel paj (andel = 1024), ett annat barn vill ha en halv paj (512). Mamma vill vara rättvis och gör en enkel uträkning.

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

Baserat på beräkningen kommer tre barn att få 28 % av kärnan, och inte hela kärnan. Det fjärde barnet får 14 % av hela kärnan, inte hälften. Men saker och ting blir annorlunda om du har ett system med flera kärnor.

Så här kommer du åt Kubernetes Pod-resurser
CPU-begäran - Multi-Core (4) System

På bilden ovan kan du se att tre barn vill ha en hel paj, och ett vill ha hälften. Eftersom mamma bakade fyra pajer får vart och ett av hennes barn så många de vill. I ett flerkärnigt system är processorresurser fördelade över alla tillgängliga processorkärnor. Om en behållare är begränsad till mindre än en full CPU-kärna kan den fortfarande använda den till 100 %.

Ovanstående beräkningar är förenklade för att förstå hur CPU fördelas mellan behållare. Naturligtvis, förutom själva behållarna, finns det andra processer som också använder CPU-resurser. När processer i en behållare är inaktiva kan andra använda dess resurs. CPU: "200m" motsvarar CPU: 0,2, vilket betyder ungefär 20 % av en kärna.

Låt oss nu prata om limit.cpu. CPU:n som Kubernetes begränsar multipliceras med 100. Resultatet är hur lång tid som behållaren kan använda var 100 µs (cpu-period).

limit.cpu matchar Docker-flaggan --cpus. Detta är en ny kombination av gammalt --cpu-period и --cpu-quota. Genom att ställa in den anger vi hur många tillgängliga CPU-resurser som behållaren maximalt kan använda innan strypningen börjar:

  • processorer - kombination cpu-period и cpu-quota. cpus = 1.5 motsvarande inställning cpu-period = 100000 и cpu-quota = 150000;
  • CPU-period - punkt CPU CFS-schemaläggare, standard 100 mikrosekunder;
  • cpu-kvot - antal mikrosekunder inuti cpu-period, som avgränsas av behållaren.

Vad händer om du installerar otillräcklig efterfrågad CPU?

Om behållaren behöver mer än den har installerat kommer den att stjäla CPU från andra processer.

Vad händer om du ställer in CPU-gränsen för lågt?

Eftersom CPU-resursen är justerbar kommer strypningen att aktiveras.

Vad händer om du inte anger en CPU-begäran?

Precis som med minnet är förfrågningsvärdet lika med gränsen.

Vad händer om du inte anger en CPU-gräns?

Behållaren kommer att använda så mycket CPU som den behöver. Om en standard CPU-policy (LimitRange) är definierad i namnområdet, används denna gräns även för behållaren.

Vad händer om du inte anger vare sig en begäran eller en CPU-gräns?

Precis som med minnet är detta det värsta scenariot. Schemaläggaren vet inte hur många resurser din behållare behöver, och detta kan orsaka allvarliga problem på noden. För att undvika detta måste du ställa in standardgränser för namnutrymmen (LimitRange).

Kom ihåg: om du begär mer CPU än noderna kan ge, kommer Poden inte att schemaläggas. Requests.cpu - inte minimivärdet, utan ett värde som är tillräckligt för att starta Poden och fungera utan fel. Om applikationen inte utför komplicerade beräkningar är det bästa alternativet att installera request.cpu <= 1 och starta så många repliker som behövs.

Idealisk mängd begärda resurser eller resursgräns

Vi lärde oss om begränsningen av datorresurser. Nu är det dags att svara på frågan: "Hur många resurser kräver min Pod för att köra programmet utan problem? Vad är den ideala mängden?

Tyvärr finns det inga tydliga svar på dessa frågor. Om du inte vet hur din applikation fungerar eller hur mycket CPU eller minne den behöver, är det bästa alternativet att ge applikationen mycket minne och CPU och sedan köra prestandatester.

Förutom prestandatester, övervaka applikationens beteende vid övervakning i en vecka. Om diagrammen visar att din applikation förbrukar färre resurser än du begärde kan du minska mängden CPU eller minne som efterfrågas.

Se detta som ett exempel Grafana instrumentbräda. Den visar skillnaden mellan de begärda resurserna eller resursgränsen och den aktuella resursanvändningen.

Slutsats

Att begära och begränsa resurser hjälper till att hålla ditt Kubernetes-kluster friskt. Korrekt gränskonfiguration minimerar kostnaderna och håller applikationerna igång hela tiden.

Kort sagt, det finns några saker att tänka på:

  1. Begärda resurser är en konfiguration som beaktas vid uppstart (när Kubernetes planerar att vara värd för programmet). Däremot är det viktigt att begränsa resurser under körning – när applikationen redan körs på noden.
  2. Jämfört med minne är CPU:n en reglerad resurs. Om det inte finns tillräckligt med CPU kommer din Pod inte att stängas av och gasspjällsmekanismen slås på.
  3. Begärda resurser och resursgräns är inte minimi- och maximivärden! Genom att definiera de resurser som efterfrågas säkerställer du att applikationen körs utan problem.
  4. En bra praxis är att ställa in minnesbegäran lika med minnesgränsen.
  5. Ok installation begärd CPU <=1, om applikationen inte utför komplexa beräkningar.
  6. Om du begär fler resurser än vad som är tillgängliga på en nod, kommer Podden aldrig att schemaläggas till den noden.
  7. För att bestämma rätt mängd begärda resurser/resursgränser, använd belastningstestning och övervakning.

Jag hoppas att den här artikeln hjälper dig att förstå det grundläggande konceptet med resursbegränsning. Och du kommer att kunna tillämpa denna kunskap i ditt arbete.

Lycka!

Vad mer att läsa:

  1. SRE Observerbarhet: Namnutrymmen och metrisk struktur.
  2. Över 90 användbara verktyg för Kubernetes: distribution, hantering, övervakning, säkerhet och mer.
  3. Vår kanal Around Kubernetes i Telegram.

Källa: will.com

Lägg en kommentar