En visuel guide til fejlfinding af Kubernetes

Bemærk. overs.: Denne artikel er en del af projektmateriale offentliggjort i det offentlige domæne lærk8s, uddannelse af virksomheder og individuelle administratorer til at arbejde med Kubernetes. I den deler Daniele Polencic, projektleder, visuelle instruktioner om, hvilke skridt der skal tages i tilfælde af generelle problemer med applikationer, der kører på K8s-klyngen.

En visuel guide til fejlfinding af Kubernetes

TL;DR: her er et diagram, der vil hjælpe dig med at fejlfinde implementeringen i Kubernetes:

En visuel guide til fejlfinding af Kubernetes

Flowchart til at finde og rette fejl i en klynge. Originalen (på engelsk) er tilgængelig på PDF и som billede.

Når du implementerer en applikation til Kubernetes, er der typisk tre komponenter, du skal definere:

  • Deployment - dette er en slags opskrift på at lave kopier af applikationen, kaldet pods;
  • Service — intern load balancer, der fordeler trafik mellem pods;
  • Ingress — en beskrivelse af, hvordan trafikken kommer fra omverdenen til Tjenesten.

Her er en hurtig grafisk oversigt:

1) I Kubernetes modtager applikationer trafik fra omverdenen gennem to lag af belastningsbalancere: intern og ekstern.

En visuel guide til fejlfinding af Kubernetes

2) Den interne balancer hedder Service, den eksterne hedder Ingress.

En visuel guide til fejlfinding af Kubernetes

3) Implementering opretter pods og overvåger dem (de oprettes ikke manuelt).

En visuel guide til fejlfinding af Kubernetes

Lad os sige, at du vil implementere en simpel applikation a la Hej Verden. YAML-konfigurationen for den vil se sådan 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 forholder sig til hinanden.

For eksempel:

  • Hvornår skal du bruge port 80, og hvornår skal du bruge 8080?
  • Skal jeg oprette en ny port for hver tjeneste, så de ikke kommer i konflikt?
  • Betyder etiketnavne noget? Skal de være ens overalt?

Før vi fokuserer på fejlretning, lad os huske, hvordan de tre komponenter relaterer til hinanden. Lad os starte med implementering og service.

Forholdet mellem implementering og service

Du vil blive overrasket, men implementering og service er på ingen måde forbundet. I stedet peger Service direkte på Pods og omgår implementeringen.

Derfor er vi interesserede i, hvordan pods og tjenester er relateret til hinanden. Tre ting at huske:

  1. Vælger (selector) for Service skal matche mindst én Pod-etiket.
  2. targetPort skal matche containerPort beholder inde i Pod'en.
  3. port Service kan være hvad som helst. Forskellige tjenester kan bruge den samme port, fordi de har forskellige IP-adresser.

Følgende diagram repræsenterer alt ovenstående i grafisk form:

1) Forestil dig, at tjenesten dirigerer trafik til en bestemt pod:

En visuel guide til fejlfinding af Kubernetes

2) Når du opretter en pod, skal du angive containerPort for hver beholder i bælg:

En visuel guide til fejlfinding af Kubernetes

3) Ved oprettelse af en service skal du angive port и targetPort. Men hvilken bruges til at forbinde til containeren?

En visuel guide til fejlfinding af Kubernetes

4) Via targetPort. Det skal matche containerPort.

En visuel guide til fejlfinding af Kubernetes

5) Lad os sige, at port 3000 er åben i containeren. Derefter værdien targetPort burde være det samme.

En visuel guide til fejlfinding af Kubernetes

I YAML-filen, etiketter og ports / targetPort skal matche:

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 etiketten track: canary øverst i afsnittet Implementering? Skal det matche?

Denne etiket er implementeringsspecifik og bruges ikke af tjenesten til at dirigere trafik. Med andre ord kan den fjernes eller tildeles en anden værdi.

Hvad med vælgeren matchLabels?

Det skal altid matche Pod'ens etiketter, da det bruges af Deployment til at spore pods.

Lad os antage, at du har lavet de korrekte redigeringer. Hvordan tjekker man dem?

Du kan kontrollere pod-etiketten 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

hvor any-name=my-app er en etiket any-name: my-app.

Er der nogle vanskeligheder tilbage?

Du kan oprette forbindelse til poden! For at gøre dette skal du bruge kommandoen port-forward i kubectl. Det giver dig mulighed for at oprette forbindelse til tjenesten og kontrollere forbindelsen.

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

