Visuelt guide til fejlfinding i Kubernetes

Bem. overs.: Denne artikel er en del af de offentligt tilgĂŠngelige materialer fra projektet learnk8s, der trĂŠner brugen af Kubernetes for virksomheder og individuelle administratorer. I denne vejledning deler Daniele Polencic, projektleder, en visuel instruktionsguide om de skridt, der skal tages ved generelle problemer med applikationer, der kĂžrer i K8s-klyngen.

Visuelt guide til fejlfinding i Kubernetes

TL;DR: her er et diagram, der kan hjĂŠlpe dig med at debugge deployment i Kubernetes:

Visuelt guide til fejlfinding i Kubernetes

Flowchart til at finde og lÞse fejl i klyngen. Den originale (pÄ engelsk) kan findes i PDF og som billede.

Ved deployment af en applikation i Kubernetes er det normalt nĂždvendigt at definere tre komponenter:

  • Deployment — en opskrift pĂ„ at oprette kopier af applikationen, kaldet pods;
  • Service — en intern load balancer, der fordeler trafik til pods;
  • Ingress — en beskrivelse af, hvordan trafikken vil nĂ„ fra den eksterne verden til Service.

Her er et kort grafisk resumé:

1) I Kubernetes fÄr applikationer trafik fra den eksterne verden gennem to lag af load balancere: intern og ekstern.

Visuelt guide til fejlfinding i Kubernetes

2) Den interne load balancer kaldes Service, den eksterne – Ingress.

Visuelt guide til fejlfinding i Kubernetes

3) Deployment opretter pods og overvÄger dem (de oprettes ikke manuelt).

Visuelt guide til fejlfinding i Kubernetes

Lad os antage, at du Þnsker at deployere en simpel applikation, som f.eks. Hello World. YAML-konfigurationen for den vil se sÄledes ud:

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 er ret lang, og det er let at blive forvirret over, hvordan komponenterne hĂŠnger sammen.

For eksempel:

  • HvornĂ„r skal man bruge port 80, og hvornĂ„r skal man bruge 8080?
  • Skal der oprettes en ny port for hver service for at undgĂ„ konflikter?
  • Har navnet pĂ„ labels nogen betydning? Skal de vĂŠre ens overalt?

FÞr vi fokuserer pÄ debugging, lad os huske pÄ, hvordan de tre komponenter hÊnger sammen. Lad os starte med Deployment og Service.

Forholdet mellem Deployment og Service

Du vil blive overrasket, men Deployments og Services er ikke direkte forbundet. I stedet angiver Service direkte til Pods uden om Deployment.

SÄledes er vi interesserede i, hvordan Pods og Services er relateret til hinanden. Husk tre ting:

  1. VÊlger (selector) for Service skal svare til mindst én label fra Pod.
  2. targetPort skal svare til containerPort i containere inden for Pod.
  3. port Porten for Service kan vĂŠre hvilken som helst. Forskellige services kan bruge den samme port, da de har forskellige IP-adresser.

NÊste skema prÊsenterer alt det ovenstÄende i grafisk form:

1) Antag, at servicen dirigerer trafik til en pod:

Visuelt guide til fejlfinding i Kubernetes

2) NÄr du opretter en pod, skal du angive containerPort for hver container i pods:

Visuelt guide til fejlfinding i Kubernetes

3) NÄr du opretter en service, skal du angive port og targetPort. Men gennem hvilken gÄr forbindelsen til containeren?

Visuelt guide til fejlfinding i Kubernetes

4) Gennem targetPort. Det skal svare til containerPort.

Visuelt guide til fejlfinding i Kubernetes

5) Antag, at port 3000 er Äben i containeren. SÄ skal vÊrdien targetPort vÊre den samme.

Visuelt guide til fejlfinding i Kubernetes

I YAML-filen skal labels og ports / targetPort svare til:

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  # <<<

Hvad med label track: canary i toppen af Deployment-sektionen? Skal den svare til?

Denne label tilhĂžrer deploymenten, og den bruges ikke af servicen til at dirigere trafik. Med andre ord kan den slettes eller tildeles en anden vĂŠrdi.

