Visuaalinen opas Kubernetesin vianmääritykseen

Huomautus. käännös: Tämä artikkeli on osa julkisesti julkaistuja projektin materiaaleja oppia8s, kouluttaa yrityksiä ja yksittäisiä järjestelmänvalvojia työskentelemään Kubernetesin kanssa. Siinä Daniele Polencic, projektipäällikkö, jakaa visuaaliset ohjeet siitä, mitä toimia, jos K8s-klusterissa toimivissa sovelluksissa ilmenee yleisiä ongelmia.

Visuaalinen opas Kubernetesin vianmääritykseen

TL;DR: tässä on kaavio, joka auttaa sinua korjaamaan käyttöönoton Kubernetesissa:

Visuaalinen opas Kubernetesin vianmääritykseen

Vuokaavio virheiden etsimiseen ja korjaamiseen klusterissa. Alkuperäinen (englanniksi) on saatavilla osoitteessa PDF и kuvana.

Kun otat sovelluksen käyttöön Kubernetesissa, sinun on yleensä määritettävä kolme komponenttia:

  • käyttöönoton - tämä on eräänlainen resepti sovelluksen kopioiden luomiseen, joita kutsutaan podiksi;
  • Palvelu — sisäinen kuormantasaaja, joka jakaa liikenteen koteloiden kesken;
  • Sisääntulo — kuvaus siitä, kuinka liikenne saapuu ulkomaailmasta Palveluun.

Tässä on nopea graafinen yhteenveto:

1) Kubernetesissa sovellukset vastaanottavat liikennettä ulkomaailmasta kahden kuormantasaajan kerroksen kautta: sisäisen ja ulkoisen.

Visuaalinen opas Kubernetesin vianmääritykseen

2) Sisäinen tasapainotin on nimeltään Service, ulkoinen on nimeltään Ingress.

Visuaalinen opas Kubernetesin vianmääritykseen

3) Käyttöönotto luo podeja ja valvoo niitä (niitä ei luoda manuaalisesti).

Visuaalinen opas Kubernetesin vianmääritykseen

Oletetaan, että haluat ottaa käyttöön yksinkertaisen sovelluksen a la Hei maailma. Sen YAML-kokoonpano näyttää tältä:

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

Määritelmä on melko pitkä ja on helppo hämmentää komponenttien välistä yhteyttä.

Esimerkiksi:

  • Milloin kannattaa käyttää porttia 80 ja milloin 8080?
  • Pitäisikö minun luoda uusi portti jokaiselle palvelulle, jotta ne eivät ole ristiriidassa?
  • Onko tarrojen nimillä väliä? Pitäisikö niiden olla samat kaikkialla?

Ennen kuin keskitymme virheenkorjaukseen, muistetaan kuinka nämä kolme komponenttia liittyvät toisiinsa. Aloitetaan käyttöönotosta ja palvelusta.

Käyttöönoton ja palvelun välinen suhde

Yllätyt, mutta käyttöönotto ja palvelu eivät liity millään tavalla toisiinsa. Sen sijaan palvelu osoittaa suoraan Podiin, ohittaen käyttöönoton.

Siksi olemme kiinnostuneita siitä, miten Podit ja Palvelut liittyvät toisiinsa. Kolme muistettavaa asiaa:

  1. Valitsija (selector) palvelun on vastattava vähintään yhtä Pod-tunnistetta.
  2. targetPort täytyy täsmätä containerPort säiliön sisällä.
  3. port Palvelu voi olla mitä tahansa. Eri palvelut voivat käyttää samaa porttia, koska niillä on eri IP-osoitteet.

Seuraava kaavio esittää kaikki edellä mainitut graafisessa muodossa:

1) Kuvittele, että palvelu ohjaa liikenteen tiettyyn pod:

Visuaalinen opas Kubernetesin vianmääritykseen

2) Kun luot podia, sinun on määritettävä containerPort jokaiselle säiliölle paloissa:

Visuaalinen opas Kubernetesin vianmääritykseen

3) Kun luot palvelua, sinun on määritettävä port и targetPort. Mutta kumpaa käytetään yhdistämiseen säiliöön?

Visuaalinen opas Kubernetesin vianmääritykseen

