Vizualni vodnik za odpravljanje težav s Kubernetesom

Opomba. prevod: Ta članek je del gradiva projekta, objavljenega v javnosti learnk8s, usposabljanje podjetij in posameznih skrbnikov za delo s Kubernetesom. V njem Daniele Polencic, vodja projekta, deli vizualna navodila o tem, kaj storiti v primeru splošnih težav z aplikacijami, ki se izvajajo v gruči K8s.

Vizualni vodnik za odpravljanje težav s Kubernetesom

TL;DR: tukaj je diagram, ki vam bo v pomoč pri odpravljanju napak pri uvajanju v Kubernetes:

Vizualni vodnik za odpravljanje težav s Kubernetesom

Diagram poteka za iskanje in odpravljanje napak v gruči. Izvirnik (v angleščini) je na voljo na PDF и kot slika.

Pri uvajanju aplikacije v Kubernetes morate običajno definirati tri komponente:

  • Deployment - to je nekakšen recept za ustvarjanje kopij aplikacije, imenovanih pods;
  • Service — notranji izravnalnik obremenitve, ki porazdeli promet med sklopi;
  • Vstop — opis, kako bo promet prišel iz zunanjega sveta do storitve.

Tukaj je kratek grafični povzetek:

1) V Kubernetesu aplikacije prejemajo promet iz zunanjega sveta prek dveh ravni izravnalnikov obremenitve: notranje in zunanje.

Vizualni vodnik za odpravljanje težav s Kubernetesom

2) Notranji izravnalnik se imenuje Service, zunanji pa Ingress.

Vizualni vodnik za odpravljanje težav s Kubernetesom

3) Razmestitev ustvari pode in jih nadzira (niso ustvarjeni ročno).

Vizualni vodnik za odpravljanje težav s Kubernetesom

Recimo, da želite razmestiti preprosto aplikacijo a la Pozdravljen, svet. Konfiguracija YAML zanj bo videti takole:

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 precej dolga in zlahka se zmedemo glede tega, kako so komponente med seboj povezane.

Na primer:

  • Kdaj morate uporabiti vrata 80 in kdaj 8080?
  • Ali naj ustvarim nova vrata za vsako storitev, da ne bodo v nasprotju?
  • Ali so imena založb pomembna? Naj bodo povsod enaki?

Preden se osredotočimo na odpravljanje napak, se spomnimo, kako so tri komponente med seboj povezane. Začnimo z uvajanjem in storitvijo.

Razmerje med uvajanjem in storitvijo

Presenečeni boste, vendar uvajanje in storitev nista na noben način povezana. Namesto tega storitev kaže neposredno na Pods, mimo uvajanja.

Zato nas zanima, kako so Pods in Storitve povezani med seboj. Zapomnite si tri stvari:

  1. Izbirnik (selector) za Storitev se mora ujemati z vsaj eno oznako Pod.
  2. targetPort se morajo ujemati containerPort zabojnik znotraj Pod.
  3. port Storitev je lahko karkoli. Različne storitve lahko uporabljajo ista vrata, ker imajo različne naslove IP.

Naslednji diagram predstavlja vse zgoraj navedeno v grafični obliki:

1) Predstavljajte si, da storitev usmerja promet na določen pod:

Vizualni vodnik za odpravljanje težav s Kubernetesom

2) Ko ustvarjate pod, morate določiti containerPort za vsako posodo v strokih:

Vizualni vodnik za odpravljanje težav s Kubernetesom

3) Ko ustvarjate storitev, morate določiti port и targetPort. Toda kateri se uporablja za povezavo s posodo?

Vizualni vodnik za odpravljanje težav s Kubernetesom

4) Prek targetPort. Mora se ujemati containerPort.

Vizualni vodnik za odpravljanje težav s Kubernetesom

5) Recimo, da so v vsebniku odprta vrata 3000. Nato vrednost targetPort mora biti enako.

Vizualni vodnik za odpravljanje težav s Kubernetesom

V datoteki YAML, oznake in ports / targetPort se morajo ujemati:

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

Kaj pa etiketa track: canary na vrhu razdelka Razmestitev? Bi se moralo ujemati?

Ta oznaka je specifična za uvajanje in je storitev ne uporablja za usmerjanje prometa. Z drugimi besedami, lahko ga odstranite ali mu dodelite drugo vrednost.

Kaj pa selektor matchLabels?

Vedno se mora ujemati z oznakami Poda, saj ga Deployment uporablja za sledenje podom.

Predpostavimo, da ste pravilno uredili. Kako jih preveriti?

Oznako stroka lahko preverite z naslednjim ukazom:

kubectl get pods --show-labels

Ali, če pods pripadajo več aplikacijam:

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

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