Hvad med vĂŠlgeren matchLabels?

Den skal altid svare til labels fra Pod,, da den bruges af Deployment til at spore pods.

Antag, at du har foretaget de korrekte ĂŠndringer. Hvordan tjekker du dem?

Du kan kontrollere labels for pods med fĂžlgende kommando:

kubectl get pods --show-labels

Eller, hvis pods tilhĂžrer flere applikationer:

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

Where any-name=my-app — dette er label any-name: my-app.

Har du stadig problemer?

Du kan tilslutte til pod! For dette skal du bruge kommandoen port-forward i kubectl. Den giver mulighed for at oprette forbindelse til servicen og kontrollere forbindelsen.

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

Her:

  • service/<service name> — navnet pĂ„ servicen; i vores tilfĂŠlde er det my-service;
  • 3000 — den port, der skal Ă„bnes pĂ„ computeren;
  • 80 — den port, der er angivet i feltet port for servicen.

Hvis forbindelsen kunne etableres, sÄ er indstillingerne korrekte.

Hvis forbindelsen ikke kunne oprettes, er der et problem med etiketterne, eller portene stemmer ikke overens.

Forbindelsen mellem Service og Ingress

Det nÊste skridt for at sikre adgang til applikationen involverer opsÊtning af Ingress. Ingress skal vide, hvordan man finder servicen, derefter finde pods og dirigere trafik til dem. Ingress finder den nÞdvendige service ud fra navn og Äben port.

I beskrivelsen af Ingress og Service skal to parametre vĂŠre ens:

  1. servicePort i Ingress skal svare til parameteren port i Service;
  2. serviceName i Ingress skal svare til feltet name i Service.

FĂžlgende skema opsummerer tilslutningen af porte:

1) Som du allerede ved, lytter Service til en given port:

Visuelt guide til fejlfinding i Kubernetes

2) Ingress har en parameter, der kaldes servicePort:

Visuelt guide til fejlfinding i Kubernetes

3) Denne parameter (servicePort) skal altid svare til port i definitionen af Service:

Visuelt guide til fejlfinding i Kubernetes

4) Hvis porten i Service er sat til 80, skal servicePort ogsÄ vÊre lig med 80:

Visuelt guide til fejlfinding i Kubernetes

I praksis er det vigtigt at vÊre opmÊrksom pÄ fÞlgende linjer:

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: /

Hvordan kan man kontrollere, om Ingress fungerer?

Man kan bruge metoden med kubectl port-forward, men i stedet for at forbinde til servicen skal man forbinde til Ingress-controlleren.

FÞrst skal du finde navnet pÄ pod'en med Ingress-controlleren:

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

Find Ingress-pod'en (den kan tilhĂžre et andet navnerum) og udfĂžr kommandoen describe, for at finde portnumrene:

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

Endelig skal du forbinde til pod'en:

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

Nu, hver gang du sender en forespÞrgsel til port 3000 pÄ din computer, vil den blive videresendt til port 80 pÄ pod'en med Ingress-controlleren. Ved at gÄ til http://localhost:3000, skal du kunne se siden oprettet af applikationen.

Resume om porte

Lad os endnu en gang huske, hvilke porte og etiketter der skal stemme overens:

  1. VÊlgeren i definitionen af Service skal svare til etiketten pÄ pod'en;
  2. targetPort i definitionen af Service skal svare til containerPort containeren inde i pod'en;
  3. port I definitionen af Service kan vĂŠre hvilken som helst. Forskellige tjenester kan bruge den samme port, da de har forskellige IP-adresser;
  4. servicePort Ingress'ens skal matche port i definitionen af Service;
  5. Navnet pÄ tjenesten skal matche feltet serviceName i Ingress.

DesvĂŠrre er det ikke nok at vide, hvordan man korrekt strukturerer YAML-konfigurationen.

Hvad sker der, nÄr noget gÄr galt?

MÄske starter pod'en ikke, eller den falder.

3 trin til fejlfinding af applikationer i Kubernetes

FÞr du begynder at debugge deployment'en, er det nÞdvendigt at have en god forstÄelse af, hvordan Kubernetes fungerer.

