Vizuelni vodič za rešavanje problema u Kubernetesu

Bilješka. transl.: Ovaj članak je dio projektnih materijala objavljenih u javnom vlasništvu learnk8s, kompanije za obuku i individualne administratore za rad sa Kubernetesom. U njemu Daniele Polenčić, projekt menadžer, dijeli vizualne upute o tome koje korake poduzeti u slučaju općih problema s aplikacijama koje rade na klasteru K8s.

Vizuelni vodič za rešavanje problema u Kubernetesu

TL;DR: evo dijagrama koji će vam pomoći da otklonite greške pri postavljanju u Kubernetes:

Vizuelni vodič za rešavanje problema u Kubernetesu

Dijagram toka za pronalaženje i popravljanje grešaka u klasteru. Original (na engleskom) je dostupan na adresi PDF и kao slika.

Kada postavljate aplikaciju na Kubernetes, obično postoje tri komponente koje trebate definirati:

  • razvoj - ovo je vrsta recepta za kreiranje kopija aplikacije, koja se zove pods;
  • usluga — interni balansator opterećenja koji distribuira promet među podovima;
  • Ulaz — opis načina na koji će saobraćaj stići iz vanjskog svijeta do Servisa.

Evo kratkog grafičkog sažetka:

1) U Kubernetesu, aplikacije primaju promet iz vanjskog svijeta kroz dva sloja balansera opterećenja: interni i eksterni.

Vizuelni vodič za rešavanje problema u Kubernetesu

2) Interni balanser se zove Service, eksterni se zove Ingress.

Vizuelni vodič za rešavanje problema u Kubernetesu

3) Deployment kreira podove i nadgleda ih (ne kreiraju se ručno).

Vizuelni vodič za rešavanje problema u Kubernetesu

Recimo da želite da implementirate jednostavnu aplikaciju a la Hello World. YAML konfiguracija za to će izgledati ovako:

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

Definicija je prilično duga i lako se zbuniti oko toga kako su komponente međusobno povezane.

Na primjer:

  • Kada treba koristiti port 80, a kada 8080?
  • Da li trebam kreirati novi port za svaku uslugu kako se ne bi sukobljavali?
  • Da li su nazivi etiketa bitni? Da li bi svuda trebalo da budu isti?

Prije nego što se fokusiramo na otklanjanje grešaka, sjetimo se kako su tri komponente povezane jedna s drugom. Počnimo sa implementacijom i servisom.

Odnos između implementacije i usluge

Iznenadit ćete se, ali implementacija i usluga nisu ni na koji način povezani. Umjesto toga, Service upućuje direktno na Podove, zaobilazeći Deployment.

Stoga nas zanima kako su podovi i usluge međusobno povezani. Tri stvari koje treba zapamtiti:

  1. Selektor (selector) za uslugu mora odgovarati barem jednoj pod naljepnici.
  2. targetPort mora odgovarati containerPort kontejner unutar Pod.
  3. port Usluga može biti bilo šta. Različite usluge mogu koristiti isti port jer imaju različite IP adrese.

Sljedeći dijagram predstavlja sve gore navedeno u grafičkom obliku:

1) Zamislite da usluga usmjerava promet na određeni pod:

Vizuelni vodič za rešavanje problema u Kubernetesu

2) Kada kreirate pod, morate navesti containerPort za svaki kontejner u mahunama:

Vizuelni vodič za rešavanje problema u Kubernetesu

3) Prilikom kreiranja usluge morate navesti port и targetPort. Ali koji se koristi za povezivanje s kontejnerom?

Vizuelni vodič za rešavanje problema u Kubernetesu

4) Via targetPort. Mora da se poklapa containerPort.

Vizuelni vodič za rešavanje problema u Kubernetesu

5) Recimo da je u kontejneru otvoren port 3000. Zatim vrijednost targetPort trebao bi biti isti.

Vizuelni vodič za rešavanje problema u Kubernetesu

U YAML datoteci, oznake i ports / targetPort mora odgovarati:

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

Šta je sa etiketom track: canary na vrhu odjeljka Deployment? Treba li se podudarati?

Ova oznaka je specifična za implementaciju i usluga je ne koristi za usmjeravanje prometa. Drugim riječima, može se ukloniti ili dodijeliti drugačiju vrijednost.

Šta je sa selektorom matchLabels?

Uvijek mora odgovarati naljepnicama Poda, budući da ga Deployment koristi za praćenje podova.

Pretpostavimo da ste napravili ispravne izmjene. Kako ih provjeriti?

Oznaku pod možete provjeriti sljedećom naredbom:

kubectl get pods --show-labels

Ili, ako mahune pripadaju nekoliko aplikacija:

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

Gde any-name=my-app je oznaka any-name: my-app.

