Vizualní příručka pro diagnostiku chyb v Kubernetes

Pozn. přek.: Tento článek je součástí volně dostupných materiálů projektu learnk8s, školícího práci s Kubernetes pro firmy a jednotlivé administrátory. Daniele Polencic, vedoucí projektu, zde sdílí jasný návod, jaké kroky je třeba učinit v případě vzniku obecných problémů s aplikacemi běžícími v klastru K8s.

Vizualní příručka pro diagnostiku chyb v Kubernetes

TL;DR: zde je diagram, který vám pomůže odladit deployment v Kubernetes:

Vizualní příručka pro diagnostiku chyb v Kubernetes

Bloková schéma pro vyhledání a opravu chyb v klastru. V originále (v angličtině) je k dispozici v PDF a jako obrázek.

Při nasazení aplikace v Kubernetes je obvykle nutné definovat tři komponenty:

  • Nasazení — to je jakýsi recept na vytváření kopií aplikace, nazývaných pod’y;
  • Služba — interní load balancer, který rozděluje dopravu mezi pod’y;
  • Ingress — popis toho, jak bude doprava proudit z vnějšího světa k Service.

Zde je krátké grafické shrnutí:

1) V Kubernetes aplikace přijímají dopravu z vnějšího světa prostřednictvím dvou vrstev load balancerů: interního a externího.

Vizualní příručka pro diagnostiku chyb v Kubernetes

2) Vnitřní load balancer se nazývá Service, externí – Ingress.

Vizualní příručka pro diagnostiku chyb v Kubernetes

3) Deployment vytváří pod’y a sleduje je (nejsou vytvářeny ručně).

Vizualní příručka pro diagnostiku chyb v Kubernetes

Předpokládejme, že chcete nasadit jednoduchou aplikaci a la Hello World. YAML konfigurace pro ni bude vypadat následovně:

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

Definice je poměrně dlouhá a snadno se v tom ztratit, jak jsou komponenty navzájem propojeny.

Například:

  • Kdy používat port 80 a kdy 8080?
  • Měl by se vytvářet nový port pro každou službu, aby nedocházelo ke konfliktu?
  • Mají názvy labelů nějaký význam? Měly by být všude stejné?

Než se zaměříme na odladění, připomeňme si, jak jsou tři komponenty propojeny. Začněme s Deployment a Service.

Propojení Deployment a Service

Možná vás to překvapí, ale Deploymenty a Servicey nejsou nijak propojeny. Místo toho Service přímo odkazuje na pod’y mimo Deployment.

Takže nás zajímá, jak spolu souvisejí Pod'y a Service'y. Je třeba mít na paměti tři věci:

  1. Selector (selector) u Service musí odpovídat alespoň jednomu labelu Pod'u.
  2. targetPort musí odpovídat containerPort kontejneru uvnitř Pod'u.
  3. port Service může mít různá nastavení. Různé služby mohou používat stejný port, protože mají různé IP adresy.

Následující schéma zobrazuje vše výše uvedené graficky:

1) Představme si, že služba směruje provoz do určitého podu:

Vizualní příručka pro diagnostiku chyb v Kubernetes

2) Při vytváření podu je nutné zadat containerPort pro každý kontejner v podech:

Vizualní příručka pro diagnostiku chyb v Kubernetes

3) Při vytváření služby je třeba uvést port a targetPort. Ale kterým z nich se připojujete k kontejneru?

Vizualní příručka pro diagnostiku chyb v Kubernetes

4) Přes targetPort. Musí odpovídat containerPort.

Vizualní příručka pro diagnostiku chyb v Kubernetes

5) Předpokládejme, že je v kontejneru otevřen port 3000. Pak musí být hodnota targetPort stejná.

Vizualní příručka pro diagnostiku chyb v Kubernetes

V YAML souboru musí být labely a ports / targetPort shodné:

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

A co se týká labelu track: canary v horní části sekce Deployment? Musí být stejný?

