Vizuální průvodce řešením problémů s Kubernetes

Poznámka. přel.: Tento článek je součástí materiálů projektu publikovaných ve veřejné doméně učit se8s, školící společnosti a jednotlivé administrátory pro práci s Kubernetes. Daniele Polencic, projektový manažer, v něm sdílí vizuální pokyny, jaké kroky podniknout v případě obecných problémů s aplikacemi běžícími na clusteru K8s.

Vizuální průvodce řešením problémů s Kubernetes

TL;DR: zde je diagram, který vám pomůže ladit nasazení v Kubernetes:

Vizuální průvodce řešením problémů s Kubernetes

Vývojový diagram pro hledání a opravu chyb v clusteru. Originál (v angličtině) je k dispozici na PDF и jako obrázek.

Při nasazování aplikace do Kubernetes jsou obvykle tři komponenty, které musíte definovat:

  • Rozvinutí - jedná se o jakýsi recept na vytváření kopií aplikace, nazývané pody;
  • Servis — interní load balancer, který rozděluje provoz mezi moduly;
  • Ingress — popis toho, jak se provoz dostane z vnějšího světa ke službě.

Zde je rychlé grafické shrnutí:

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

Vizuální průvodce řešením problémů s Kubernetes

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

Vizuální průvodce řešením problémů s Kubernetes

3) Deployment vytváří moduly a monitoruje je (nevytvářejí se ručně).

Vizuální průvodce řešením problémů s Kubernetes

Řekněme, že chcete nasadit jednoduchou aplikaci a la Ahoj světe. Konfigurace YAML pro něj bude vypadat takto:

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 je snadné se zmást, jak spolu komponenty souvisí.

Například:

  • Kdy byste měli použít port 80 a kdy byste měli použít 8080?
  • Mám pro každou službu vytvořit nový port, aby nebyly v konfliktu?
  • Záleží na názvech štítků? Mají být všude stejní?

Než se zaměříme na ladění, připomeňme si, jak spolu tyto tři složky souvisí. Začněme s nasazením a servisem.

Vztah mezi nasazením a službou

Budete překvapeni, ale Deployment a Service spolu nijak nesouvisí. Místo toho služba ukazuje přímo na moduly a obchází nasazení.

Zajímá nás tedy, jak spolu moduly a služby souvisí. Tři věci k zapamatování:

  1. Selektor (selector) pro službu musí odpovídat alespoň jednomu štítku podu.
  2. targetPort se musí shodovat containerPort kontejner uvnitř pod.
  3. port Služba může být cokoliv. Různé služby mohou používat stejný port, protože mají různé IP adresy.

Následující diagram znázorňuje vše výše uvedené v grafické podobě:

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

Vizuální průvodce řešením problémů s Kubernetes

2) Při vytváření podu musíte specifikovat containerPort pro každý kontejner v luscích:

Vizuální průvodce řešením problémů s Kubernetes

3) Při vytváření služby musíte specifikovat port и targetPort. Který se ale používá pro připojení ke kontejneru?

Vizuální průvodce řešením problémů s Kubernetes

4) Přes targetPort. Musí se shodovat containerPort.

Vizuální průvodce řešením problémů s Kubernetes

5) Řekněme, že je v kontejneru otevřený port 3000. Pak hodnota targetPort by mělo být stejné.

Vizuální průvodce řešením problémů s Kubernetes

V souboru YAML, štítky a ports / targetPort se musí shodovat:

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 štítek track: canary v horní části sekce Nasazení? Mělo by se to shodovat?

Tento štítek je specifický pro nasazení a služba jej nepoužívá ke směrování provozu. Jinými slovy, může být odstraněn nebo přiřazena jiná hodnota.

A co volič matchLabels?

Vždy se musí shodovat se štítky podu, protože ho používá Deployment ke sledování modulů.

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

Štítek pod můžete zkontrolovat pomocí následujícího příkazu:

kubectl get pods --show-labels

Nebo pokud moduly patří k několika aplikacím:

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

Kde any-name=my-app je štítek any-name: my-app.

Zůstaly nějaké potíže?

Můžete se připojit k modulu! Chcete-li to provést, musíte použít příkaz port-forward v kubectl. Umožňuje vám připojit se ke službě a zkontrolovat připojení.

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