Da hver K8s-applikation har tre komponenter, skal du debugge dem i en bestemt rĂŠkkefĂžlge, startende fra bunden.

  1. Fþrst skal du sikre dig, at pod'erne fungerer, og derefter 

  2. Kontrollerer, om tjenesten leverer trafik til pod'erne, og derefter 

  3. Kontrollerer, om Ingress er korrekt konfigureret.

Visualisering:

1) Begynd at lede efter problemer fra bunden. FĂžrst skal du kontrollere, at pod'erne har status Klar og KĂžrende:

Visuelt guide til fejlfinding i Kubernetes

2) Hvis pod'erne er klar (Klar), skal du finde ud af, om tjenesten distribuerer trafik mellem pod'erne:

Visuelt guide til fejlfinding i Kubernetes

3) Endelig skal du analysere forbindelsen mellem tjenesten og Ingress:

Visuelt guide til fejlfinding i Kubernetes

1. Fejlfinding af pod'er

I de fleste tilfĂŠlde er problemet relateret til pod'en. SĂžrg for, at pod'erne er angivet som Klar og KĂžrende. Dette kan kontrolleres med kommandoen:

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 outputtet fra ovenstÄende kommando er den sidste pod angivet som KÞrende og Klar, men for de to andre er det ikke tilfÊldet.

Hvordan forstÄr man, hvad der gik galt?

Der er fire nyttige kommandoer til fejlfinding af pod'er:

  1. kubectl logs giver mulighed for at hente logfiler fra containere i pod'en;
  2. kubectl describe pod giver mulighed for at se en liste over begivenheder relateret til pod'en;
  3. kubectl get pod giver mulighed for at fÄ YAML-konfigurationen for pod'en gemt i Kubernetes;
  4. kubectl exec -ti bash giver mulighed for at starte en interaktiv kommandolinje i en af containerne i pod'en

Hvilken skal man vĂŠlge?

Problemet er, at der ikke er en universel kommando. Du skal bruge en kombination af dem.

Typiske problemer med pod'er

Der er to hovedtyper af fejl i pod'er: opstartsfejl (startup) og runtime-fejl.

Opstartsfejl:

  • ImagePullBackoff
  • ImageInspectError
  • ErrImagePull
  • ErrImageNeverPull
  • RegistryUnavailable
  • UgyldigBilledeNavn

Runtime-fejl:

  • CrashLoopBackOff
  • KĂžrContainerFejl
  • DrĂŠbContainerFejl
  • BekrĂŠftIkkeRodBrugerFejl
  • KĂžrInitContainerFejl
  • OpretPodSandboxFejl
  • KonfigPodSandboxFejl
  • DrĂŠbPodSandboxFejl
  • OpsĂŠtteNetvĂŠrkFejl
  • NedbrydeNetvĂŠrkFejl

Nogle fejl forekommer oftere end andre. Her er nogle af de mest almindelige fejl og mÄder at lÞse dem pÄ.

ImagePullBackOff

Denne fejl opstĂ„r, nĂ„r Kubernetes ikke kan hente et billede til en af pod’ens containere. Her er tre af de mest almindelige Ă„rsager til dette:

  1. Billednavnet er forkert angivet – for eksempel har du lavet en fejl i det, eller billedet eksisterer ikke;
  2. En ikke-eksisterende tag er angivet for billedet;
  3. Billedet opbevares i et privat register, og Kubernetes har ikke de nÞdvendige tilladelser til at fÄ adgang til det.

De to fĂžrste Ă„rsager er lette at lĂžse – du skal blot rette billednavnet og taggen. I tilfĂŠlde af den sidste skal du indtaste legitimationsoplysninger til det private register i Secret og tilfĂžje referencer til det i pod’erne. I Kubernetes-dokumentationen er der et eksempel pĂ„, hvordan dette kan gĂžres.

CrashLoopBackOff

Kubernetes viser en fejl CrashLoopBackOff, hvis containeren ikke kan starte. Dette sker normalt, nÄr:

  1. Der er en fejl i applikationen, der forhindrer den i at starte;
  2. Container det er forkert konfigureret;
  3. Liveness-testen er mislykket for mange gange.