her:

  • service/<service name> — tjenestenavn; i vores tilfælde er det my-service;
  • 3000 er den port, der skal åbnes på computeren;
  • 80 - port angivet i feltet port service.

Hvis forbindelsen blev etableret, er indstillingerne korrekte.

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

Forholdet mellem Service og Ingress

Det næste trin i at give adgang til applikationen involverer opsætning af Ingress. Ingress skal vide, hvordan man finder en tjeneste og derefter finde pods og dirigere trafik til dem. Ingress finder den nødvendige service ved navn og åben port.

I beskrivelsen af ​​Ingress og Service skal to parametre matche:

  1. servicePort in Ingress skal matche parameteren port i brug;
  2. serviceName i Ingress skal matche feltet name i brug.

Følgende diagram opsummerer portforbindelserne:

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

En visuel guide til fejlfinding af Kubernetes

2) Ingress har en parameter kaldet servicePort:

En visuel guide til fejlfinding af Kubernetes

3) Denne parameter (servicePort) skal altid matche port i servicedefinitionen:

En visuel guide til fejlfinding af Kubernetes

4) Hvis port 80 er angivet i Service, så er det nødvendigt at servicePort var også lig med 80:

En visuel guide til fejlfinding af Kubernetes

I praksis skal du 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 kontrollerer man, om Ingress kører?

Du kan bruge metoden med kubectl port-forward, men i stedet for tjenesten skal du oprette forbindelse til Ingress-controlleren.

Først skal du finde ud af navnet på poden 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-poden (den kan være i et andet navneområde), og kør kommandoen describefor at finde ud af portnumrene:

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

Slut endeligt til pod'en:

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

Hver gang du nu sender en anmodning til port 3000 på din computer, vil den blive videresendt til port 80 på poden med Ingress-controlleren. Ved at gå til http://localhost:3000, bør du se siden genereret af applikationen.

Oversigt over havne

Lad os huske igen, hvilke porte og etiketter der skal matche:

  1. Vælgeren i Service-definitionen skal matche podsens etiket;
  2. targetPort i definitionen skal Service matche containerPort beholder inde i en pod;
  3. port i definitionen Service kan være hvad som helst. Forskellige tjenester kan bruge den samme port, fordi de har forskellige IP-adresser;
  4. servicePort Ingress skal matche port i definitionen af ​​Service;
  5. Tjenestenavnet skal matche feltet serviceName i Ingress.

Desværre er det ikke nok at vide, hvordan man strukturerer en YAML-konfiguration korrekt.

Hvad sker der, når tingene går galt?

Poden starter muligvis ikke, eller den kan gå ned.

3 trin til at diagnosticere applikationsproblemer i Kubernetes

Før du begynder at fejlfinde din installation, skal du have en god forståelse af, hvordan Kubernetes fungerer.

Da hver applikation, der downloades i K8s, har tre komponenter, bør de fejlsøges i en bestemt rækkefølge, startende helt fra bunden.

  1. Først skal du sikre dig, at bælgerne virker, så...
  2. Tjek, om tjenesten leverer trafik til pods, og så...
  3. Tjek, om Ingress er konfigureret korrekt.

Visuel repræsentation:

1) Du bør begynde at lede efter problemer helt fra bunden. Tjek først, at pods har statusser Ready и Running:

En visuel guide til fejlfinding af Kubernetes

2) Hvis bælgerne er klar (Ready), bør du finde ud af, om tjenesten distribuerer trafik mellem pods:

En visuel guide til fejlfinding af Kubernetes

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

En visuel guide til fejlfinding af Kubernetes

1. Diagnostik af bælg

I de fleste tilfælde er problemet relateret til poden. Sørg for, at pods er opført som Ready и Running. Du kan kontrollere dette ved at bruge 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 kommandooutputtet ovenfor er den sidste pod angivet som Running и Readydette er dog ikke tilfældet for de to andre.

Hvordan forstår man, hvad der gik galt?

Der er fire nyttige kommandoer til at diagnosticere pods:

  1. kubectl logs <имя pod'а> giver dig mulighed for at udtrække logfiler fra beholdere i en pod;
  2. kubectl describe pod <имя pod'а> giver dig mulighed for at se en liste over begivenheder forbundet med poden;
  3. kubectl get pod <имя pod'а> giver dig mulighed for at få YAML-konfigurationen af ​​en pod gemt i Kubernetes;
  4. kubectl exec -ti <имя pod'а> bash giver dig mulighed for at starte en interaktiv kommandoskal i en af ​​pod-beholderne

Hvilken skal du vælge?

Faktum er, at der ikke er nogen universel kommando. En kombination af disse bør anvendes.