Zde:

  • service/<service name> - Název služby; v našem případě je my-service;
  • 3000 je port, který je třeba otevřít v počítači;
  • 80 - port zadaný v poli port servis.

Pokud bylo spojení navázáno, pak jsou nastavení správná.

Pokud se připojení nezdaří, je problém se štítky nebo se porty neshodují.

Vztah mezi Service a Ingress

Dalším krokem při poskytování přístupu k aplikaci je nastavení Ingress. Ingress potřebuje vědět, jak najít službu, pak najít pody a nasměrovat na ně provoz. Ingress vyhledá požadovanou službu podle názvu a otevřeného portu.

V popisu Ingress a Service se musí shodovat dva parametry:

  1. servicePort v Ingress musí odpovídat parametru port ve službě;
  2. serviceName v Ingress musí odpovídat poli name ve službě.

Následující diagram shrnuje připojení portů:

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

Vizuální průvodce řešením problémů s Kubernetes

2) Ingress má parametr nazvaný servicePort:

Vizuální průvodce řešením problémů s Kubernetes

3) Tento parametr (servicePort) se musí vždy shodovat port v definici služby:

Vizuální průvodce řešením problémů s Kubernetes

4) Je-li ve službě Service uveden port 80, je to nutné servicePort se také rovnalo 80:

Vizuální průvodce řešením problémů s 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 zkontrolovat, zda Ingress běží?

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

Nejprve musíte zjistit název modulu s ovladačem 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

Najděte modul Ingress (může být v jiném jmenném prostoru) a spusťte příkaz describejak zjistit čí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 modulu:

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

Nyní pokaždé, když odešlete požadavek na port 3000 na vašem počítači, bude předán na port 80 modulu s řadičem Ingress. Tím, že půjdete do http://localhost:3000, měli byste vidět stránku vygenerovanou aplikací.

Shrnutí portů

Ještě jednou si připomeňme, které porty a štítky se musí shodovat:

  1. Selektor v definici služby musí odpovídat štítku podu;
  2. targetPort v definici Služba se musí shodovat containerPort nádoba uvnitř pouzdra;
  3. port v definici Služba může být cokoliv. Různé služby mohou používat stejný port, protože mají různé IP adresy;
  4. servicePort Vstup musí odpovídat port v definici Služby;
  5. Název služby musí odpovídat poli serviceName ve společnosti Ingress.

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

Co se stane, když se věci pokazí?

Modul se nemusí spustit nebo se může zřítit.

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

Než začnete ladit své nasazení, musíte dobře rozumět tomu, jak Kubernetes funguje.

Protože každá aplikace stažená v K8s má tři součásti, měly by být laděny v určitém pořadí, počínaje úplně zdola.

  1. Nejprve se musíte ujistit, že lusky fungují, pak...
  2. Zkontrolujte, zda služba dodává provoz do modulů, a poté...
  3. Zkontrolujte, zda je Ingress správně nakonfigurován.

Vizuální reprezentace:

1) Měli byste začít hledat problémy od samého dna. Nejprve zkontrolujte, zda pody mají stavy Ready и Running:

Vizuální průvodce řešením problémů s Kubernetes

2) Pokud jsou lusky připraveny (Ready), měli byste zjistit, zda služba rozděluje provoz mezi moduly:

Vizuální průvodce řešením problémů s Kubernetes

3) Nakonec musíte analyzovat spojení mezi službou a Ingress:

Vizuální průvodce řešením problémů s Kubernetes

1. Diagnostika lusků

Ve většině případů problém souvisí s pod. Ujistěte se, že pody jsou uvedeny jako Ready и Running. Můžete to 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

Ve výše uvedeném výstupu příkazu je poslední modul uveden jako Running и Ready, to však není případ zbylých dvou.

Jak pochopit, co se pokazilo?

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

  1. kubectl logs <имя pod'а> umožňuje extrahovat polena z kontejnerů v podu;
  2. kubectl describe pod <имя pod'а> umožňuje zobrazit seznam událostí spojených s pod;
  3. kubectl get pod <имя pod'а> umožňuje získat konfiguraci YAML pod uloženého v Kubernetes;
  4. kubectl exec -ti <имя pod'а> bash umožňuje spustit interaktivní příkazový shell v jednom z kontejnerů pod