Det er nÞdvendigt at forsÞge at fÄ fat i loggene fra containeren for at finde ud af Ärsagen til dens nedbrud. Hvis adgangen til loggene er svÊr, da containeren genstarter for hurtigt, kan fÞlgende kommando bruges:

kubectl logs  --previous

Den viser fejlmeddelelser fra den tidligere inkarnation af containeren.

KĂžrContainerFejl

Denne fejl opstĂ„r, nĂ„r containeren ikke er i stand til at starte. Den svarer til Ăžjeblikket fĂžr applikationen starter. Årsagen til dette er normalt en forkert konfiguration, sĂ„som:

  • forsĂžger at montere et ikke-eksisterende volumen, som ConfigMap eller Secrets;
  • forsĂžger at montere et read-only volumen som read-write.

Til analyse af sÄdanne fejl er kommandoen kubectl describe pod.

Pod’ene er i Pending-status

Efter oprettelsen forbliver pod’en i status Pending.

Hvorfor sker dette?

Her er mulige Ärsager (jeg forudsÊtter, at planlÊggeren fungerer korrekt):

  1. Der er ikke nok ressourcer i klyngen, sĂ„som beregningskraft og hukommelse, til at starte pod’en.
  2. I det relevante navnerum er der oprettet et objekt ResourceQuota Og oprettelsen af en pod vil fĂžre til, at navnerummet overskrider kvoten.
  3. Pod er knyttet til Pending PersistentVolumeClaim.

I dette tilfĂŠlde anbefales det at bruge kommandoen kubectl describe og tjekke sektionen Begivenheder:

kubectl describe pod

I tilfĂŠlde af fejl relateret til ResourceQuotas, anbefales det at se gennem klyngens logs med kommandoen

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

Pods er ikke i Ready tilstand

Hvis pod'en er markeret som KĂžrende, men ikke er i tilstanden Klar, betyder det, at pod'ens beredskabsprĂžve (readiness probe) mislykkes.

NÄr dette sker, opretter pod'en ikke forbindelse til tjenesten, og trafikken faktisk tilgÄr den ikke. Fejlen i beredskabsprÞven skyldes problemer i applikationen. I sÄ fald skal sektionen Begivenheder i udgangen af kommandoen kubectl describe.

2. Diagnostik af tjenester

Hvis pods er markeret som KĂžrende og Klar, men der stadig ikke er noget svar fra applikationen, skal tjenesteindstillingerne kontrolleres.

Tjenester hÄndterer trafikdirigering til pods baseret pÄ deres labels. Derfor er det fÞrste, man skal gÞre, at tjekke, hvor mange pods der arbejder med tjenesten. Dette kan gÞres ved at kontrollere endpoints i tjenesten:

kubectl describe service  | grep Endpoints

Endpoint er et par vĂŠrdier af typen <IP-аЎрДс:ĐżĐŸŃ€Ń‚>, og der skal vĂŠre mindst et sĂ„dant par i udgangen (det vil sige, at mindst Ă©n pod arbejder med tjenesten).

Hvis sektionen Endpoints er tom, er der to mulige scenarier:

  1. der er ingen pod's med den rigtige label (tip: tjek om navnerummet er korrekt valgt);
  2. der er en fejl i tjenestens labels i vĂŠlgeren.

Hvis du ser en liste over endpoints, men stadig ikke kan fÄ adgang til applikationen, er den sandsynlige skyldner en fejl i targetPort den beskrivelse af tjenesten.

Hvordan tjekker man, om tjenesten fungerer?

Uanset hvilken type tjeneste kan man bruge kommandoen kubectl port-forward til at oprette forbindelse til den:

kubectl port-forward service/ 3000:80

Her:

  • <service-name> — navn pĂ„ tjenesten;
  • 3000 — porten, som du Ă„bner pĂ„ computeren;
  • 80 — porten pĂ„ servicesiden.

3. Diagnostik af Ingress

Hvis du er nÄet hertil, sÄ:

  • pods er markeret som KĂžrende og Klar;
  • tjenesten distribuerer trafik til pods med succes.

Men du kan stadig ikke "nÄ" applikationen.