4) kautta targetPort. Sen täytyy sopia containerPort.

Visuaalinen opas Kubernetesin vianmääritykseen

5) Oletetaan, että säiliössä on auki portti 3000. Sitten arvo targetPort pitäisi olla sama.

Visuaalinen opas Kubernetesin vianmääritykseen

YAML-tiedostossa tunnisteet ja ports / targetPort täytyy täsmätä:

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

Entä etiketti track: canary Käyttöönotto-osion yläosassa? Pitäisikö sen sopia?

Tämä tunniste on käyttöönottokohtainen, eikä palvelu käytä sitä liikenteen reitittämiseen. Toisin sanoen se voidaan poistaa tai sille voidaan määrittää eri arvo.

Entä valitsin matchLabels?

Sen on aina vastattava podin tarroja, koska Deployment käyttää sitä podien seuraamiseen.

Oletetaan, että teit oikeat muokkaukset. Miten ne tarkistetaan?

Voit tarkistaa pod-etiketin seuraavalla komennolla:

kubectl get pods --show-labels

Tai jos kotelot kuuluvat useisiin sovelluksiin:

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

jossa any-name=my-app on etiketti any-name: my-app.

Onko vaikeuksia jäljellä?

Voit liittää podiin! Tätä varten sinun on käytettävä komentoa port-forward julkaisussa kubectl. Sen avulla voit muodostaa yhteyden palveluun ja tarkistaa yhteyden.

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

tässä:

  • service/<service name> - palvelun nimi; meidän tapauksessamme se on my-service;
  • 3000 on portti, joka on avattava tietokoneessa;
  • 80 - kentässä määritetty portti port palvelua.

Jos yhteys on muodostettu, asetukset ovat oikein.

Jos yhteys epäonnistuu, tarroissa on ongelma tai portit eivät täsmää.

Palvelun ja Ingressin välinen suhde

Seuraava vaihe sovelluksen käyttöoikeuden tarjoamisessa on Ingressin määrittäminen. Ingressin on osattava löytää palvelu, löytää sitten podit ja ohjata liikenne niihin. Ingress löytää tarvittavan palvelun nimen ja avoimen portin perusteella.

Ingressin ja Servicen kuvauksessa kahden parametrin on vastattava:

  1. servicePort Ingressin on vastattava parametria port palveluksessa;
  2. serviceName Ingressin on vastattava kenttää name palveluksessa.

Seuraavassa kaaviossa on yhteenveto porttiliitännöistä:

1) Kuten jo tiedät, Service kuuntelee tiettyä port:

Visuaalinen opas Kubernetesin vianmääritykseen

2) Ingressillä on parametri nimeltään servicePort:

Visuaalinen opas Kubernetesin vianmääritykseen

3) Tämä parametri (servicePort) on aina vastattava port Palvelun määritelmässä:

Visuaalinen opas Kubernetesin vianmääritykseen

4) Jos palvelussa on määritetty portti 80, se on välttämätöntä servicePort oli myös yhtä kuin 80:

Visuaalinen opas Kubernetesin vianmääritykseen

Käytännössä sinun on kiinnitettävä huomiota seuraaviin riveihin:

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

Kuinka tarkistaa, onko Ingress käynnissä?

Voit käyttää menetelmää kanssa kubectl port-forward, mutta palvelun sijaan sinun on muodostettava yhteys Ingress-ohjaimeen.

Ensin sinun on selvitettävä podin nimi Ingress-ohjaimella:

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

Etsi Ingress pod (se voi olla eri nimiavaruudessa) ja suorita komento describesaadaksesi selville porttinumerot:

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

Yhdistä lopuksi podiin:

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

Nyt joka kerta kun lähetät pyynnön tietokoneesi porttiin 3000, se välitetään podin porttiin 80 Ingress-ohjaimella. Menemällä http://localhost:3000, sinun pitäisi nähdä sovelluksen luoma sivu.

Yhteenveto porteista