Da li su ostale poteškoće?

Možete se povezati na pod! Da biste to učinili, trebate koristiti naredbu port-forward u kubectl. Omogućava vam da se povežete na uslugu i provjerite vezu.

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

Ovde:

  • service/<service name> — naziv usluge; u našem slučaju jeste my-service;
  • 3000 je port koji treba otvoriti na računaru;
  • 80 - port naveden u polju port usluga.

Ako je veza uspostavljena, onda su postavke ispravne.

Ako veza ne uspije, postoji problem s oznakama ili se portovi ne poklapaju.

Odnos između usluge i ingressa

Sljedeći korak u pružanju pristupa aplikaciji uključuje postavljanje Ingressa. Ingress mora znati kako pronaći uslugu, zatim pronaći podove i usmjeriti promet na njih. Ingress pronalazi potrebnu uslugu po imenu i otvorenom portu.

U opisu ulaza i usluge dva parametra moraju se podudarati:

  1. servicePort in Ingress mora odgovarati parametru port u službi;
  2. serviceName in Ingress mora odgovarati polju name u servisu.

Sljedeći dijagram sumira veze portova:

1) Kao što već znate, Servis sluša određene port:

Vizuelni vodič za rešavanje problema u Kubernetesu

2) Ingress ima parametar koji se zove servicePort:

Vizuelni vodič za rešavanje problema u Kubernetesu

3) Ovaj parametar (servicePort) mora uvijek odgovarati port u definiciji usluge:

Vizuelni vodič za rešavanje problema u Kubernetesu

4) Ako je port 80 naveden u Servisu, onda je to neophodno servicePort je takođe bilo jednako 80:

Vizuelni vodič za rešavanje problema u Kubernetesu

U praksi morate obratiti pažnju na sljedeće redove:

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

Kako provjeriti da li Ingress radi?

Metodu možete koristiti sa kubectl port-forward, ali umjesto usluge potrebno je da se povežete na Ingress kontroler.

Prvo morate saznati naziv pod sa Ingress kontrolerom:

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

Pronađite Ingress pod (možda je u drugom imenskom prostoru) i pokrenite naredbu describeda saznate brojeve portova:

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

Konačno, povežite se na pod:

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

Sada svaki put kada pošaljete zahtjev na port 3000 na vašem računaru, on će biti proslijeđen na port 80 pod sa Ingress kontrolerom. Odlaskom na http://localhost:3000, trebali biste vidjeti stranicu koju je generirala aplikacija.

Sažetak portova

Prisjetimo se još jednom koji portovi i oznake moraju odgovarati:

  1. Selektor u definiciji usluge mora odgovarati oznaci pod;
  2. targetPort u definiciji Usluga mora odgovarati containerPort kontejner unutar mahune;
  3. port u definiciji Usluga može biti bilo šta. Različite usluge mogu koristiti isti port jer imaju različite IP adrese;
  4. servicePort Ulaz se mora podudarati port u definiciji usluge;
  5. Ime usluge mora odgovarati polju serviceName u Ingress.

Nažalost, nije dovoljno znati kako pravilno strukturirati YAML konfiguraciju.

Šta se dešava kada stvari krenu po zlu?

Pod se možda neće pokrenuti ili se može srušiti.

3 koraka za dijagnosticiranje problema sa aplikacijama u Kubernetesu

Prije nego što počnete s otklanjanjem grešaka u svojoj implementaciji, morate dobro razumjeti kako Kubernetes funkcionira.

Pošto svaka aplikacija preuzeta u K8s ima tri komponente, trebalo bi ih otkloniti određenim redoslijedom, počevši od samog dna.

  1. Prvo morate biti sigurni da kapsule rade, a zatim...
  2. Provjerite da li servis obezbjeđuje promet do podova, a zatim...
  3. Provjerite je li Ingress ispravno konfiguriran.

Vizuelni prikaz:

1) Trebali biste početi tražiti probleme od samog dna. Prvo provjerite da li podovi imaju statuse Ready и Running:

Vizuelni vodič za rešavanje problema u Kubernetesu

2) Ako su mahune spremne (Ready), trebali biste saznati da li usluga distribuira promet između podova:

Vizuelni vodič za rešavanje problema u Kubernetesu

3) Na kraju, potrebno je analizirati vezu između usluge i Ingressa:

Vizuelni vodič za rešavanje problema u Kubernetesu

1. Dijagnostika mahuna

U većini slučajeva problem je vezan za mahunu. Provjerite jesu li mahune navedene kao Ready и Running. Ovo možete provjeriti pomoću naredbe:

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

U izlazu naredbe iznad, posljednji pod je naveden kao Running и Ready, međutim, to nije slučaj za druga dva.

Kako razumjeti šta je pošlo po zlu?

