Visuell guide för felsökning i Kubernetes

Obs. övers.: Denna artikel ingår i de publika resurserna från projektet learnk8s, som utbildar i arbete med Kubernetes för företag och individuella administratörer. I den delar Daniele Polencic, projektledaren, med sig av en tydlig instruktion om vilka steg som bör vidtas vid allmänna problem med applikationer som körs i K8s-klustret.

Visuell guide för felsökning i Kubernetes

TL;DR: här är en schematisk översikt som kan hjälpa dig att felsöka deployment i Kubernetes:

Visuell guide för felsökning i Kubernetes

Flödesschema för att hitta och rätta till fel i klustret. Den finns i original (på engelska) i PDF och som en bild.

När man distribuerar en applikation i Kubernetes måste man vanligtvis definiera tre komponenter:

  • Deployment — en slags recept för att skapa kopior av applikationen, kallade poddar;
  • Tjänst — en intern lastbalanserare som distribuerar trafiken mellan poddarna;
  • Ingress — en beskrivning av hur trafiken kommer att nå tjänsten från den externa världen.

Här är en kort grafisk sammanfattning:

1) I Kubernetes får applikationerna trafik från omvärlden genom två lager av lastbalanserare: intern och extern.

Visuell guide för felsökning i Kubernetes

2) Den interna lastbalanseraren kallas Service, den externa – Ingress.

Visuell guide för felsökning i Kubernetes

3) Deployment skapar poddar och övervakar dem (de skapas inte manuellt).

Visuell guide för felsökning i Kubernetes

Anta att du vill distribuera en enkel applikation i stil med Hello World. YAML-konfigurationen för den kommer att se ut som följande:

apiVersion: apps/v1
kind: Deployment # <<<
metadata:
  name: my-deployment
  labels:
    track: canary
spec:
  selector:
    matchLabels:
      any-name: my-app
  template:
    metadata:
      labels:
        any-name: my-app
    spec:
      containers:
      - name: cont1
        image: learnk8s/app:1.0.0
        ports:
        - containerPort: 8080
---
apiVersion: v1
kind: Service # <<<
metadata:
  name: my-service
spec:
  ports:
  - port: 80
    targetPort: 8080
  selector:
    name: app
---
apiVersion: networking.k8s.io/v1beta1
kind: Ingress # <<<
metadata:
  name: my-ingress
spec:
  rules:
  - http:
    paths:
    - backend:
        serviceName: app
        servicePort: 80
      path: /

Definitionen är ganska lång och det är lätt att bli förvirrad över hur komponenterna hänger ihop.

Till exempel:

  • När bör man använda port 80, och när bör man använda 8080?
  • Ska man skapa en ny port för varje tjänst så att de inte krockar?
  • Har namnen på etiketter någon betydelse? Ska de vara samma överallt?

Innan vi fokuserar på felsökning, låt oss påminna oss om hur de tre komponenterna hänger ihop. Låt oss börja med Deployment och Service.

Relationen mellan Deployment och Service

Du kommer att bli förvånad, men Deployment och Service är inte direkt kopplade. Istället anger Service direkt poddar och går förbi Deployment.

Därför är vi intresserade av hur Pods och Services relaterar till varandra. Det är viktigt att komma ihåg tre saker:

  1. Väljare (selector) för Service måste matcha åtminstone en etikett från Pod.
  2. targetPort måste överensstämma med containerPort för containern inuti Pod.
  3. port Service kan vara vilken som helst. Olika tjänster kan använda samma port, eftersom de har olika IP-adresser.

Följande diagram representerar allt ovanstående i grafisk form:

1) Anta att tjänsten dirigerar trafik till en viss pod:

Visuell guide för felsökning i Kubernetes

2) Vid skapandet av en pod måste du ange containerPort för varje container i pods:

Visuell guide för felsökning i Kubernetes

3) Vid skapandet av en service måste det anges port och targetPort. Men genom vilken går anslutningen till containern?

Visuell guide för felsökning i Kubernetes

4) Genom targetPort. Det måste matcha med containerPort.

Visuell guide för felsökning i Kubernetes

5) Anta att port 3000 är öppen i containern. Då ska värdet targetPort vara detsamma.

Visuell guide för felsökning i Kubernetes

I YAML-filen måste etiketterna och ports / targetPort överensstämma:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-deployment
  labels:
    track: canary