Kterou byste si měli vybrat?

Faktem je, že neexistuje žádný univerzální příkaz. Měla by být použita jejich kombinace.

Typické problémy s pod

Existují dva hlavní typy chyb pod: chyby při spuštění a chyby za běhu.

Chyby při spouštění:

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

Runtime chyby:

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

Některé chyby jsou častější než jiné. Zde jsou některé z nejčastějších chyb a jak je opravit.

ImagePullBackOff

K této chybě dochází, když Kubernetes nemůže získat obrázek pro jeden z kontejnerů pod. Zde jsou tři nejčastější důvody:

  1. Název obrázku je nesprávný – například jste se v něm spletli nebo obrázek neexistuje;
  2. Pro obrázek byla zadána neexistující značka;
  3. Obrázek je uložen v soukromém registru a Kubernetes nemá oprávnění k němu přistupovat.

První dva důvody lze snadno odstranit – stačí opravit název obrázku a značku. V případě druhého je třeba zadat přihlašovací údaje pro uzavřený registr do Tajemství a přidat na něj odkazy v pods. V dokumentaci Kubernetes existuje příklad jak se to dá udělat.

Crash Loop Back Off

Kubenetes vyvolá chybu CrashLoopBackOff, pokud kontejner nelze spustit. K tomu obvykle dochází, když:

  1. V aplikaci je chyba, která brání jejímu spuštění;
  2. kontejner nakonfigurován nesprávně;
  3. Test živosti selhal příliš mnohokrát.

Musíte se pokusit dostat k protokolům z kontejneru, abyste zjistili důvod jeho selhání. Pokud je obtížné získat přístup k protokolům, protože se kontejner restartuje příliš rychle, můžete použít následující příkaz:

kubectl logs <pod-name> --previous

Zobrazuje chybové zprávy z předchozí inkarnace kontejneru.

RunContainerError

K této chybě dochází, když se kontejner nespustí. Odpovídá okamžiku před spuštěním aplikace. Obvykle je to způsobeno nesprávným nastavením, například:

  • pokus o připojení neexistujícího svazku, jako je ConfigMap nebo Secrets;
  • pokus o připojení svazku pouze pro čtení jako čtení i zápis.

Tým je vhodný pro analýzu takových chyb kubectl describe pod <pod-name>.

Moduly jsou ve stavu Nevyřízeno

Po vytvoření zůstává modul ve stavu Pending.

Proč se to děje?

Zde jsou možné důvody (předpokládám, že plánovač funguje dobře):

  1. Cluster nemá dostatek prostředků, jako je výpočetní výkon a paměť, ke spuštění modulu.
  2. Objekt je nainstalován v příslušném jmenném prostoru ResourceQuota a vytvoření podu způsobí, že jmenný prostor překročí kvótu.
  3. Pod je vázán na Nevyřízeno PersistentVolumeClaim.

V tomto případě se doporučuje použít příkaz kubectl describe a zkontrolujte sekci Events:

kubectl describe pod <pod name>

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

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

Pody nejsou připraveny

Pokud je pod uveden jako Running, ale není ve stavu Ready, znamená kontrolu jeho připravenosti (sonda připravenosti) selže.

Když k tomu dojde, modul se nepřipojí ke službě a neproudí k němu žádný provoz. Selhání testu připravenosti je způsobeno problémy v aplikaci. V tomto případě, abyste našli chybu, musíte analyzovat sekci Events ve výstupu příkazu kubectl describe.

2. Servisní diagnostika

Pokud jsou pody uvedeny jako Running и Ready, ale aplikace stále neodpovídá, měli byste zkontrolovat nastavení služby.

Služby jsou zodpovědné za směrování provozu do podů v závislosti na jejich štítcích. Proto první věc, kterou musíte udělat, je zkontrolovat, kolik modulů pracuje se službou. Chcete-li to provést, můžete zkontrolovat koncové body ve službě:

kubectl describe service <service-name> | grep Endpoints

Koncový bod je dvojice hodnot formuláře <IP-адрес:порт>, a alespoň jeden takový pár musí být přítomen na výstupu (tj. alespoň jeden modul pracuje se službou).