Postoje četiri korisne naredbe za dijagnosticiranje podova:

  1. kubectl logs <имя pod'а> omogućava vam da izvučete trupce iz kontejnera u pod;
  2. kubectl describe pod <имя pod'а> omogućava vam da vidite listu događaja povezanih sa modulom;
  3. kubectl get pod <имя pod'а> omogućava vam da dobijete YAML konfiguraciju modula pohranjenog u Kubernetes;
  4. kubectl exec -ti <имя pod'а> bash omogućava vam da pokrenete interaktivnu komandnu ljusku u jednom od pod kontejnera

Koju da odaberete?

Činjenica je da ne postoji univerzalna komanda. Trebalo bi koristiti kombinaciju ovih.

Tipični problemi s mahunama

Postoje dvije glavne vrste grešaka modula: greške pri pokretanju i greške u toku izvođenja.

Greške pri pokretanju:

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

Greške u toku rada:

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

Neke greške su češće od drugih. Evo nekih od najčešćih grešaka i kako ih popraviti.

ImagePullBackOff

Ova greška se javlja kada Kubernetes ne može dobiti sliku za jedan od pod kontejnera. Evo tri najčešća razloga za to:

  1. Naziv slike je netačan - na primjer, pogriješili ste u njoj ili slika ne postoji;
  2. Za sliku je specificirana nepostojeća oznaka;
  3. Slika je pohranjena u privatnom registru i Kubernetes nema dozvolu da joj pristupi.

Prva dva razloga je lako eliminisati - samo ispravite naziv i oznaku slike. U slučaju potonjeg, potrebno je da unesete vjerodajnice za zatvoreni registar u Secret i dodate veze do njega u podovima. U Kubernetes dokumentaciji postoji primjer kako se to može uraditi.

Crash Loop Back Off

Kubenetes daje grešku CrashLoopBackOff, ako se kontejner ne može pokrenuti. Ovo se obično dešava kada:

  1. Postoji greška u aplikaciji koja sprečava njeno pokretanje;
  2. Kontejner pogrešno konfigurisano;
  3. Test Liveness nije uspio previše puta.

Morate pokušati doći do dnevnika iz kontejnera kako biste saznali razlog njegovog neuspjeha. Ako je teško pristupiti evidenciji jer se kontejner prebrzo ponovo pokreće, možete koristiti sljedeću naredbu:

kubectl logs <pod-name> --previous

Prikazuje poruke o grešci iz prethodne inkarnacije kontejnera.

RunContainerError

Ova greška se javlja kada se kontejner ne pokrene. Odgovara trenutku prije pokretanja aplikacije. Obično je uzrokovana pogrešnim postavkama, na primjer:

  • pokušaj montiranja nepostojećeg volumena kao što je ConfigMap ili Secrets;
  • pokušajte montirati volumen samo za čitanje kao čitanje-pisanje.

Tim je vrlo pogodan za analizu takvih grešaka kubectl describe pod <pod-name>.

Podovi su u stanju čekanja

Jednom kreirana, mahuna ostaje u stanju Pending.

Zašto se to događa?

Evo mogućih razloga (pretpostavljam da planer radi dobro):

  1. Klaster nema dovoljno resursa, kao što su procesorska snaga i memorija, za pokretanje modula.
  2. Objekt je instaliran u odgovarajućem imenskom prostoru ResourceQuota a kreiranje pod-a će uzrokovati da prostor imena pređe kvotu.
  3. Pod je vezan za Na čekanju PersistentVolumeClaim.

U tom slučaju preporučuje se korištenje naredbe kubectl describe i provjerite odjeljak Events:

kubectl describe pod <pod name>

U slučaju grešaka u vezi sa ResourceQuotas, preporučuje se pregled evidencije klastera pomoću naredbe

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

Mahune nisu spremne

Ako je pod naveden kao Running, ali nije u stanju Ready, znači provjeru njegove spremnosti (sonda spremnosti) ne uspijeva.

Kada se to dogodi, pod se ne povezuje sa uslugom i nema saobraćaja do njega. Neuspjeh testa spremnosti uzrokovan je problemima u aplikaciji. U ovom slučaju, da biste pronašli grešku, morate analizirati odjeljak Events u izlazu komande kubectl describe.

2. Servisna dijagnostika

Ako su mahune navedene kao Running и Ready, ali još uvijek nema odgovora iz aplikacije, trebali biste provjeriti postavke usluge.

Usluge su odgovorne za usmjeravanje prometa na podove ovisno o njihovim oznakama. Stoga, prva stvar koju trebate učiniti je provjeriti koliko podova radi s uslugom. Da biste to učinili, možete provjeriti krajnje tačke u servisu:

kubectl describe service <service-name> | grep Endpoints