spec:
  selector:
    matchLabels:
      any-name: my-app
  template:
    metadata:
     labels:  # <<<
        any-name: my-app  # <<<
   spec:
      containers:
      - name: cont1
        image: learnk8s/app:1.0.0
        ports:
       - containerPort: 8080  # <<<
---
apiVersion: v1
kind: Service
metadata:
  name: my-service
spec:
  ports:
  - port: 80
   targetPort: 8080  # <<<
 selector:  # <<<
    any-name: my-app  # <<<

Men hur är det med etiketten track: canary i den övre delen av Deployment-avsnittet? Måste den matcha?

Denna etikett hänför sig till distributionen och används inte av tjänsten för att dirigera trafik. Med andra ord kan den tas bort eller ges ett annat värde.

Och vad sägs om väljaren matchLabels?

Den måste alltid matcha etiketter från Pod,eftersom den används av Deployment för att spåra pods.

Anta att du har gjort rätt ändringar. Hur kan du kontrollera dem?

Etiketter på pods kan kontrolleras med följande kommando:

kubectl get pods --show-labels

Eller om pods tillhör flera applikationer:

kubectl get pods --selector any-name=my-app --show-labels

Där any-name=my-app — det är etiketten any-name: my-app.

Har du fortfarande problem?

Du kan ansluta till pod! För detta bör du använda kommandot port-forward i kubectl. Det låter dig ansluta till tjänsten och kontrollera anslutningen.

kubectl port-forward service/<service name> 3000:80

Här:

  • service/<service name> — namnet på tjänsten; i vårt fall är det my-service;
  • 3000 — porten som behöver öppnas på datorn;
  • 80 — porten angiven i fältet port för tjänsten.

Om anslutningen lyckades, är inställningarna korrekta.

Om anslutningen misslyckades, är problemet med etiketterna eller portarna matchar inte.

Kopplingen mellan Service och Ingress

Nästa steg för att säkerställa åtkomst till applikationen handlar om att konfigurera Ingress. Ingress måste veta hur den hittar tjänsten, sedan hitta poddar och dirigera trafiken till dem. Ingress hittar den önskade tjänsten efter namn och öppet portnummer.

Det måste finnas ett överenskommelse om två parametrar i beskrivningen av Ingress och Service:

  1. servicePort i Ingress måste motsvara parametern port i Service;
  2. serviceName i Ingress måste matcha fältet name i Service.

Den följande schemat sammanfattar anslutningen av portar:

1) Som du redan vet lyssnar Service på ett visst port:

Visuell guide för felsökning i Kubernetes

2) Ingress har en parameter som kallas servicePort:

Visuell guide för felsökning i Kubernetes

3) Denna parameter (servicePort) måste alltid matcha port i definitionen av Service:

Visuell guide för felsökning i Kubernetes

4) Om port 80 är angiven i Service, måste servicePort också vara lika med 80:

Visuell guide för felsökning i Kubernetes

I praktiken måste man vara uppmärksam på följande rader:

apiVersion: v1
kind: Service
metadata:
 name: my-service  # <<<
spec:
  ports:
 - port: 80  # <<<
   targetPort: 8080
  selector:
    any-name: my-app
---
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: my-ingress
spec:
  rules:
  - http:
    paths:
    - backend:
       serviceName: my-service  # <<<
       servicePort: 80  # <<<
     path: /

Hur kan man kontrollera om Ingress fungerar?

Man kan använda metoden med kubectl port-forward, men istället för tjänsten måste man koppla upp sig mot Ingress-kontrollern.

Först måste man ta reda på namnet på podden med Ingress-kontrollern:

kubectl get pods --all-namespaces
NAMESPACE   NAME                              READY STATUS
kube-system coredns-5644d7b6d9-jn7cq          1/1   Running
kube-system etcd-minikube                     1/1   Running
kube-system kube-apiserver-minikube           1/1   Running
kube-system kube-controller-manager-minikube  1/1   Running
kube-system kube-proxy-zvf2h                  1/1   Running
kube-system kube-scheduler-minikube           1/1   Running
kube-system nginx-ingress-controller-6fc5bcc  1/1   Running

Hitta Ingress-podden (den kan tillhöra ett annat namnrum) och kör kommandot objektet PVC:, för att ta reda på portnummer:

kubectl describe pod nginx-ingress-controller-6fc5bcc 
--namespace kube-system 
 | grep Ports