Tento label se vztahuje k nasazení a služba jej nepoužívá k směrování provozu. Jinými slovy, lze jej odstranit nebo přiřadit jinou hodnotu.

A co selektor matchLabels?

Musí vždy odpovídat labelům Pod'u, neboť ho Deployment používá ke sledování podů.

Předpokládejme, že jste provedli správné úpravy. Jak je zkontrolovat?

Labely podů můžete zkontrolovat následujícím příkazem:

kubectl get pods --show-labels

Nebo pokud patří pod'y k více aplikacím:

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

Kde any-name=my-app — to je label any-name: my-app.

Stále jsou problémy?

Můžete se připojit k pod'u! K tomu použijte příkaz port-forward v kubectl. Umožňuje připojit se k službě a zkontrolovat spojení.

kubectl port-forward service/ 3000:80

Zde:

  • service/ — název služby; v našem případě je to my-service;
  • 3000 — port, který je třeba otevřít na počítači;
  • 80 — port uvedený v poli port služby.

Pokud se podařilo navázat spojení, znamená to, že nastavení je správné.

Pokud se spojení nepodařilo navázat, znamená to, že je problém s etikety nebo porty se neshodují.

Spojení Service a Ingress

Dalším krokem k zajištění přístupu k aplikaci je nastavení Ingressu. Ingress musí vědět, jak najít službu, poté najít pody a nasměrovat k nim provoz. Ingress najde požadovanou službu podle názvu a otevřeného portu.

Ve specifikaci Ingressu a Service musí být shodné dva parametry:

  1. servicePort v Ingressu by se měl shodovat s parametrem port v Service;
  2. serviceName v Ingressu by mělo odpovídat poli name v Service.

Následující schéma shrnuje propojení portů:

1) Jak již víte, služba naslouchá na určitém port:

Vizualní příručka pro diagnostiku chyb v Kubernetes

2) Ingress má parametr, nazývaný servicePort:

Vizualní příručka pro diagnostiku chyb v Kubernetes

3) Tento parametr (servicePort) musí být vždy shodný s port v definici Service:

Vizualní příručka pro diagnostiku chyb v Kubernetes

4) Pokud je v Service nastaven port 80, pak je nutné, aby servicePort také byl roven 80:

Vizualní příručka pro diagnostiku chyb v Kubernetes

V praxi je třeba věnovat pozornost následujícím řádkům:

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

Jak ověřit, zda Ingress funguje?

Můžete použít metodu s kubectl port-forward, ale místo služby se musíte připojit k Ingress controlleru.

Nejprve je potřeba zjistit název podu s Ingress controllerem:

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

Najděte pod Ingress (může patřit do jiného jmenného prostoru) a proveďte příkaz popis, abyste zjistili čísla portů:

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

Nakonec se připojte k podu:

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

Nyní, kdykoliv odešlete požadavek na port 3000 na počítači, bude přesměrován na port 80 podu s Ingress controllerem. Pokud přejdete na http://localhost:3000, měli byste vidět stránku vytvořenou aplikací.

Shrnutí portů

Pojďme si ještě jednou připomenout, které porty a etikety by měly být shodné:

  1. Selektor v definici Service by měl odpovídat etiketě podu;
  2. targetPort v definici Service by se měl shodovat s containerPort kontejnery uvnitř podu;
  3. port V definici služby může být jakákoliv. Různé služby mohou používat stejný port, protože mají různé IP adresy;
  4. servicePort Ingress musí odpovídat port v definici služby;
  5. Název služby musí odpovídat poli serviceName v Ingressu.

Bohužel nestačí vědět, jak správně strukturovat YAML konfiguraci.

Co se stane, když něco jde špatně?

Možná, že pod se nespouští nebo se zastavuje.

3 kroky k diagnostice problémů s aplikacemi v Kubernetes