Typiske pod problemer

Der er to hovedtyper af pod-fejl: opstartsfejl og runtime-fejl.

Opstartsfejl:

  • ImagePullBackoff
  • ImageInspectError
  • ErrImagePull
  • ErrImageNeverPull
  • RegistryUnavailable
  • InvalidImageName

Kørselsfejl:

  • CrashLoopBackOff
  • RunContainerError
  • KillContainerError
  • VerifyNonRootError
  • RunInitContainerError
  • CreatePodSandboxError
  • ConfigPodSandboxError
  • KillPodSandboxError
  • SetupNetworkError
  • TeardownNetworkError

Nogle fejl er mere almindelige end andre. Her er nogle af de mest almindelige fejl, og hvordan du løser dem.

ImagePullBackOff

Denne fejl opstår, når Kubernetes ikke er i stand til at hente et billede for en af ​​pod-beholderne. Her er de tre mest almindelige årsager til dette:

  1. Navnet på billedet er forkert - for eksempel har du lavet en fejl i det, eller billedet eksisterer ikke;
  2. Et ikke-eksisterende tag blev angivet for billedet;
  3. Billedet er gemt i et privat register, og Kubernetes har ikke tilladelse til at få adgang til det.

De første to grunde er nemme at eliminere - bare ret billedets navn og tag. I sidstnævntes tilfælde skal du indtaste legitimationsoplysninger for det lukkede register i Secret og tilføje links til det i pods. I Kubernetes-dokumentationen der er et eksempel hvordan dette kan gøres.

Crash Loop Back Off

Kubenetes kaster en fejl CrashLoopBackOff, hvis beholderen ikke kan starte. Dette sker normalt, når:

  1. Der er en fejl i programmet, der forhindrer det i at starte;
  2. container konfigureret forkert;
  3. Liveness-testen har fejlet for mange gange.

Du skal prøve at komme til logfilerne fra containeren for at finde ud af årsagen til dens fejl. Hvis det er svært at få adgang til logfilerne, fordi containeren genstarter for hurtigt, kan du bruge følgende kommando:

kubectl logs <pod-name> --previous

Den viser fejlmeddelelser fra den tidligere inkarnation af beholderen.

RunContainerError

Denne fejl opstår, når containeren ikke starter. Det svarer til øjeblikket før applikationen startes. Det er normalt forårsaget af forkerte indstillinger, for eksempel:

  • forsøg på at montere en ikke-eksisterende volumen såsom ConfigMap eller Secrets;
  • et forsøg på at montere en skrivebeskyttet volumen som læse-skrive.

Holdet er velegnet til at analysere sådanne fejl kubectl describe pod <pod-name>.

Pods er i afventende tilstand

Når den er oprettet, forbliver poden i tilstanden Pending.

Hvorfor sker det her?

Her er de mulige årsager (jeg antager, at skemalæggeren fungerer fint):

  1. Klyngen har ikke nok ressourcer, såsom processorkraft og hukommelse, til at køre poden.
  2. Objektet er installeret i det relevante navneområde ResourceQuota og oprettelse af en pod vil få navneområdet til at gå ud over kvoten.
  3. Pod er bundet til at vente PersistentVolumeClaim.

I dette tilfælde anbefales det at bruge kommandoen kubectl describe og tjek afsnittet Events:

kubectl describe pod <pod name>

I tilfælde af fejl vedr ResourceQuotas, anbefales det at se klyngelogfilerne ved hjælp af kommandoen

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

Pods er ikke klar

Hvis pod er angivet som Running, men er ikke i en tilstand Ready, betyder at kontrollere dens beredskab (beredskab sonde) fejler.

Når dette sker, forbinder poden ikke til tjenesten, og der flyder ingen trafik til den. Fejlen i parathedstesten er forårsaget af problemer i applikationen. I dette tilfælde skal du analysere afsnittet for at finde fejlen Events i kommandoudgangen kubectl describe.

2. Servicediagnostik

Hvis bælg er angivet som Running и Ready, men der er stadig intet svar fra applikationen, bør du kontrollere tjenesteindstillingerne.

Tjenester er ansvarlige for at dirigere trafik til pods afhængigt af deres etiketter. Derfor er det første, du skal gøre, at tjekke, hvor mange pods der fungerer med tjenesten. For at gøre dette kan du tjekke slutpunkterne i tjenesten:

kubectl describe service <service-name> | grep Endpoints

Endpoint er et par værdier af formen <IP-адрес:порт>, og mindst et sådant par skal være til stede i outputtet (det vil sige, at mindst én pod fungerer med tjenesten).

