En visuell veiledning for feilsøking av Kubernetes

Merk. overs.: Denne artikkelen er en del av prosjektmateriellet som er publisert i det offentlige domene learnk8s, opplæring av selskaper og individuelle administratorer for å jobbe med Kubernetes. I den deler Daniele Polencic, prosjektleder, visuelle instruksjoner om hvilke skritt du skal ta i tilfelle generelle problemer med applikasjoner som kjører på K8s-klyngen.

En visuell veiledning for feilsøking av Kubernetes

TL;DR: her er et diagram som vil hjelpe deg med å feilsøke distribusjon i Kubernetes:

En visuell veiledning for feilsøking av Kubernetes

Flytskjema for å finne og rette feil i en klynge. Originalen (på engelsk) er tilgjengelig på PDF и som bilde.

Når du distribuerer en applikasjon til Kubernetes, er det vanligvis tre komponenter du må definere:

  • Utplassering - dette er en slags oppskrift for å lage kopier av applikasjonen, kalt pods;
  • Service — intern lastbalanser som fordeler trafikk mellom pods;
  • Ingress — en beskrivelse av hvordan trafikk vil komme fra omverdenen til Tjenesten.

Her er en rask grafisk oppsummering:

1) I Kubernetes mottar applikasjoner trafikk fra omverdenen gjennom to lag med lastbalansere: intern og ekstern.

En visuell veiledning for feilsøking av Kubernetes

2) Den interne balansereren heter Service, den eksterne kalles Ingress.

En visuell veiledning for feilsøking av Kubernetes

3) Utrulling oppretter pods og overvåker dem (de opprettes ikke manuelt).

En visuell veiledning for feilsøking av Kubernetes

La oss si at du vil distribuere en enkel applikasjon a la Hallo verden. YAML-konfigurasjonen for den vil se slik ut:

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

Definisjonen er ganske lang og det er lett å bli forvirret over hvordan komponentene forholder seg til hverandre.

For eksempel:

  • Når bør du bruke port 80 og når bør du bruke 8080?
  • Bør jeg opprette en ny port for hver tjeneste slik at de ikke kommer i konflikt?
  • Har etikettnavn noen betydning? Skal de være like overalt?

Før vi fokuserer på feilsøking, la oss huske hvordan de tre komponentene forholder seg til hverandre. La oss starte med distribusjon og service.

Forholdet mellom utplassering og tjeneste

Du vil bli overrasket, men distribusjon og service er på ingen måte relatert. I stedet peker Service direkte til Pods, og omgår distribusjon.

Derfor er vi interessert i hvordan poder og tjenester er relatert til hverandre. Tre ting å huske:

  1. Velger (selector) for Service må samsvare med minst én Pod-etikett.
  2. targetPort må samsvare containerPort beholder inne i Pod.
  3. port Service kan være hva som helst. Ulike tjenester kan bruke samme port fordi de har forskjellige IP-adresser.

Følgende diagram representerer alt ovenfor i grafisk form:

1) Tenk deg at tjenesten dirigerer trafikk til en bestemt pod:

En visuell veiledning for feilsøking av Kubernetes

2) Når du oppretter en pod, må du spesifisere containerPort for hver beholder i belg:

En visuell veiledning for feilsøking av Kubernetes

3) Når du oppretter en tjeneste, må du spesifisere port и targetPort. Men hvilken brukes til å koble til containeren?

En visuell veiledning for feilsøking av Kubernetes

4) Via targetPort. Det må matche containerPort.

En visuell veiledning for feilsøking av Kubernetes

5) La oss si at port 3000 er åpen i beholderen. Deretter verdien targetPort skal være det samme.

En visuell veiledning for feilsøking av Kubernetes

I YAML-filen, etiketter og ports / targetPort må samsvare:

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

Hva med etiketten track: canary øverst i distribusjonsdelen? Skal det matche?

Denne etiketten er distribusjonsspesifikk og brukes ikke av tjenesten til å rute trafikk. Med andre ord kan den fjernes eller tildeles en annen verdi.

Hva med velgeren matchLabels?

Den må alltid samsvare med Pod-etikettene, siden den brukes av Deployment til å spore pods.

La oss anta at du har gjort de riktige endringene. Hvordan sjekke dem?

Du kan sjekke pod-etiketten med følgende kommando:

kubectl get pods --show-labels

Eller, hvis pods tilhører flere applikasjoner:

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

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

Er det noen vanskeligheter igjen?

Du kan koble til poden! For å gjøre dette må du bruke kommandoen port-forward i kubectl. Den lar deg koble til tjenesten og sjekke tilkoblingen.

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