Než začnete ladit deployment, je třeba mít dobrou představu o tom, jak Kubernetes funguje.

Vzhledem k tomu, že v každé aplikaci nasazené v K8s jsou tři komponenty, je důležité je ladit v určitém pořadí, začínaje nejnižší vrstvou.

  1. Nejprve je třeba se ujistit, že pody pracují, poté…
  2. Zkontrolujte, zda služba dodává provoz podům, a pak…
  3. Zkontrolujte, zda je Ingress správně nakonfigurován.

Grafické znázornění:

1) Hledání problémů by mělo začínat od spodní části. Nejprve zkontrolujte, zda mají pody stavy Ready a Dokončeno:

Vizualní příručka pro diagnostiku chyb v Kubernetes

2) Pokud jsou pody připraveny (Ready), je třeba zjistit, zda služba správně směruje provoz mezi pody:

Vizualní příručka pro diagnostiku chyb v Kubernetes

3) Nakonec je třeba analyzovat spojení mezi službou a Ingress.

Vizualní příručka pro diagnostiku chyb v Kubernetes

1. Diagnostika podů

Většinu času je problém spojen s pod. Ujistěte se, že pody jsou uvedeny jako Ready a Dokončeno. To lze zkontrolovat pomocí příkazu:

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 výstupu příkazu výše je poslední pod uveden jako Dokončeno a Ready, nicméně pro dva ostatní to neplatí.

Jak zjistit, co je špatně?

Existují čtyři užitečné příkazy pro diagnostiku podů:

  1. kubectl logs umožňuje získat logy z kontejnerů v podu;
  2. kubectl describe pod umožňuje zobrazit seznam událostí souvisejících s podem;
  3. kubectl get pod umožňuje získat YAML konfiguraci podu uloženou v Kubernetes;
  4. kubectl exec -ti bash umožňuje spustit interaktivní příkazový řádek v jednom z kontejnerů podu.

Který z nich vybrat?

Problém je v tom, že neexistuje univerzální příkaz. Je třeba použít jejich kombinaci.

Typické problémy podů

Existují dva hlavní typy chyb podů: chyby při spuštění (startup) a chyby během běhu (runtime).

Chyby spuštění:

  • ImagePullBackoff
  • ImageInspectError
  • ErrImagePull
  • ErrImageNeverPull
  • RegistryUnavailable
  • NeplatnéJménoObrazu

Chyby běhu:

  • CrashLoopBackOff
  • ChybaSpuštěníKontejneru
  • ChybaZabitíKontejneru
  • OvěřitChybuNeroot
  • ChybaSpuštěníInitKontejneru
  • ChybaVytvořeníPodSandboxu
  • ChybaKonfiguracePodSandboxu
  • ChybaZabitíPodSandboxu
  • Některé chyby se vyskytují častěji než jiné. Zde je několik nejčastějších chyb a způsoby jejich odstranění.
  • ImagePullBackOff

Tato chyba se objevuje, když Kubernetes nemůže získat obraz pro jeden z kontejnerů podu. Tady jsou tři nejčastější příčiny:

Nesprávně zadané jméno obrazu — například jste v něm udělali chybu, nebo obraz neexistuje;

Byl uveden neexistující tag pro obraz;

  1. Obraz je uložen v soukromém registru a Kubernetes nemá oprávnění k jeho přístupu.
  2. První dvě příčiny se snadno odstraní — stačí opravit jméno obrazu a tag. V případě poslední je třeba přidat údaje pro soukromý registr do Secret a přidat odkazy na něj do podů. V dokumentaci Kubernetes
  3. je příklad

jak to provést. Kubernetes zobrazí chybu , pokud se kontejner nemůže spustit. K tomu obvykle dochází, když:

CrashLoopBackOff