So ostale še kakšne težave?

Lahko se povežete s podom! Če želite to narediti, morate uporabiti ukaz port-forward v kubectl. Omogoča vam povezavo s storitvijo in preverjanje povezave.

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

Tukaj:

  • service/<service name> — ime storitve; v našem primeru je my-service;
  • 3000 so vrata, ki jih je treba odpreti v računalniku;
  • 80 - vrata, navedena v polju port storitev.

Če je bila povezava vzpostavljena, so nastavitve pravilne.

Če povezava ne uspe, je težava z oznakami ali pa se vrata ne ujemajo.

Razmerje med storitvijo in vstopom

Naslednji korak pri zagotavljanju dostopa do aplikacije je nastavitev Ingressa. Ingress mora vedeti, kako najti storitev, nato poiskati pode in usmeriti promet nanje. Ingress najde zahtevano storitev po imenu in odprtih vratih.

V opisu Ingress in Service se morata ujemati dva parametra:

  1. servicePort v Ingress se mora ujemati s parametrom port v službi;
  2. serviceName v Ingress se mora ujemati s poljem name v službi.

Naslednji diagram povzema povezave vrat:

1) Kot že veste, storitev posluša določenega port:

Vizualni vodnik za odpravljanje težav s Kubernetesom

2) Ingress ima imenovan parameter servicePort:

Vizualni vodnik za odpravljanje težav s Kubernetesom

3) Ta parameter (servicePort) se morajo vedno ujemati port v definiciji storitve:

Vizualni vodnik za odpravljanje težav s Kubernetesom

4) Če so v storitvi podana vrata 80, je to potrebno servicePort je bilo tudi enako 80:

Vizualni vodnik za odpravljanje težav s Kubernetesom

V praksi morate biti pozorni na naslednje vrstice:

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 preveriti, ali Ingress deluje?

Metodo lahko uporabite z kubectl port-forward, vendar se morate namesto storitve povezati s krmilnikom Ingress.

Najprej morate ugotoviti ime stroka s krmilnikom Ingress:

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

Poiščite Ingress pod (morda je v drugem imenskem prostoru) in zaženite ukaz describeče želite izvedeti številke vrat:

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

Na koncu se povežite s podom:

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

Zdaj vsakič, ko pošljete zahtevo na vrata 3000 na vašem računalniku, bo ta posredovana na vrata 80 sklopa s krmilnikom Ingress. Z odhodom na http://localhost:3000, bi morali videti stran, ki jo ustvari aplikacija.

Povzetek pristanišč

Spomnimo se še enkrat, katera vrata in oznake se morajo ujemati:

  1. Izbirnik v definiciji storitve se mora ujemati z oznako sklopa;
  2. targetPort v definiciji Storitev se mora ujemati containerPort posoda v stroku;
  3. port v definiciji Storitev je lahko karkoli. Različne storitve lahko uporabljajo ista vrata, ker imajo različne naslove IP;
  4. servicePort Vhod se mora ujemati port v definiciji storitve;
  5. Ime storitve se mora ujemati s poljem serviceName v Ingressu.

Na žalost ni dovolj vedeti, kako pravilno strukturirati konfiguracijo YAML.

Kaj se zgodi, ko gre kaj narobe?

Strok se morda ne bo zagnal ali pa se bo zrušil.

3 koraki za diagnosticiranje težav z aplikacijami v Kubernetesu

Preden začnete odpravljati napake pri uvajanju, morate dobro razumeti, kako deluje Kubernetes.

Ker ima vsaka aplikacija, prenesena v K8s, tri komponente, jih je treba odpravljati v določenem vrstnem redu, začenši od samega dna.

  1. Najprej se morate prepričati, da stroki delujejo, nato ...
  2. Preverite, ali storitev dobavlja promet enotam, nato pa ...
  3. Preverite, ali je Ingress pravilno konfiguriran.

Vizualna predstavitev:

1) Težave bi morali začeti iskati od samega dna. Najprej preverite, ali imajo sklopi statuse Ready и Running:

Vizualni vodnik za odpravljanje težav s Kubernetesom

2) Če so stroki pripravljeni (Ready), morate ugotoviti, ali storitev porazdeljuje promet med sklopi:

Vizualni vodnik za odpravljanje težav s Kubernetesom

3) Končno morate analizirati povezavo med storitvijo in Ingressom:

Vizualni vodnik za odpravljanje težav s Kubernetesom

1. Diagnostika strokov

V večini primerov je težava povezana s strokom. Prepričajte se, da so stroki navedeni kot Ready и Running. To lahko preverite z ukazom:

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

V zgornjem izhodu ukaza je zadnji pod naveden kot Running и Ready, vendar to ne velja za druga dva.

Kako razumeti, kaj je šlo narobe?