Muistetaan vielä kerran, mitkä portit ja tarrat on vastattava:

  1. Palvelumäärittelyn valitsimen on vastattava podin nimiötä;
  2. targetPort määritelmässä Palvelun on vastattava containerPort säiliön sisällä;
  3. port määritelmässä palvelu voi olla mitä tahansa. Eri palvelut voivat käyttää samaa porttia, koska niillä on eri IP-osoitteet;
  4. servicePort Sisääntulon on oltava sama port Palvelun määritelmässä;
  5. Palvelun nimen on vastattava kenttää serviceName Ingressissä.

Valitettavasti ei riitä, että tiedät, kuinka YAML-kokoonpano rakennetaan oikein.

Mitä tapahtuu, kun asiat menevät pieleen?

Pod ei ehkä käynnisty tai se voi kaatua.

3 vaihetta sovellusongelmien diagnosoimiseksi Kubernetesissa

Ennen kuin aloitat käyttöönoton virheenkorjauksen, sinulla on oltava hyvä käsitys Kubernetesin toiminnasta.

Koska jokaisessa K8s:ssa ladatussa sovelluksessa on kolme komponenttia, ne tulisi tehdä tietyssä järjestyksessä, alhaalta alkaen.

  1. Ensin sinun on varmistettava, että kotelot toimivat, ja sitten...
  2. Tarkista, toimittaako palvelu liikennettä podille, ja sitten...
  3. Tarkista, onko Ingress määritetty oikein.

Visuaalinen esitys:

1) Sinun pitäisi alkaa etsiä ongelmia alhaalta. Tarkista ensin, että koteloilla on tilat Ready и Running:

Visuaalinen opas Kubernetesin vianmääritykseen

2) Jos palot ovat valmiita (Ready), sinun tulee selvittää, jakaako palvelu liikennettä podien välillä:

Visuaalinen opas Kubernetesin vianmääritykseen

3) Lopuksi sinun on analysoitava yhteys palvelun ja Ingressin välillä:

Visuaalinen opas Kubernetesin vianmääritykseen

1. Palojen diagnostiikka

Useimmissa tapauksissa ongelma liittyy koteloon. Varmista, että palot on lueteltu nimellä Ready и Running. Voit tarkistaa tämän komennolla:

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

Yllä olevassa komennon lähdössä viimeinen pod on listattu muodossa Running и ReadyTämä ei kuitenkaan päde kahdelle muulle.

Kuinka ymmärtää, mikä meni pieleen?

Palojen diagnosointiin on neljä hyödyllistä komentoa:

  1. kubectl logs <имя pod'а> voit poimia tukkeja säiliöistä kotelossa;
  2. kubectl describe pod <имя pod'а> voit tarkastella podiin liittyvien tapahtumien luetteloa;
  3. kubectl get pod <имя pod'а> antaa sinun saada Kubernetesiin tallennetun podin YAML-määritykset;
  4. kubectl exec -ti <имя pod'а> bash voit käynnistää interaktiivisen komentotulkin yhdessä pod-säiliöistä

Kumpi kannattaa valita?

Tosiasia on, että universaalia käskyä ei ole olemassa. Näiden yhdistelmää tulee käyttää.

Tyypillisiä pultin ongelmia

Pod-virheitä on kahta päätyyppiä: käynnistysvirheet ja ajonaikaiset virheet.

Käynnistysvirheet:

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

Ajonaikaiset virheet:

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

Jotkut virheet ovat yleisempiä kuin toiset. Tässä on joitain yleisimmistä virheistä ja niiden korjaamisesta.

ImagePullBackOff

Tämä virhe ilmenee, kun Kubernetes ei pysty hankkimaan kuvaa jollekin pod-säilölle. Tässä on kolme yleisintä syytä tähän:

  1. Kuvan nimi on virheellinen - esimerkiksi teit siinä virheen tai kuvaa ei ole olemassa;
  2. Kuvalle määritettiin olematon tunniste;
  3. Kuva on tallennettu yksityiseen rekisteriin, eikä Kubernetesilla ole oikeutta käyttää sitä.

Kaksi ensimmäistä syytä on helppo poistaa – korjaa vain kuvan nimi ja tunniste. Jälkimmäisen tapauksessa sinun on syötettävä suljetun rekisterin tunnistetiedot Secret ja lisättävä linkit siihen koteloissa. Kubernetes-dokumentaatiossa on esimerkki miten tämä voidaan tehdä.