V aplikaci je chyba, která znemožňuje její spuštění; CrashLoopBackOffje špatně nakonfigurována

  1. Test životnosti selhal příliš mnohokrát.
  2. Kontejner Je třeba se pokusit dostat k logům z kontejneru, abyste zjistili důvod jeho selhání. Pokud je obtížné získat přístup k logům, protože se kontejner příliš rychle restartuje, můžete použít následující příkaz:;
  3. kubectl logs --previous

Tento příkaz vrátí chybové zprávy z předchozí reinkarnace kontejneru.

Tato chyba nastává, když kontejner není schopen se spustit. Odpovídá to fázi před spuštěním aplikace. Obvykle je jejím důvodem nesprávná konfigurace, například:

pokyn k připojení neexistujícího svazku, jako je ConfigMap nebo Secrets;

ChybaSpuštěníKontejneru

pokyn k připojení svazku typu pouze pro čtení jako pro zápis.

  • K analýze podobných chyb je vhodný příkaz
  • kubectl describe pod

Pody jsou ve stavu Pending Po vytvoření pod zůstává ve stavu.

Proč se to děje?

Zde jsou možné příčiny (předpokládám, že plánovač funguje správně): Pending.

V clusteru není dostatek zdrojů, jako je výpočetní výkon a paměť, pro spuštění podu.

V příslušném prostoru názvů je nastaven objekt

  1. ResourceQuota
  2. V odpovídajícím jmenném prostoru je nastavena objektová komponenta ResourceQuota Vytvoření podu povede k překročení kvóty jmenného prostoru.
  3. Pod je vázán na Pending PersistentVolumeClaim.

V takovém případě se doporučuje použít příkaz kubectl describe a zkontrolovat sekci Události:

kubectl describe pod

V případě chyb souvisejících s ResourceQuotas, doporučuje se prostudovat logy clusteru pomocí příkazu

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

Pody nejsou v stavu Ready

Pokud je pod označen jako Dokončeno, ale není ve stavu Ready, znamená to, že kontrola jeho připravenosti (readiness probe) neprobíhá úspěšně.

Když k tomu dojde, pod se nepřipojuje k službě a na něj neplyne žádný provoz. Selhání testu připravenosti je způsobeno problémy v aplikaci. V takovém případě je třeba analyzovat sekci Události ve výstupu příkazu kubectl describe.

2. Diagnostika služeb

Pokud jsou pody označeny jako Dokončeno a Ready, ale odpověď z aplikace stále není, je třeba zkontrolovat nastavení služby.

Služby zařizují směrování provozu k podům na základě jejich štítků. Proto je první věc, kterou je třeba udělat, zkontrolovat, kolik podů pracuje se službou. K tomu můžete zkontrolovat endpointy ve službě:

kubectl describe service  | grep Endpoints

Endpoint je dvojice hodnot typu <IP-адрес:порт>, a ve výstupu by měla být přítomna alespoň jedna taková dvojice (to znamená, že se se službou pracuje alespoň jeden pod).

Pokud je sekce Endpoints prázdná, mohou být dva možné scénáře:

  1. neexistuje žádný pod se správným štítkem (nápověda: zkontrolujte, zda je správně vybrán jmenný prostor);
  2. existuje chyba v štítcích služby v selektoru.

Pokud vidíte seznam endpointů, ale stále se nemůžete dostat k aplikaci, pravděpodobným viníkem je chyba v targetPort popisu služby.

Jak zkontrolovat funkčnost služby?

Bez ohledu na typ služby, můžete použít příkaz kubectl port-forward pro připojení k ní:

kubectl port-forward service/ 3000:80

Zde:

  • <service-name> — název služby;
  • 3000 — port, který otvíráte na počítači;
  • 80 — port na straně služby.

3. Diagnostika Ingress

Pokud jste dočetli až sem, tak:

  • pody jsou označeny jako Dokončeno a Ready;
  • služba úspěšně rozděluje provoz mezi pody.

Nicméně stále se nemůžete "dostat" k aplikaci.