Pokud oddíl Endpoins prázdné, jsou možné dvě možnosti:

  1. neexistují žádné pody se správným štítkem (nápověda: zkontrolujte, zda je jmenný prostor vybrán správně);
  2. Ve selektoru je chyba ve štítcích služeb.

Pokud vidíte seznam koncových bodů, ale stále nemáte přístup k aplikaci, pak je pravděpodobným viníkem chyba v targetPort v popisu služby.

Jak zkontrolovat funkčnost služby?

Bez ohledu na typ služby můžete příkaz použít kubectl port-forward připojit se k němu:

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

Zde:

  • <service-name> - Název služby;
  • 3000 je port, který otevřete v počítači;
  • 80 - port na straně služby.

3. Diagnostika vstupu

Pokud jste dočetli až sem, pak:

  • lusky jsou uvedeny jako Running и Ready;
  • služba úspěšně rozděluje provoz mezi moduly.

K aplikaci se však stále nemůžete dostat.

To znamená, že řadič Ingress s největší pravděpodobností není správně nakonfigurován. Vzhledem k tomu, že řadič Ingress je komponenta třetí strany v clusteru, existují různé metody ladění v závislosti na jeho typu.

Než se však uchýlíte k použití speciálních nástrojů pro konfiguraci Ingress, můžete udělat něco velmi jednoduchého. Ingress používá serviceName и servicePort pro připojení ke službě. Musíte zkontrolovat, zda jsou správně nakonfigurovány. Můžete to udělat pomocí příkazu:

kubectl describe ingress <ingress-name>

Pokud sloupec Backend prázdné, existuje vysoká pravděpodobnost chyby konfigurace. Pokud jsou backendy na svém místě, ale aplikace stále není přístupná, problém může souviset s:

  • nastavení přístupnosti Ingress z veřejného internetu;
  • nastavení přístupnosti clusteru z veřejného internetu.

Problémy s infrastrukturou můžete identifikovat přímým připojením k modulu Ingress. Chcete-li to provést, nejprve najděte modul Ingress Controller (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 describepro nastavení portu:

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

Nakonec se připojte k modulu:

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

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

Funguje to teď?

  • Pokud ano, pak je problém s infrastrukturou. Je potřeba přesně zjistit, jak je provoz do clusteru směrován.
  • Pokud ne, problém je v řadiči Ingress.

Pokud se vám nepodaří zprovoznit Ingress controller, budete ho muset odladit.

Existuje mnoho druhů ovladačů Ingress. Nejoblíbenější jsou Nginx, HAProxy, Traefik atd. (Další informace o stávajících řešeních viz naše recenze - Cca. překlad.) Měli byste se podívat na průvodce odstraňováním problémů v příslušné dokumentaci ovladače. Protože Ingress Nginx je nejpopulárnější Ingress controller, do článku jsme zahrnuli několik tipů, jak vyřešit problémy s ním související.

Ladění řadiče Ingress Nginx

Projekt Ingress-nginx má úředníka plugin pro kubectl. tým kubectl ingress-nginx lze použít pro:

  • analýza logů, backendů, certifikátů atd.;
  • připojení k Ingress;
  • studovat aktuální konfiguraci.

Následující tři příkazy vám s tím pomohou:

  • kubectl ingress-nginx lint — šeky nginx.conf;
  • kubectl ingress-nginx backend – prozkoumá backend (podobně jako kubectl describe ingress <ingress-name>);
  • kubectl ingress-nginx logs — kontroluje protokoly.

Všimněte si, že v některých případech může být nutné zadat správný jmenný prostor pro Ingress controller pomocí příznaku --namespace <name>.

Shrnutí

Odstraňování problémů s Kubernetes může být náročné, pokud nevíte, kde začít. Vždy byste měli k problému přistupovat zdola nahoru: začněte s pody a poté přejděte ke službě a Ingress. Techniky ladění popsané v tomto článku lze použít na jiné objekty, například:

  • nečinné úlohy a CronJobs;
  • StatefulSets a DaemonSets.

Vyjadřuji svou vděčnost Gergely Risko, Daniel Weibel и Charles Christyraj za cenné připomínky a doplnění.

PS od překladatele

Přečtěte si také na našem blogu:

Zdroj: www.habr.com

Přidat komentář