Krajnja tačka je par vrijednosti forme <IP-адрес:порт>, a najmanje jedan takav par mora biti prisutan u izlazu (odnosno, barem jedan pod radi s uslugom).

Ako odjeljak Endpoins prazno, moguće su dvije opcije:

  1. nema podova sa ispravnom oznakom (savet: proverite da li je imenski prostor pravilno izabran);
  2. Došlo je do greške u servisnim oznakama u biraču.

Ako vidite listu krajnjih tačaka, ali i dalje ne možete pristupiti aplikaciji, onda je vjerovatni krivac greška u targetPort u opisu usluge.

Kako provjeriti funkcionalnost servisa?

Bez obzira na vrstu usluge, možete koristiti naredbu kubectl port-forward da se povežete na njega:

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

Ovde:

  • <service-name> — naziv usluge;
  • 3000 je port koji otvarate na računaru;
  • 80 - priključak na servisnoj strani.

3. Ulazna dijagnostika

Ako ste čitali do sada, onda:

  • mahune su navedene kao Running и Ready;
  • usluga uspješno distribuira promet među podovima.

Međutim, još uvijek ne možete pristupiti aplikaciji.

To znači da Ingress kontroler najvjerovatnije nije ispravno konfiguriran. Pošto je Ingress kontroler komponenta treće strane u klasteru, postoje različite metode otklanjanja grešaka u zavisnosti od njegovog tipa.

Ali prije nego što pribjegnete korištenju posebnih alata za konfiguriranje Ingress-a, možete učiniti nešto vrlo jednostavno. Ingress uses serviceName и servicePort da se povežete na servis. Morate provjeriti jesu li ispravno konfigurirani. To možete učiniti pomoću naredbe:

kubectl describe ingress <ingress-name>

Ako kolona Backend prazno, postoji velika vjerovatnoća greške u konfiguraciji. Ako su backendovi na svom mjestu, ali aplikacija još uvijek nije dostupna, onda problem može biti povezan sa:

  • Postavke pristupačnosti ulaza s javnog Interneta;
  • postavke pristupačnosti klastera sa javnog Interneta.

Možete identifikovati probleme sa infrastrukturom tako što ćete se direktno povezati na Ingress pod. Da biste to učinili, prvo pronađite modul Ingress Controller (može biti u drugom imenskom prostoru):

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

Iskoristi tim describeza postavljanje porta:

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

Konačno, povežite se na pod:

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

Sada će svi zahtjevi za portom 3000 na računaru biti preusmjereni na port 80 modula.

Radi li sada?

  • Ako da, onda je problem u infrastrukturi. Potrebno je saznati kako se tačno promet usmjerava na klaster.
  • Ako nije, onda je problem u Ingress kontroleru.

Ako ne možete natjerati Ingress kontroler da radi, morat ćete ga otkloniti.

Postoji mnogo varijanti Ingress kontrolera. Najpopularniji su Nginx, HAProxy, Traefik itd. (za više informacija o postojećim rješenjima, pogledajte naša recenzija - cca. prevod) Trebali biste pogledati vodič za rješavanje problema u relevantnoj dokumentaciji kontrolera. Zbog Ingress Nginx je najpopularniji Ingress kontroler, u članak smo uključili nekoliko savjeta za rješavanje problema povezanih s njim.

Otklanjanje grešaka na Ingress Nginx kontroleru

Ingress-nginx projekat ima zvaničnika dodatak za kubectl. Tim kubectl ingress-nginx može se koristiti za:

  • analiza dnevnika, backenda, certifikata, itd.;
  • veze sa Ingressom;
  • proučavanje trenutne konfiguracije.

U tome će vam pomoći sljedeće tri naredbe:

  • kubectl ingress-nginx lint - čekovi nginx.conf;
  • kubectl ingress-nginx backend — istražuje pozadinu (slično kao kubectl describe ingress <ingress-name>);
  • kubectl ingress-nginx logs — provjerava dnevnike.

Imajte na umu da ćete u nekim slučajevima možda morati navesti ispravan prostor imena za Ingress kontroler koristeći zastavicu --namespace <name>.

Rezime

Rješavanje problema s Kubernetesom može biti izazovno ako ne znate odakle početi. Problemu uvijek treba pristupiti odozdo prema gore: počnite sa podovima, a zatim prijeđite na uslugu i Ingress. Tehnike otklanjanja grešaka opisane u ovom članku mogu se primijeniti na druge objekte, kao što su:

  • idle Jobs i CronJobs;
  • StatefulSets i DaemonSets.

Izražavam svoju zahvalnost Gergely Risko, Daniel Weibel и Charles Christyraj za vrijedne komentare i dodatke.

PS od prevodioca

Pročitajte i na našem blogu:

izvor: www.habr.com

Dodajte komentar