To znamená, že pravděpodobně je špatně nastaven kontroler Ingress. Vzhledem k tomu, že kontroler Ingress je komponenta třetích stran v clusteru, existují různé metody ladění v závislosti na jeho typu.

Ale než se uchýlíte k pomoci speciálních nástrojů pro konfiguraci Ingressu, lze udělat něco velmi jednoduchého. Ingress používá serviceName a servicePort k připojení k službě. Je nutné zkontrolovat, zda jsou správně nastaveny. To lze provést pomocí příkazu:

kubectl describe ingress

Pokud je sloupec Backend plánovali udělat na Linuxu. Backend interaguje s DB, načítá potřebný seznam privilegií a poté, v závislosti na tom, jaká privilegium má autorizovaný uživatel, poskytuje přístup k podepisování finančních dokumentů a jejich zasílání k realizaci, nebo generaci nějaké zprávy. prázdný, je vysoká pravděpodobnost chyby ve konfiguraci. Pokud jsou backendy na místě, ale k aplikaci stále není přístup, může být problém spojen s:

  • nastavením dostupnosti Ingressu z veřejného internetu;
  • nastavením dostupnosti clusteru z veřejného internetu.

Pro identifikaci problémů se strukturou se můžete přímo připojit k podu Ingressu. Nejprve najděte pod Ingress kontroléru (může být v jiném jmenném 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

Použijte příkaz popis, abyste nastavili port:

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

Nakonec se připojte k podu:

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

Nyní budou všechny požadavky na port 3000 na počítači přesměrovány na port 80 podu.

Funguje nyní?

  • Pokud ano, je problém se strukturou. Je nutné zjistit, jak přesně je směrování provozu do clusteru realizováno.
  • Pokud ne, je problém s kontrolérem Ingress.

Pokud se vám nedaří rozběhnout kontrolér Ingress, budete muset provést jeho debugování.

Existuje mnoho typů kontrolérů Ingress. Nejpopulárnější jsou Nginx, HAProxy, Traefik a další. (více o existujících řešeních viz našem přehledu — pozn. překl.) Měli byste se řídit příručkou pro odstraňování problémů v dokumentaci příslušného kontroléru. Vzhledem k tomu, že Ingress Nginx je nejpopulárnějším kontrolérem Ingress, zahrnuli jsme do článku několik rad pro řešení s ním souvisejících problémů.

Debugování kontroléru Ingress Nginx

Projekt Ingress-nginx má oficiální plugin pro kubectl. Příkaz kubectl ingress-nginx můžete použít k:

  • analýze logů, backendů, certifikátů atd.;
  • připojení k Ingressu;
  • zkoumání aktuální konfigurace.

Pomohou vám v tom následující tři příkazy:

  • kubectl ingress-nginx lint — kontroluje nginx.conf;
  • kubectl ingress-nginx backend — zkoumá backend (analogicky s kubectl describe ingress);
  • kubectl ingress-nginx logs — kontroluje logy.

Upozorňujeme: v některých případech může být nutné uvést správný jmenný prostor pro kontrolér Ingress pomocí přepínače --namespace.

Shrnutí

Diagnostika v Kubernetes může být složitým úkolem, pokud nevíte, jak začít. K problému byste měli vždy přistupovat metodou „shora dolů“: začněte od pods a poté přejděte na servis a Ingress. Metody ladění popsané v článku lze aplikovat i na další objekty, jako jsou:

  • nefunkční Joby a CronJoby;
  • StatefulSety a DaemonSety.

Vyjadřuji díky Gergelymu Risko, Danielovi Weibelovi a Charlesi Christyrajovi za cenné připomínky a doplnění.

P.S. od překladatele

Přečtěte si také náš blog:

Zdroj: habr.com

Koupit spolehlivý hosting pro webové stránky s ochranou proti DDoS, VPS VDS servery 🔥 Koupit spolehlivý hosting pro webové stránky s ochranou proti DDoS, VPS VDS servery | ProHoster