her:

  • service/<service name> — tjenestenavn; i vårt tilfelle er det my-service;
  • 3000 er porten som må åpnes på datamaskinen;
  • 80 - port spesifisert i feltet port service.

Hvis tilkoblingen ble opprettet, er innstillingene korrekte.

Hvis tilkoblingen mislykkes, er det et problem med etikettene eller portene stemmer ikke overens.

Forholdet mellom Service og Ingress

Det neste trinnet i å gi tilgang til applikasjonen innebærer å sette opp Ingress. Ingress må vite hvordan man finner en tjeneste, og deretter finne pods og dirigere trafikk til dem. Ingress finner den nødvendige tjenesten ved navn og åpen port.

I beskrivelsen av Ingress og Service må to parametere samsvare:

  1. servicePort in Ingress må samsvare med parameteren port i tjeneste;
  2. serviceName i Ingress må samsvare med feltet name i tjeneste.

Følgende diagram oppsummerer porttilkoblingene:

1) Som du allerede vet, lytter Service til en viss port:

En visuell veiledning for feilsøking av Kubernetes

2) Ingress har en parameter kalt servicePort:

En visuell veiledning for feilsøking av Kubernetes

3) Denne parameteren (servicePort) må alltid samsvare port i tjenestedefinisjonen:

En visuell veiledning for feilsøking av Kubernetes

4) Hvis port 80 er spesifisert i Service, er det nødvendig at servicePort var også lik 80:

En visuell veiledning for feilsøking av Kubernetes

I praksis må du ta hensyn til 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 sjekke om Ingress kjører?

Du kan bruke metoden med kubectl port-forward, men i stedet for tjenesten må du koble til Ingress-kontrolleren.

Først må du finne ut navnet på poden med Ingress-kontrolleren:

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

Finn Ingress-poden (den kan være i et annet navneområde) og kjør kommandoen describefor å finne ut portnumrene:

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

Koble til slutt til poden:

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

Nå hver gang du sender en forespørsel til port 3000 på datamaskinen din, vil den bli videresendt til port 80 på poden med Ingress-kontrolleren. Ved å gå til http://localhost:3000, bør du se siden generert av applikasjonen.

Sammendrag av havner

La oss igjen huske hvilke porter og etiketter som må samsvare:

  1. Velgeren i tjenestedefinisjonen må samsvare med podens etikett;
  2. targetPort i definisjonen Tjenesten må samsvare containerPort beholder inne i en pod;
  3. port i definisjonen Service kan være hva som helst. Ulike tjenester kan bruke samme port fordi de har forskjellige IP-adresser;
  4. servicePort Ingress må samsvare port i definisjonen av tjeneste;
  5. Tjenestenavnet må samsvare med feltet serviceName i Ingress.

Dessverre er det ikke nok å vite hvordan man strukturerer en YAML-konfigurasjon på riktig måte.

Hva skjer når ting går galt?

Poden starter kanskje ikke, eller den kan krasje.

3 trinn for å diagnostisere applikasjonsproblemer i Kubernetes

Før du begynner å feilsøke distribusjonen din, må du ha en god forståelse av hvordan Kubernetes fungerer.

Siden hver applikasjon som lastes ned i K8s har tre komponenter, bør de feilsøkes i en bestemt rekkefølge, fra bunnen av.

  1. Først må du sørge for at podene fungerer, så...
  2. Sjekk om tjenesten leverer trafikk til podene, og så...
  3. Sjekk om Ingress er riktig konfigurert.

Visuell representasjon:

1) Du bør begynne å lete etter problemer helt fra bunnen. Sjekk først at pods har statuser Ready и Running:

En visuell veiledning for feilsøking av Kubernetes

2) Hvis belgene er klare (Ready), bør du finne ut om tjenesten distribuerer trafikk mellom pods:

En visuell veiledning for feilsøking av Kubernetes

3) Til slutt må du analysere sammenhengen mellom tjenesten og Ingress:

En visuell veiledning for feilsøking av Kubernetes

1. Diagnostikk av pods

I de fleste tilfeller er problemet relatert til poden. Sørg for at pods er oppført som Ready и Running. Du kan sjekke dette ved å bruke 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 kommandoutgangen ovenfor er den siste poden oppført som Running и ReadyDette er imidlertid ikke tilfellet for de to andre.

Hvordan forstå hva som gikk galt?