Hvis afsnit Endpoins tom, to muligheder er mulige:

  1. der er ingen pods med den korrekte etiket (tip: tjek om navneområdet er valgt korrekt);
  2. Der er en fejl i serviceetiketterne i vælgeren.

Hvis du ser en liste over endepunkter, men stadig ikke kan få adgang til applikationen, er den sandsynlige synder en fejl i targetPort i servicebeskrivelsen.

Hvordan tjekker man tjenestens funktionalitet?

Uanset hvilken type tjeneste, du kan bruge kommandoen kubectl port-forward for at oprette forbindelse til det:

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

her:

  • <service-name> — tjenestenavn;
  • 3000 er den port, du åbner på computeren;
  • 80 - port på servicesiden.

3. Indgangsdiagnostik

Hvis du har læst så langt, så:

  • bælg er opført som Running и Ready;
  • tjenesten distribuerer med succes trafik blandt pods.

Du kan dog stadig ikke nå appen.

Det betyder, at Ingress-controlleren højst sandsynligt ikke er konfigureret korrekt. Da Ingress-controlleren er en tredjepartskomponent i klyngen, er der forskellige fejlfindingsmetoder afhængigt af dens type.

Men før du tyr til at bruge specielle værktøjer til at konfigurere Ingress, kan du gøre noget meget simpelt. Ingress bruger serviceName и servicePort for at oprette forbindelse til tjenesten. Du skal kontrollere, om de er konfigureret korrekt. Du kan gøre dette ved at bruge kommandoen:

kubectl describe ingress <ingress-name>

Hvis kolonne Backend tom, er der stor sandsynlighed for en konfigurationsfejl. Hvis backends er på plads, men applikationen stadig ikke er tilgængelig, kan problemet være relateret til:

  • Tilgængelighedsindstillinger fra det offentlige internet;
  • klyngetilgængelighedsindstillinger fra det offentlige internet.

Du kan identificere problemer med infrastrukturen ved at oprette forbindelse direkte til Ingress-poden. For at gøre dette skal du først finde Ingress Controller-poden (den kan være i et andet navneområde):

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 describefor at indstille porten:

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

Slut endeligt til pod'en:

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

Nu vil alle anmodninger til port 3000 på computeren blive omdirigeret til port 80 på poden.

Virker det nu?

  • Hvis ja, så er problemet med infrastrukturen. Det er nødvendigt at finde ud af præcis, hvordan trafikken dirigeres til klyngen.
  • Hvis ikke, så er problemet med Ingress-controlleren.

Hvis du ikke kan få Ingress-controlleren til at virke, bliver du nødt til at fejlsøge den.

Der er mange varianter af Ingress-controllere. De mest populære er Nginx, HAProxy, Traefik osv. (for mere information om eksisterende løsninger, se vores anmeldelse - ca. oversættelse) Du bør henvise til fejlfindingsvejledningen i den relevante controllerdokumentation. Fordi Ingress Nginx er den mest populære Ingress-controller, har vi inkluderet nogle tips i artiklen til at løse problemer relateret til det.

Fejlretning af Ingress Nginx-controlleren

Ingress-nginx-projektet har en embedsmand plugin til kubectl. Hold kubectl ingress-nginx kan bruges til:

  • analyse af logfiler, backends, certifikater osv.;
  • forbindelser til Ingress;
  • studerer den aktuelle konfiguration.

Følgende tre kommandoer vil hjælpe dig med dette:

  • kubectl ingress-nginx lint - checks nginx.conf;
  • kubectl ingress-nginx backend — udforsker backend (ligner kubectl describe ingress <ingress-name>);
  • kubectl ingress-nginx logs — kontrollerer loggene.

Bemærk, at du i nogle tilfælde muligvis skal angive det korrekte navneområde for Ingress-controlleren ved hjælp af flaget --namespace <name>.

Resumé

Fejlfinding Kubernetes kan være udfordrende, hvis du ikke ved, hvor du skal starte. Du bør altid nærme dig problemet nedefra og op: start med pods, og gå derefter videre til tjenesten og Ingress. Debugging-teknikkerne beskrevet i denne artikel kan anvendes på andre objekter, såsom:

  • ledige job og CronJobs;
  • StatefulSets og DaemonSets.

Jeg udtrykker min taknemmelighed Gergely Risko, Daniel Weibel и Charles Christyraj for værdifulde kommentarer og tilføjelser.

PS fra oversætteren

Læs også på vores blog:

Kilde: www.habr.com

Tilføj en kommentar