Ports:         80/TCP, 443/TCP, 18080/TCP

Slutligen, anslut till podden:

kubectl port-forward nginx-ingress-controller-6fc5bcc 3000:80 --namespace kube-system

Nu, varje gång du skickar en begäran till port 3000 på din dator, kommer det att vidarebefordras till port 80 på podden med Ingress-kontrollern. När du går till http://localhost:3000, bör du se sidan skapad av applikationen.

Sammanfattning av portar

Låt oss påminna om vilka portar och etiketter som måste matcha:

  1. Väljaren i definieringen av Service måste matcha med etiketten på podden;
  2. targetPort i definieringen av Service måste matcha med containerPort containern inuti podden;
  3. port I definitionen av Service kan vara vilken som helst. Olika tjänster kan använda samma port, eftersom de har olika IP-adresser;
  4. servicePort Ingressens måste matcha port i definitionen av Service;
  5. Tjänstens namn måste matcha fältet serviceName i Ingress.

Tyvärr är det inte tillräckligt att veta hur man korrekt strukturerar YAML-konfiguration.

Vad händer när något går fel?

Det kan hända att podden inte startar eller kraschar.

3 steg för att diagnostisera problem med applikationer i Kubernetes

Innan du börjar debugga deploymenten är det viktigt att ha en god förståelse för hur Kubernetes fungerar.

Eftersom varje applikation i K8s har tre komponenter, bör du debugga dem i en viss ordning, börja från botten.

  1. Först måste du säkerställa att poddarna fungerar, sedan…
  2. Kontrollera om tjänsten levererar trafik till poddarna, och sedan…
  3. Kontrollera att Ingress är korrekt konfigurerad.

Visuellt representation:

1) Börja leta efter problem från botten. Kontrollera först att poddarna har statuser Redo och Running:

Visuell guide för felsökning i Kubernetes

2) Om poddarna är redo (Redo), kontrollera om tjänsten distribuerar trafik mellan poddarna:

Visuell guide för felsökning i Kubernetes

3) Slutligen, analysera sambandet mellan tjänsten och Ingress:

Visuell guide för felsökning i Kubernetes

1. Diagnos av poddar

I de flesta fall är problemet kopplat till podden. Se till att poddarna är listade som Redo och Running. Du kan kontrollera detta med kommandot:

kubectl get pods
NAME                    READY STATUS            RESTARTS  AGE
app1                    0/1   ImagePullBackOff  0         47h
app2                    0/1   Error             0         47h
app3-76f9fcd46b-xbv4k   1/1   Running           1         47h

I utskriften av kommandot ovan är den senaste podden listad som Running och Redo, men för de två andra är det inte så.

Hur förstå att något gick fel?

Det finns fyra användbara kommandon för diagnostik av poddar:

  1. kubectl logs möjliggör att hämta loggar från containrar i podden;
  2. kubectl describe pod möjliggör att se lista över händelser kopplade till podden;
  3. kubectl get pod låter dig få YAML-konfigurationen av podden lagrad i Kubernetes;
  4. kubectl exec -ti bash låtger att starta en interaktiv kommandotolk i en av containrarna i podden.

Vilket av dem ska du välja?

Poängen är att det inte finns något universellt kommando. Du bör använda en kombination av dem.

Typiska problem med poddar

Det finns två grundläggande typer av podfel: fel vid start (startup) och fel vid drift (runtime).

Startfel:

  • ImagePullBackoff
  • ImageInspectError
  • ErrImagePull
  • ErrImageNeverPull
  • RegistryUnavailable
  • OgiltigtBildNamn

Körning-fel:

  • CrashLoopBackOff
  • KörContainerFel
  • DödaContainerFel
  • VerifieraIckeRotFel
  • KörInitContainerFel
  • SkapaPodSandboxFel
  • KonfigureraPodSandboxFel
  • DödaPodSandboxFel
  • Vissa fel inträffar oftare än andra. Här är några av de vanligaste felen och hur man åtgärdar dem.
  • ImagePullBackOff

Detta fel uppstår när Kubernetes inte kan hämta en bild för en av pod'ens containrar. Här är tre vanliga orsaker till detta:

Felaktigt angivet bildnamn - till exempel, du har gjort ett misstag i det eller bilden existerar inte;