Det er fire nyttige kommandoer for å diagnostisere pods:

  1. kubectl logs <имя pod'а> lar deg trekke ut logger fra beholdere i en pod;
  2. kubectl describe pod <имя pod'а> lar deg se en liste over hendelser knyttet til poden;
  3. kubectl get pod <имя pod'а> lar deg få YAML-konfigurasjonen til en pod lagret i Kubernetes;
  4. kubectl exec -ti <имя pod'а> bash lar deg starte et interaktivt kommandoskall i en av podbeholderne

Hvilken bør du velge?

Faktum er at det ikke er noen universell kommando. En kombinasjon av disse bør brukes.

Typiske podproblemer

Det er to hovedtyper pod-feil: oppstartsfeil og kjøretidsfeil.

Oppstartsfeil:

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

Kjøretidsfeil:

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

Noen feil er mer vanlige enn andre. Her er noen av de vanligste feilene og hvordan du kan fikse dem.

ImagePullBackOff

Denne feilen oppstår når Kubernetes ikke klarer å skaffe et bilde for en av podbeholderne. Her er de tre vanligste årsakene til dette:

  1. Navnet på bildet er feil - for eksempel har du gjort en feil i det, eller bildet eksisterer ikke;
  2. En ikke-eksisterende kode ble spesifisert for bildet;
  3. Bildet er lagret i et privat register og Kubernetes har ikke tilgang til det.

De to første årsakene er enkle å eliminere - bare korriger bildenavnet og -koden. Når det gjelder sistnevnte, må du skrive inn legitimasjon for det lukkede registeret i Secret og legge til lenker til det i pods. I Kubernetes-dokumentasjonen det er et eksempel hvordan dette kan gjøres.

Crash Loop Tilbake Av

Kubenetes kaster en feil CrashLoopBackOff, hvis beholderen ikke kan starte. Dette skjer vanligvis når:

  1. Det er en feil i applikasjonen som hindrer den i å starte;
  2. container konfigurert feil;
  3. Liveness-testen har feilet for mange ganger.

Du må prøve å komme til loggene fra beholderen for å finne ut årsaken til feilen. Hvis det er vanskelig å få tilgang til loggene fordi beholderen starter på nytt for raskt, kan du bruke følgende kommando:

kubectl logs <pod-name> --previous

Den viser feilmeldinger fra forrige inkarnasjon av beholderen.

RunContainerError

Denne feilen oppstår når beholderen ikke starter. Det tilsvarer øyeblikket før applikasjonen startes. Det er vanligvis forårsaket av feil innstillinger, for eksempel:

  • forsøk på å montere et ikke-eksisterende volum som ConfigMap eller Secrets;
  • et forsøk på å montere et skrivebeskyttet volum som lese-skrive.

Teamet er godt egnet til å analysere slike feil kubectl describe pod <pod-name>.

Pods er i ventende tilstand

Når den er opprettet, forblir poden i tilstanden Pending.

Hvorfor skjer dette?

Her er de mulige årsakene (jeg antar at planleggeren fungerer bra):

  1. Klyngen har ikke nok ressurser, for eksempel prosessorkraft og minne, til å kjøre poden.
  2. Objektet er installert i riktig navneområde ResourceQuota og å opprette en pod vil føre til at navneområdet går utover kvoten.
  3. Pod er bundet til Venter PersistentVolumeClaim.

I dette tilfellet anbefales det å bruke kommandoen kubectl describe og sjekk delen Events:

kubectl describe pod <pod name>

Ved feil knyttet til ResourceQuotas, anbefales det å vise klyngeloggene ved å bruke kommandoen

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

Pods er ikke klare

Hvis pod er oppført som Running, men er ikke i en tilstand Ready, betyr å sjekke beredskapen (beredskapsundersøkelse) mislykkes.

Når dette skjer, kobles ikke poden til tjenesten, og ingen trafikk flyter til den. Beredskapstestfeilen er forårsaket av problemer i applikasjonen. I dette tilfellet, for å finne feilen, må du analysere delen Events i kommandoutgangen kubectl describe.

2. Servicediagnostikk

Hvis pods er oppført som Running и Ready, men det er fortsatt ikke noe svar fra applikasjonen, bør du sjekke tjenesteinnstillingene.

Tjenester er ansvarlige for å dirigere trafikk til pods avhengig av etikettene deres. Derfor er det første du må gjøre å sjekke hvor mange pods som fungerer med tjenesten. For å gjøre dette kan du sjekke endepunktene i tjenesten:

kubectl describe service <service-name> | grep Endpoints

Endpoint er et par verdier av skjemaet <IP-адрес:порт>, og minst ett slikt par må være til stede i utgangen (det vil si at minst én pod fungerer med tjenesten).