Crash Loop Back Off

Kubenetes antaa virheen CrashLoopBackOff, jos säiliö ei käynnisty. Tämä tapahtuu yleensä, kun:

  1. Sovelluksessa on virhe, joka estää sen käynnistymisen;
  2. Astia määritetty väärin;
  3. Elävyystesti on epäonnistunut liian monta kertaa.

Sinun on yritettävä päästä lokeihin säiliöstä selvittääksesi syyn sen epäonnistumiseen. Jos lokeihin on vaikea päästä käsiksi, koska säilö käynnistyy uudelleen liian nopeasti, voit käyttää seuraavaa komentoa:

kubectl logs <pod-name> --previous

Se näyttää virheilmoitukset säiliön edellisestä inkarnaatiosta.

RunContainerError

Tämä virhe ilmenee, kun säilö ei käynnisty. Se vastaa hetkeä ennen sovelluksen käynnistämistä. Se johtuu yleensä vääristä asetuksista, esimerkiksi:

  • yrittää liittää olematon taltio, kuten ConfigMap tai Secrets;
  • yritys liittää vain luku -taltio luku-kirjoitukseksi.

Ryhmä soveltuu hyvin tällaisten virheiden analysointiin kubectl describe pod <pod-name>.

Podit ovat odotustilassa

Kun pod on luotu, se pysyy tilassa Pending.

Miksi tämä tapahtuu?

Tässä ovat mahdolliset syyt (oletan, että ajastin toimii hyvin):

  1. Klusterilla ei ole tarpeeksi resursseja, kuten prosessointitehoa ja muistia, podin suorittamiseen.
  2. Objekti asennetaan sopivaan nimiavaruuteen ResourceQuota ja podin luominen saa nimiavaruuden ylittämään kiintiön.
  3. Pod on sidottu Odottaa-tilaan PersistentVolumeClaim.

Tässä tapauksessa on suositeltavaa käyttää komentoa kubectl describe ja tarkista osio Events:

kubectl describe pod <pod name>

Jos virheitä liittyy ResourceQuotas, on suositeltavaa tarkastella klusterin lokeja komennolla

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

Palot eivät ole valmiita

Jos pod on luettelossa Running, mutta ei ole tilassa Ready, tarkoittaa sen valmiuden tarkistamista (valmiusanturi) epäonnistuu.

Kun näin tapahtuu, pod ei muodosta yhteyttä palveluun eikä siihen kulje liikennettä. Valmiustestin epäonnistuminen johtuu sovelluksen ongelmista. Tässä tapauksessa sinun on analysoitava osio virheen löytämiseksi Events komennon ulostulossa kubectl describe.

2. Huollon diagnostiikka

Jos palot on listattu nimellä Running и Ready, mutta sovellus ei vieläkään vastaa, sinun tulee tarkistaa palvelun asetukset.

Palvelut vastaavat liikenteen ohjaamisesta podille etikettien mukaan. Siksi ensimmäinen asia, joka sinun on tehtävä, on tarkistaa, kuinka monta podia toimii palvelun kanssa. Voit tehdä tämän tarkistamalla palvelun päätepisteet:

kubectl describe service <service-name> | grep Endpoints

Päätepiste on muodon arvopari <IP-адрес:порт>, ja vähintään yhden tällaisen parin on oltava läsnä lähdössä (eli vähintään yksi pod toimii palvelun kanssa).

Jos jakso Endpoins tyhjä, kaksi vaihtoehtoa on mahdollista:

  1. ei ole tyynyjä, joilla on oikea otsikko (vinkki: tarkista onko nimiavaruus valittu oikein);
  2. Valitsimen palvelutarroissa on virhe.

Jos näet luettelon päätepisteistä, mutta et silti pääse käyttämään sovellusta, todennäköinen syyllinen on virhe targetPort palvelukuvauksessa.

Kuinka tarkistaa palvelun toimivuus?

Palvelutyypistä riippumatta voit käyttää komentoa kubectl port-forward yhdistääksesi siihen:

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

tässä:

  • <service-name> - palvelun nimi;
  • 3000 on portti, jonka avaat tietokoneessa;
  • 80 - portti huoltopuolella.

3. Sisääntulon diagnostiikka