Obstajajo štirje uporabni ukazi za diagnosticiranje podov:

  1. kubectl logs <имя pod'а> omogoča pridobivanje hlodov iz posod v pod;
  2. kubectl describe pod <имя pod'а> omogoča ogled seznama dogodkov, povezanih s podom;
  3. kubectl get pod <имя pod'а> omogoča pridobitev konfiguracije YAML za pod, shranjeno v Kubernetesu;
  4. kubectl exec -ti <имя pod'а> bash omogoča zagon interaktivne ukazne lupine v enem od vsebnikov pod

Katerega izbrati?

Dejstvo je, da univerzalnega ukaza ni. Uporabiti je treba kombinacijo teh.

Tipične težave s podom

Obstajata dve glavni vrsti napak pod: napake ob zagonu in napake med izvajanjem.

Napake pri zagonu:

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

Napake med izvajanjem:

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

Nekatere napake so pogostejše od drugih. Tukaj je nekaj najpogostejših napak in kako jih odpraviti.

ImagePullBackOff

Ta napaka se pojavi, ko Kubernetes ne more pridobiti slike za enega od vsebnikov pod. Tukaj so trije najpogostejši razlogi za to:

  1. Ime slike ni pravilno - na primer, v njem ste naredili napako ali pa slika ne obstaja;
  2. Za sliko je bila določena neobstoječa oznaka;
  3. Slika je shranjena v zasebnem registru in Kubernetes nima dovoljenja za dostop do nje.

Prva dva razloga je enostavno odpraviti - samo popravite ime slike in oznako. V primeru slednjega morate v Secret vnesti poverilnice za zaprti register in v pods dodati povezave do njega. V dokumentaciji Kubernetes obstaja primer kako je to mogoče storiti.

Crash Loop Back Off

Kubenetes vrže napako CrashLoopBackOff, če se vsebnik ne more zagnati. To se običajno zgodi, ko:

  1. V aplikaciji je napaka, ki preprečuje njen zagon;
  2. posoda nepravilno konfiguriran;
  3. Test Liveness je bil prevečkrat neuspešen.

Morate poskusiti priti do dnevnikov iz zabojnika, da ugotovite razlog za njegovo okvaro. Če je težko dostopati do dnevnikov, ker se vsebnik prehitro znova zažene, lahko uporabite naslednji ukaz:

kubectl logs <pod-name> --previous

Prikazuje sporočila o napakah iz prejšnje inkarnacije vsebnika.

RunContainerError

Ta napaka se pojavi, ko se vsebnik ne zažene. Ustreza trenutku pred zagonom aplikacije. Običajno je posledica nepravilnih nastavitev, na primer:

  • poskus priklopa neobstoječega nosilca, kot je ConfigMap ali Secrets;
  • poskus namestitve nosilca samo za branje kot branje-pisanje.

Ekipa je zelo primerna za analizo takšnih napak kubectl describe pod <pod-name>.

Stroki so v stanju čakanja

Ko je enkrat ustvarjen, pod ostane v stanju Pending.

Zakaj se to dogaja?

Tu so možni razlogi (predvidevam, da razporejevalnik deluje dobro):

  1. Grozd nima dovolj virov, kot sta procesorska moč in pomnilnik, za zagon sklopa.
  2. Objekt je nameščen v ustreznem imenskem prostoru ResourceQuota in ustvarjanje sklopa bo povzročilo, da bo imenski prostor presegel kvoto.
  3. Pod je vezan na čakanje PersistentVolumeClaim.

V tem primeru je priporočljivo uporabiti ukaz kubectl describe in preverite razdelek Events:

kubectl describe pod <pod name>

V primeru napak, povezanih z ResourceQuotas, je priporočljivo, da si ogledate dnevnike gruče z ukazom

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

Stroki niso pripravljeni

Če je pod naveden kot Running, vendar ni v stanju Ready, pomeni preverjanje njegove pripravljenosti (sonda pripravljenosti) ne uspe.

Ko se to zgodi, se enota ne poveže s storitvijo in do nje ne teče promet. Neuspeh preizkusa pripravljenosti je posledica težav v aplikaciji. V tem primeru morate za iskanje napake analizirati razdelek Events v izhodu ukaza kubectl describe.

2. Servisna diagnostika

Če so stroki navedeni kot Running и Ready, vendar še vedno ni odgovora aplikacije, preverite nastavitve storitve.

Storitve so odgovorne za usmerjanje prometa do podov glede na njihove oznake. Zato morate najprej preveriti, koliko podov deluje s storitvijo. Če želite to narediti, lahko preverite končne točke v storitvi:

kubectl describe service <service-name> | grep Endpoints