Angiven icke-existerande tagg för bilden;

  1. Bilden lagras i en privat registrering och Kubernetes har inte behörighet att komma åt den.
  2. De första två orsakerna är lätta att åtgärda - det räcker med att rätta till bildnamn och tagg. I det sista fallet måste inloggningsuppgifter för den privata registreringen läggas till i Secret och länkas till pod'arna. I Kubernetes-dokumentationen
  3. finns ett exempel

på hur detta kan göras. Kubernetes skriver ut ett fel , om containern inte kan starta. Detta inträffar vanligtvis när:

CrashLoopBackOff

Det finns ett fel i applikationen som hindrar den från att starta; CrashLoopBackOffinställningarna är felaktiga

  1. Liveness-testet har misslyckats för många gånger.
  2. Container Det är nödvändigt att försöka nå loggar från containern för att ta reda på orsaken till dess misslyckande. Om det är svårt att komma åt loggarna eftersom containern startas om för snabbt, kan följande kommando användas:;
  3. kubectl logs --previous

Det visar felmeddelanden från den tidigare reinkarnationen av containern.

Detta fel uppstår när containern inte kan starta. Det motsvarar ögonblicket före applikationens start. Vanligtvis orsakas det av felaktiga inställningar, till exempel:

försök att montera en icke-existerande volym, som ConfigMap eller Secrets;

KörContainerFel

försök att montera en read-only volym som read-write.

  • För att analysera sådana fel passar kommandot
  • kubectl describe pod

Pod'arna är i Pending-status Efter skapelsen förblir podden i status.

Vad orsakar detta?

Här är möjliga orsaker (jag utgår från att schemaläggaren fungerar normalt): Pending.

Det finns inte tillräckligt med resurser i klustret, såsom beräkningskraft och minne, för att starta podden.

I det relevanta namnrymden har ett objekt

  1. ResourceQuota
  2. В соответствующем пространстве имен установлен объект ResourceQuota Och skapandet av en pod kommer att leda till att namnutrymmet överskrider kvoten.
  3. Pod är kopplad till Pending PersistentVolumeClaim.

I det här fallet rekommenderas det att använda kommandot kubectl describe och kontrollera avsnittet Händelser:

kubectl describe pod

Vid fel relaterade till ResourceQuotas, rekommenderas det att granska klusterloggarna med kommandot

kubectl get events --sort-by=.metadata.creationTimestamp

Podar är inte i Ready-status

Om pod är markerad som Running, men inte är i status Redo, betyder det att kontrollen av dess beredskap (readiness probe) misslyckas.

När detta händer så kan pod inte koppla till tjänsten, och trafik når inte den. Misslyckandet av readiness-testet orsakas av problem i applikationen. I så fall behöver du analysera avsnittet Händelser i kommandots utdata kubectl describe.

2. Diagnostik av tjänster

Om podar visas som Running och Redo, men det finns fortfarande inget svar från applikationen, bör du kontrollera tjänstens inställningar.

Tjänster ansvarar för att dirigera trafik till podar beroende på deras etiketter. Så det första du behöver göra är att kontrollera hur många podar som körs med tjänsten. För detta kan du kontrollera endpointarna i tjänsten:

kubectl describe service  | grep Endpoints

Endpoint är ett par värden av typen <IP-адрес:порт>, och i utdata bör det finnas minst ett sådant par (det vill säga att minst en pod arbetar med tjänsten).

Om avsnittet Endpoints är tomt, kan två alternativ vara möjliga:

  1. det finns inga podar med rätt etikett (tips: kontrollera om namnutrymmet är korrekt valt);
  2. det finns ett fel i tjänstetiketterna i selektorn.

Om du ser en lista över endpoints, men fortfarande inte kan få åtkomst till applikationen, är det troligt att problemet är ett fel i targetPort tjänstens beskrivning.

Hur kontrollerar man tjänstens funktionalitet?

Oavsett typ av tjänst kan du använda kommandot kubectl port-forward för att ansluta till den:

kubectl port-forward service/ 3000:80

Här:

  • <service-name> — namnet på tjänsten;
  • 3000 — porten som du öppnar på datorn;
  • 80 — porten på tjänstsidan.

3. Diagnostik av Ingress

Om du har läst hit, så:

  • podar visas som Running och Redo;
  • tjänsten distribuerar trafik framgångsrikt mellan podarna.

Ändå kan du fortfarande inte "nå" applikationen.