Jos olet lukenut tähän asti, niin:

  • palot on listattu nimellä Running и Ready;
  • palvelu jakaa onnistuneesti liikennettä podien kesken.

Et kuitenkaan pääse sovellukseen.

Tämä tarkoittaa, että Ingress-ohjainta ei todennäköisesti ole määritetty oikein. Koska Ingress-ohjain on klusterin kolmannen osapuolen komponentti, on olemassa erilaisia ​​virheenkorjausmenetelmiä sen tyypistä riippuen.

Mutta ennen kuin käytät erikoistyökaluja Ingressin määrittämiseen, voit tehdä jotain hyvin yksinkertaista. Ingressin käyttö serviceName и servicePort muodostaaksesi yhteyden palveluun. Sinun on tarkistettava, onko ne määritetty oikein. Voit tehdä tämän komennolla:

kubectl describe ingress <ingress-name>

Jos sarake Backend tyhjä, konfigurointivirheen todennäköisyys on suuri. Jos taustaohjelmat ovat paikoillaan, mutta sovellus ei vieläkään ole käytettävissä, ongelma voi liittyä:

  • Saapuminen esteettömyysasetukset julkisesta Internetistä;
  • klusterin esteettömyysasetukset julkisesta Internetistä.

Voit tunnistaa infrastruktuurin ongelmat muodostamalla yhteyden suoraan Ingress podiin. Voit tehdä tämän etsimällä ensin Ingress Controller pod (se voi olla eri nimiavaruudessa):

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

Käytä komentoa describeportin asettaminen:

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

Yhdistä lopuksi podiin:

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

Nyt kaikki tietokoneen porttia 3000 koskevat pyynnöt ohjataan podin porttiin 80.

Toimiiko se nyt?

  • Jos kyllä, niin ongelma on infrastruktuurissa. On tarpeen selvittää tarkasti, kuinka liikenne ohjataan klusteriin.
  • Jos ei, niin ongelma on Ingress-ohjaimessa.

Jos et saa Ingress-ohjainta toimimaan, sinun on suoritettava virheenkorjaus.

Ingress-ohjaimia on monia erilaisia. Suosituimmat ovat Nginx, HAProxy, Traefik jne. (lisätietoja olemassa olevista ratkaisuista, katso meidän tarkastelu - noin käännös.) Tutustu vianmääritysoppaaseen ohjaimen asiakirjoissa. Koska Ingress Nginx on suosituin Ingress-ohjain, olemme sisällyttäneet artikkeliin vinkkejä siihen liittyvien ongelmien ratkaisemiseksi.

Ingress Nginx -ohjaimen virheenkorjaus

Ingress-nginx-projektilla on virallinen kubectl-laajennus. Tiimi kubectl ingress-nginx voidaan käyttää:

  • lokien, taustaohjelmien, varmenteiden jne. analysointi;
  • yhteydet Ingressiin;
  • nykyisen kokoonpanon tutkiminen.

Seuraavat kolme komentoa auttavat sinua tässä:

  • kubectl ingress-nginx lint - tarkastukset nginx.conf;
  • kubectl ingress-nginx backend - tutkii taustaa (samanlainen kuin kubectl describe ingress <ingress-name>);
  • kubectl ingress-nginx logs - tarkistaa lokit.

Huomaa, että joissain tapauksissa saatat joutua määrittämään oikean nimiavaruuden Ingress-ohjaimelle käyttämällä lippua --namespace <name>.

Yhteenveto

Kubernetesin vianmääritys voi olla haastavaa, jos et tiedä mistä aloittaa. Sinun tulee aina lähestyä ongelmaa alhaalta ylöspäin: aloita podista ja siirry sitten palveluun ja Ingressiin. Tässä artikkelissa kuvattuja virheenkorjaustekniikoita voidaan soveltaa muihin objekteihin, kuten:

  • idle Jobs ja CronJobs;
  • StatefulSets ja DaemonSets.

ilmaisen kiitollisuuteni Gergely Risko, Daniel Weibel и Charles Christyraj arvokkaita kommentteja ja lisäyksiä varten.

PS kääntäjältä

Lue myös blogistamme:

Lähde: will.com

Lisää kommentti