Det betyder, at Ingress-controllernes opsĂŠtning sandsynligvis er forkert. Da Ingress-controlleren er en ekstern komponent i klyngen, er der forskellige fejlfindingsmetoder afhĂŠngigt af dens type.

Men fĂžr du bruger specielle vĂŠrktĂžjer til at konfigurere Ingress, kan du gĂžre noget ganske simpelt. Ingress bruger serviceName og servicePort til at oprette forbindelse til tjenesten. Det er nĂždvendigt at kontrollere, om de er korrekt konfigureret. Dette kan gĂžres med kommandoen:

kubectl describe ingress

Hvis kolonnen Backend er tom, er der stor sandsynlighed for en fejl i konfigurationen. Hvis backend'en er pÄ plads, men du stadig ikke kan tilgÄ applikationen, kan problemet vÊre relateret til:

  • indstillingerne for tilgĂŠngelighed af Ingress fra internettet;
  • indstillingerne for tilgĂŠngelighed af klyngen fra internettet.

For at finde problemer med infrastrukturen kan du forbinde direkte til Ingress-pod'en. Find fĂžrst pod'en for Ingress-controlleren (den kan vĂŠre i et andet navnerum):

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

Brug kommandoen describe, for at sĂŠtte porten:

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

Endelig skal du forbinde til pod'en:

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

Nu vil alle forespÞrgsler til port 3000 pÄ computeren blive omdirigeret til port 80 af pod'en.

Fungerer det nu?

  • Hvis ja, sĂ„ er der et problem med infrastrukturen. Det er nĂždvendigt at finde ud af, hvordan trafikken rutes til klyngen.
  • Hvis nej, sĂ„ er problemet med Ingress-controlleren.

Hvis du ikke kan fÄ Ingress-controlleren til at fungere, skal den fejlfinding.

Der findes mange varianter af Ingress-controllere. De mest populére er Nginx, HAProxy, Traefik og andre. (mere om de eksisterende lþsninger, se vores gennemgang — red. anm.) Det anbefales at fþlge fejlfindingguiden i dokumentationen for den relevante controller. Da Ingress Nginx er den mest populére Ingress-controller, har vi inkluderet nogle tips til lþsning af relaterede problemer i artiklen.

Fejlfinding af Ingress Nginx-controlleren

Projektet Ingress-nginx har en officiel plugin til kubectl. Kommandoen kubectl ingress-nginx kan bruges til:

  • analyse af logs, backends, certifikater osv.;
  • tilslutning til Ingress;
  • undersĂžgelse af den aktuelle konfiguration.

De fĂžlgende tre kommandoer vil hjĂŠlpe dig med dette:

  • kubectl ingress-nginx lint — tjekker nginx.conf;
  • kubectl ingress-nginx backend — undersĂžger backend (pĂ„ samme mĂ„de som kubectl describe ingress);
  • kubectl ingress-nginx logs — tjekker logs.

BemĂŠrk: i nogle tilfĂŠlde kan det vĂŠre nĂždvendigt at angive det korrekte navnerum for Ingress-controlleren med flaget --namespace.

CV

Fejlfinding i Kubernetes kan vĂŠre en udfordring, hvis man ikke ved, hvor man skal starte. Problemet bĂžr altid angrebet fra bunden opad: begynd med pod’ene, og gĂ„ derefter videre til tjenesten og Ingress. De debugmetoder, der beskrives i artiklen, kan ogsĂ„ anvendes pĂ„ andre objekter sĂ„som:

  • fejlende Job’ere og CronJob’ere;
  • StatefulSet’ere og DaemonSet’ere.

Jeg vil gerne takke Gergely Risko, Daniel Weibel og Charles Christyraj for vĂŠrdifulde bemĂŠrkninger og tilfĂžjelser.

P.S. fra oversĂŠtteren

LÊs ogsÄ pÄ vores blog:

Kilde: habr.com

KĂžb pĂ„lidelig webhosting med DDoS-beskyttelse, VPS VDS-servere đŸ”„ KĂžb pĂ„lidelig webhosting med DDoS-beskyttelse, VPS VDS-servere | ProHoster