Detta innebär att troligen Ingress-kontrollern är felaktigt konfigurerad. Eftersom Ingress-kontrollern är en extern komponent i klustret, finns det olika felavhjälpningsmetoder beroende på typ.

Men innan man använder specialverktyg för att konfigurera Ingress, kan man göra något ganska enkelt. Ingress använder serviceName och servicePort för att ansluta till tjänsten. Det är nödvändigt att kontrollera om de är korrekt konfigurerade. Detta kan göras med kommandot:

kubectl describe ingress

Om kolumnen Backend är tom, är det stor risk att det finns ett konfigurationsfel. Om bakändarna är på plats, men applikationen fortfarande inte är åtkomlig, kan problemet vara relaterat till:

  • tillgänglighetsinställningarna för Ingress från offentliga internet;
  • tillgänglighetsinställningarna för klustret från offentliga internet.

För att identifiera problem med infrastrukturen kan du ansluta direkt till Ingress-poden. För detta, hitta först podden för Ingress-kontrollern (den kan befinna sig i ett annat namnrymd):

kubectl get pods --all-namespaces
NAMESPACE   NAME                              READY STATUS
kube-system coredns-5644d7b6d9-jn7cq          1/1   Running
kube-system etcd-minikube                     1/1   Running
kube-system kube-apiserver-minikube           1/1   Running
kube-system kube-controller-manager-minikube  1/1   Running
kube-system kube-proxy-zvf2h                  1/1   Running
kube-system kube-scheduler-minikube           1/1   Running
kube-system nginx-ingress-controller-6fc5bcc  1/1   Running

Använd kommandot objektet PVC:, för att ställa in porten:

kubectl describe pod nginx-ingress-controller-6fc5bcc
--namespace kube-system 
 | grep Ports

Slutligen, anslut till podden:

kubectl port-forward nginx-ingress-controller-6fc5bcc 3000:80 --namespace kube-system

Nu kommer alla förfrågningar på port 3000 på datorn att omdirigeras till port 80 för podden.

Fungerar den nu?

  • Om ja, så är problemet med infrastrukturen. Det är nödvändigt att ta reda på hur trafikdirigeringen till klustret sker.
  • Om nej, så är problemet med Ingress-kontrollern.

Om det inte går att få Ingress-kontrollern att fungera, måste den debugas.

Det finns många typer av Ingress-kontrollrar. De mest populära är Nginx, HAProxy, Traefik och andra. (mer om befintliga lösningar, se vår recension — anm. red.) Det kan vara bra att använda felsökningsguiden i dokumentationen för den specifika kontrollern. Eftersom Ingress Nginx är den mest populära Ingress-kontrollern, har vi inkluderat några tips i artikeln för att lösa relaterade problem.

Debugga Nginx Ingress-kontrollern

Ingress-nginx-projektet har en officiell plugin för kubectl. Kommandot kubectl ingress-nginx kan användas för:

  • analys av loggar, bakändar, certifikat etc.;
  • ansluta till Ingress;
  • granska den nuvarande konfigurationen.

De följande tre kommandona hjälper dig med detta:

  • kubectl ingress-nginx lint — kontrollerar nginx.conf;
  • kubectl ingress-nginx backend — undersöker bakänden (på samma sätt som kubectl describe ingress);
  • kubectl ingress-nginx logs — kontrollerar loggar.

Observera: i vissa fall kan det vara nödvändigt att ange rätt namnrymd för Ingress-kontrollern med hjälp av flaggan --namespace.

Sammanfattning

Diagnosering i Kubernetes kan vara en utmaning om man inte vet hur man ska börja. Problemet bör alltid angripas från botten och upp: börja med poddar och gå sedan vidare till tjänster och Ingress. Metoderna för avlusning som beskrivs i artikeln kan också tillämpas på andra objekt, såsom:

  • misslyckade Jobbar och CronJobbar;
  • StatefulSet och DaemonSet.

Jag vill uttrycka mitt tack Gergely Risko, Daniel Weibel och Charles Christyraj för värdefulla kommentarer och tillägg.

P.S. från översättaren

Läs även i vår blogg:

Källa: habr.com

Köp pålitlig webbhotell med DDoS-skydd, VPS VDS-servrar 🔥 Köp pålitlig webbhotell med DDoS-skydd, VPS VDS-servrar | ProHoster