Končna točka je par vrednosti obrazca <IP-адрес:порт>, in vsaj en tak par mora biti prisoten v izhodu (to pomeni, da vsaj en pod deluje s storitvijo).

Če razdelek Endpoins prazno, možni sta dve možnosti:

  1. ni podov s pravilno oznako (namig: preverite, ali je imenski prostor pravilno izbran);
  2. Pri servisnih oznakah v izbirniku je napaka.

Če vidite seznam končnih točk, vendar še vedno ne morete dostopati do aplikacije, je verjetno krivec napaka v targetPort v opisu storitve.

Kako preveriti delovanje storitve?

Ne glede na vrsto storitve lahko uporabite ukaz kubectl port-forward za povezavo z njim:

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

Tukaj:

  • <service-name> — ime storitve;
  • 3000 so vrata, ki jih odprete v računalniku;
  • 80 - vrata na servisni strani.

3. Ingress diagnostika

Če ste prebrali tako daleč, potem:

  • stroki so navedeni kot Running и Ready;
  • storitev uspešno porazdeli promet med pods.

Vendar še vedno ne morete doseči aplikacije.

To pomeni, da krmilnik Ingress najverjetneje ni pravilno konfiguriran. Ker je krmilnik Ingress komponenta tretje osebe v gruči, obstajajo različne metode odpravljanja napak, odvisno od njegove vrste.

Toda preden se zatečete k uporabi posebnih orodij za konfiguracijo Ingressa, lahko naredite nekaj zelo preprostega. Ingress uporablja serviceName и servicePort za povezavo s storitvijo. Preveriti morate, ali so pravilno konfigurirani. To lahko storite z ukazom:

kubectl describe ingress <ingress-name>

Če stolpec Backend prazno, obstaja velika verjetnost konfiguracijske napake. Če so ozadja na mestu, vendar aplikacija še vedno ni dostopna, je težava morda povezana z:

  • Nastavitve dostopnosti Ingress iz javnega interneta;
  • nastavitve dostopnosti gruče iz javnega interneta.

Težave z infrastrukturo lahko prepoznate tako, da se neposredno povežete z Ingress podom. Če želite to narediti, najprej poiščite pod Ingress Controller (lahko je v drugem imenskem 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

Uporabite ukaz describeza nastavitev vrat:

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

Na koncu se povežite s podom:

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

Zdaj bodo vse zahteve na vrata 3000 v računalniku preusmerjene na vrata 80 sklopa.

Ali zdaj deluje?

  • Če ja, potem je problem v infrastrukturi. Treba je natančno ugotoviti, kako je promet usmerjen v gručo.
  • Če ne, potem je težava v krmilniku Ingress.

Če krmilnika Ingress ne morete omogočiti, da deluje, ga boste morali odpraviti.

Obstaja veliko vrst krmilnikov Ingress. Najbolj priljubljeni so Nginx, HAProxy, Traefik itd. (za več informacij o obstoječih rešitvah glejte naš pregled — pribl. prev.) Oglejte si vodnik za odpravljanje težav v ustrezni dokumentaciji krmilnika. Zaradi Ingress Nginx je najbolj priljubljen krmilnik Ingress, smo v članek vključili nekaj nasvetov za reševanje težav, povezanih z njim.

Odpravljanje napak krmilnika Ingress Nginx

Projekt Ingress-nginx ima uradnika vtičnik za kubectl. Ekipa kubectl ingress-nginx se lahko uporablja za:

  • analiza dnevnikov, zaledij, certifikatov itd.;
  • povezave z Ingressom;
  • preučevanje trenutne konfiguracije.

Pri tem vam bodo pomagali naslednji trije ukazi:

  • kubectl ingress-nginx lint — čeki nginx.conf;
  • kubectl ingress-nginx backend — raziskuje zaledje (podobno kot kubectl describe ingress <ingress-name>);
  • kubectl ingress-nginx logs — preverja dnevnike.

Upoštevajte, da boste v nekaterih primerih morda morali podati pravilen imenski prostor za krmilnik Ingress z uporabo zastavice --namespace <name>.

Povzetek

Odpravljanje težav s Kubernetesom je lahko izziv, če ne veste, kje začeti. Težave se morate vedno lotiti od spodaj navzgor: začnite s podi, nato pa nadaljujte s storitvijo in Ingressom. Tehnike odpravljanja napak, opisane v tem članku, je mogoče uporabiti za druge predmete, kot so:

  • nedejavna opravila in CronJobs;
  • StatefulSets in DaemonSets.

Izražam svojo hvaležnost Gergely Risko, Daniel Weibel и Charles Christyraj za dragocene komentarje in dodatke.

PS od prevajalca

Preberite tudi na našem blogu:

Vir: www.habr.com

Dodaj komentar