Hvis seksjon Endpoins tom, to alternativer er mulig:

  1. det er ingen pods med riktig etikett (hint: sjekk om navneområdet er valgt riktig);
  2. Det er en feil i tjenesteetikettene i velgeren.

Hvis du ser en liste over endepunkter, men fortsatt ikke får tilgang til applikasjonen, er den sannsynlige skyldige en feil i targetPort i tjenestebeskrivelsen.

Hvordan sjekke funksjonaliteten til tjenesten?

Uavhengig av type tjeneste, kan du bruke kommandoen kubectl port-forward for å koble til den:

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

her:

  • <service-name> — tjenestenavn;
  • 3000 er porten du åpner på datamaskinen;
  • 80 - babord på servicesiden.

3. Inngangsdiagnostikk

Hvis du har lest så langt, så:

  • pods er oppført som Running и Ready;
  • tjenesten distribuerer trafikk mellom pods.

Du kan imidlertid fortsatt ikke nå appen.

Dette betyr at Ingress-kontrolleren mest sannsynlig ikke er riktig konfigurert. Siden Ingress-kontrolleren er en tredjepartskomponent i klyngen, er det forskjellige feilsøkingsmetoder avhengig av typen.

Men før du tyr til å bruke spesialverktøy for å konfigurere Ingress, kan du gjøre noe veldig enkelt. Ingress bruker serviceName и servicePort for å koble til tjenesten. Du må sjekke om de er riktig konfigurert. Du kan gjøre dette ved å bruke kommandoen:

kubectl describe ingress <ingress-name>

Hvis kolonne Backend tom, er det stor sannsynlighet for en konfigurasjonsfeil. Hvis backends er på plass, men applikasjonen fortsatt ikke er tilgjengelig, kan problemet være relatert til:

  • Ingress tilgjengelighetsinnstillinger fra det offentlige Internett;
  • klyngetilgjengelighetsinnstillinger fra det offentlige Internett.

Du kan identifisere problemer med infrastrukturen ved å koble direkte til Ingress-poden. For å gjøre dette, finn først Ingress Controller-poden (den kan være i et annet 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

Bruk kommandoen describefor å stille inn porten:

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

Koble til slutt til poden:

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

Nå vil alle forespørsler til port 3000 på datamaskinen bli omdirigert til port 80 på poden.

Fungerer det nå?

  • Hvis ja, så er problemet med infrastrukturen. Det er nødvendig å finne ut nøyaktig hvordan trafikken dirigeres til klyngen.
  • Hvis ikke, er problemet med Ingress-kontrolleren.

Hvis du ikke får Ingress-kontrolleren til å fungere, må du feilsøke den.

Det finnes mange varianter av Ingress-kontrollere. De mest populære er Nginx, HAProxy, Traefik, etc. (for mer informasjon om eksisterende løsninger, se vår anmeldelse — ca. oversett.) Du bør se feilsøkingsveiledningen i den relevante kontrollerdokumentasjonen. Fordi det Ingress Nginx er den mest populære Ingress-kontrolleren, har vi inkludert noen tips i artikkelen for å løse problemer relatert til den.

Feilsøking av Ingress Nginx-kontrolleren

Ingress-nginx-prosjektet har en offisiell plugin for kubectl. Team kubectl ingress-nginx kan brukes til:

  • analyse av logger, backends, sertifikater, etc.;
  • forbindelser til Ingress;
  • studerer den nåværende konfigurasjonen.

Følgende tre kommandoer vil hjelpe deg med dette:

  • kubectl ingress-nginx lint — sjekker nginx.conf;
  • kubectl ingress-nginx backend — utforsker backend (ligner på kubectl describe ingress <ingress-name>);
  • kubectl ingress-nginx logs — sjekker loggene.

Merk at du i noen tilfeller må spesifisere riktig navneområde for Ingress-kontrolleren ved å bruke flagget --namespace <name>.

Oppsummering

Feilsøking av Kubernetes kan være utfordrende hvis du ikke vet hvor du skal begynne. Du bør alltid nærme deg problemet fra bunnen og opp: start med pods, og gå deretter videre til tjenesten og Ingress. Feilsøkingsteknikkene beskrevet i denne artikkelen kan brukes på andre objekter, for eksempel:

  • ledige jobber og CronJobs;
  • StatefulSets og DaemonSets.

Jeg uttrykker min takknemlighet Gergely Risko, Daniel Weibel и Charles Christyraj for verdifulle kommentarer og tillegg.

PS fra oversetter

Les også på bloggen vår:

Kilde: www.habr.com

Legg til en kommentar