Notă. transl.: Acest articol face parte din materialele proiectului publicate în domeniul public , instruirea companiilor și a administratorilor individuali pentru a lucra cu Kubernetes. În cadrul acestuia, Daniele Polencic, manager de proiect, împărtășește instrucțiuni vizuale cu privire la ce pași trebuie urmați în cazul unor probleme generale cu aplicațiile care rulează pe clusterul K8s.

TL;DR: iată o diagramă care vă va ajuta să depanați implementarea în Kubernetes:
Diagramă pentru găsirea și remedierea erorilor într-un cluster. Originalul (în engleză) este disponibil la и .
Când implementați o aplicație în Kubernetes, există de obicei trei componente pe care trebuie să le definiți:
- Implementare - acesta este un fel de rețetă pentru crearea unor copii ale aplicației, numite păstăi;
- Service — echilibrator de încărcare intern care distribuie traficul între poduri;
- Pătrundere — o descriere a modului în care traficul va ajunge din lumea exterioară către Serviciu.
Iată un rezumat grafic rapid:
1) În Kubernetes, aplicațiile primesc trafic din lumea exterioară prin două straturi de echilibrare a încărcăturii: intern și extern.

2) Echilibratorul intern se numește Service, cel extern se numește Ingress.

3) Deployment creează poduri și le monitorizează (nu sunt create manual).

Să presupunem că doriți să implementați o aplicație simplă la fel Salut Lume. Configurația YAML pentru aceasta va arăta astfel:
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: /Definiția este destul de lungă și este ușor să fii confuz cu privire la modul în care componentele se raportează între ele.
De exemplu:
- Când ar trebui să utilizați portul 80 și când ar trebui să utilizați 8080?
- Ar trebui să creez un port nou pentru fiecare serviciu, astfel încât acestea să nu intre în conflict?
- Numele etichetelor contează? Ar trebui să fie la fel peste tot?
Înainte de a ne concentra pe depanare, să ne amintim cum se leagă cele trei componente una cu cealaltă. Să începem cu Deployment and Service.
Relația dintre implementare și serviciu
Veți fi surprins, dar Deployment și Service nu sunt în niciun fel conectate. În schimb, Service indică direct către Poduri, ocolind Implementarea.
Astfel, ne interesează modul în care Podurile și Serviciile sunt legate între ele. Trei lucruri de reținut:
- Selector (
selector) pentru Service trebuie să se potrivească cu cel puțin o etichetă Pod. -
targetPorttrebuie să se potrivească cucontainerPortcontainer în interiorul Pod. -
portServiciul poate fi orice. Servicii diferite pot folosi același port deoarece au adrese IP diferite.
Următoarea diagramă reprezintă toate cele de mai sus sub formă grafică:
1) Imaginați-vă că serviciul direcționează traficul către un anumit pod:

2) Când creați un pod, trebuie să specificați containerPort pentru fiecare recipient în păstăi:

3) Când creați un serviciu, trebuie să specificați port и targetPort. Dar care este folosit pentru a se conecta la container?

4) Via targetPort. Trebuie să se potrivească containerPort.

5) Să presupunem că portul 3000 este deschis în container targetPort ar trebui să fie la fel.

În fișierul YAML, etichetele și ports / targetPort trebuie să se potrivească cu:
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 # <<< Ce zici de etichetă track: canary în partea de sus a secțiunii Implementare? Ar trebui să se potrivească?
Această etichetă este specifică implementării și nu este utilizată de serviciu pentru a ruta traficul. Cu alte cuvinte, poate fi eliminat sau atribuită o valoare diferită.
Dar selectorul matchLabels?
Trebuie să se potrivească întotdeauna cu etichetele Pod-ului, deoarece este folosit de Deployment pentru a urmări podurile.
Să presupunem că ați făcut modificările corecte. Cum să le verific?
Puteți verifica eticheta podului cu următoarea comandă:
kubectl get pods --show-labelsSau, dacă podurile aparțin mai multor aplicații:
kubectl get pods --selector any-name=my-app --show-labels unde any-name=my-app este o etichetă any-name: my-app.
Au mai rămas dificultăți?
Vă puteți conecta la pod! Pentru a face acest lucru, trebuie să utilizați comanda port-forward în kubectl. Vă permite să vă conectați la serviciu și să verificați conexiunea.
kubectl port-forward service/<service name> 3000:80aici:
-
service/<service name>- numele serviciului; in cazul nostru estemy-service; - 3000 este portul care trebuie deschis pe computer;
- 80 - port specificat în câmp
portserviciu.
Dacă conexiunea a fost stabilită, atunci setările sunt corecte.
Dacă conexiunea eșuează, există o problemă cu etichetele sau porturile nu se potrivesc.
Relația dintre serviciu și intrare
Următorul pas în furnizarea accesului la aplicație implică configurarea Ingress. Ingress trebuie să știe cum să găsească un serviciu, apoi să găsească pod-uri și să direcționeze traficul către ele. Ingress găsește serviciul necesar după nume și portul deschis.
În descrierea Intrării și Serviciului, doi parametri trebuie să se potrivească:
-
servicePortîn Ingress trebuie să se potrivească cu parametrulportîn funcțiune; -
serviceNameîn Ingress trebuie să se potrivească cu câmpulnameîn funcțiune.
Următoarea diagramă rezumă conexiunile portului:
1) După cum știți deja, Service ascultă un anumit port:

2) Ingress are un parametru numit servicePort:

3) Acest parametru (servicePort) trebuie să se potrivească întotdeauna port în definiția serviciului:

4) Dacă portul 80 este specificat în Service, atunci este necesar ca servicePort a fost, de asemenea, egal cu 80:

În practică, trebuie să acordați atenție următoarelor linii:
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: /Cum se verifică dacă Ingress rulează?
Puteți folosi metoda cu kubectl port-forward, dar în loc de serviciu trebuie să vă conectați la controlerul Ingress.
Mai întâi trebuie să aflați numele podului cu controlerul 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 Găsiți podul Ingress (poate fi într-un spațiu de nume diferit) și rulați comanda describepentru a afla numerele portului:
kubectl describe pod nginx-ingress-controller-6fc5bcc
--namespace kube-system
| grep Ports
Ports: 80/TCP, 443/TCP, 18080/TCPÎn cele din urmă, conectați-vă la pod:
kubectl port-forward nginx-ingress-controller-6fc5bcc 3000:80 --namespace kube-systemAcum, de fiecare dată când trimiteți o solicitare către portul 3000 de pe computer, aceasta va fi redirecționată către portul 80 al podului cu controlerul Ingress. Mergând la , ar trebui să vedeți pagina generată de aplicație.
Rezumatul porturilor
Să ne amintim încă o dată ce porturi și etichete trebuie să se potrivească:
- Selectorul din definiția serviciului trebuie să se potrivească cu eticheta podului;
-
targetPortîn definiție Serviciul trebuie să se potriveascăcontainerPortrecipient în interiorul unei păstaie; -
portîn definiție Serviciul poate fi orice. Servicii diferite pot folosi același port deoarece au adrese IP diferite; -
servicePortIntrarea trebuie să se potriveascăportîn definiția Serviciului; - Numele serviciului trebuie să corespundă câmpului
serviceNameîn Ingress.
Din păcate, nu este suficient să știți cum să structurați corect o configurație YAML.
Ce se întâmplă când lucrurile merg prost?
Este posibil ca podul să nu pornească sau să se prăbușească.
3 pași pentru a diagnostica problemele de aplicație în Kubernetes
Înainte de a începe depanarea implementării, trebuie să înțelegeți bine cum funcționează Kubernetes.
Deoarece fiecare aplicație descărcată în K8s are trei componente, acestea ar trebui să fie depanate într-o anumită ordine, începând chiar de jos.
- Mai întâi trebuie să vă asigurați că păstăile funcționează, apoi...
- Verificați dacă serviciul furnizează trafic către poduri, apoi...
- Verificați dacă Ingress este configurat corect.
Reprezentare vizuala:
1) Ar trebui să începi să cauți probleme chiar de jos. Mai întâi verificați dacă podurile au stări Ready и Running:

2) Dacă păstăile sunt gata (Ready), ar trebui să aflați dacă serviciul distribuie traficul între poduri:

3) În cele din urmă, trebuie să analizați legătura dintre serviciu și Ingress:

1. Diagnosticarea păstăilor
În cele mai multe cazuri, problema este legată de pod. Asigurați-vă că păstăile sunt listate ca Ready и Running. Puteți verifica acest lucru folosind comanda:
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 În rezultatul comenzii de mai sus, ultimul pod este listat ca Running и Ready, cu toate acestea, nu este cazul celorlalte două.
Cum să înțelegi ce a mers prost?
Există patru comenzi utile pentru diagnosticarea podurilor:
-
kubectl logs <имя pod'а>vă permite să extrageți bușteni din containere dintr-o păstăi; -
kubectl describe pod <имя pod'а>vă permite să vizualizați o listă de evenimente asociate cu pod; -
kubectl get pod <имя pod'а>vă permite să obțineți configurația YAML a unui pod stocat în Kubernetes; -
kubectl exec -ti <имя pod'а> bashvă permite să lansați un shell de comandă interactiv într-unul dintre containerele pod
Pe care ar trebui să-l alegi?
Faptul este că nu există o comandă universală. Ar trebui utilizată o combinație a acestora.
Probleme tipice cu pod
Există două tipuri principale de erori de pod: erori de pornire și erori de rulare.
Erori de pornire:
-
ImagePullBackoff -
ImageInspectError -
ErrImagePull -
ErrImageNeverPull -
RegistryUnavailable -
InvalidImageName
Erori de rulare:
-
CrashLoopBackOff -
RunContainerError -
KillContainerError -
VerifyNonRootError -
RunInitContainerError -
CreatePodSandboxError -
ConfigPodSandboxError -
KillPodSandboxError -
SetupNetworkError -
TeardownNetworkError
Unele erori sunt mai frecvente decât altele. Iată câteva dintre cele mai frecvente erori și cum să le remediați.
ImagePullBackOff
Această eroare apare atunci când Kubernetes nu poate obține o imagine pentru unul dintre containerele pod. Iată cele trei cele mai comune motive pentru aceasta:
- Numele imaginii este incorect - de exemplu, ați făcut o greșeală în ea sau imaginea nu există;
- A fost specificată o etichetă inexistentă pentru imagine;
- Imaginea este stocată într-un registru privat și Kubernetes nu are permisiunea de a o accesa.
Primele două motive sunt ușor de eliminat - doar corectați numele și eticheta imaginii. În cazul acestuia din urmă, trebuie să introduceți acreditările pentru registrul închis în Secret și să adăugați linkuri către acesta în poduri. În documentația Kubernetes cum se poate face acest lucru.
Loop de blocare înapoi
Kubenetes aruncă o eroare CrashLoopBackOff, dacă containerul nu poate porni. Acest lucru se întâmplă de obicei atunci când:
- Există un bug în aplicație care împiedică lansarea acesteia;
- Recipient ;
- Testul Liveness a eșuat de prea multe ori.
Trebuie să încercați să ajungeți la jurnalele din container pentru a afla motivul eșecului acestuia. Dacă este dificil să accesați jurnalele deoarece containerul repornește prea repede, puteți utiliza următoarea comandă:
kubectl logs <pod-name> --previousAfișează mesaje de eroare de la încarnarea anterioară a containerului.
RunContainerError
Această eroare apare atunci când containerul nu reușește să pornească. Corespunde cu momentul înainte de lansarea aplicației. De obicei, este cauzată de setări incorecte, de exemplu:
- încercarea de a monta un volum inexistent, cum ar fi ConfigMap sau Secrets;
- încercați să montați un volum numai în citire ca citire-scriere.
Echipa este potrivită pentru a analiza astfel de erori kubectl describe pod <pod-name>.
Pod-urile sunt în starea În așteptare
Odată creat, podul rămâne în stare Pending.
De ce se întâmplă acest lucru?
Iată posibilele motive (presupun că programatorul funcționează bine):
- Clusterul nu are suficiente resurse, cum ar fi puterea de procesare și memoria, pentru a rula podul.
- Obiectul este instalat în spațiul de nume corespunzător
ResourceQuotaiar crearea unui pod va face ca spațiul de nume să depășească cota. - Podul este legat la În așteptare
PersistentVolumeClaim.
În acest caz, se recomandă utilizarea comenzii kubectl describe și verificați secțiunea Events:
kubectl describe pod <pod name> În cazul erorilor legate de ResourceQuotas, este recomandat să vizualizați jurnalele cluster folosind comanda
kubectl get events --sort-by=.metadata.creationTimestampPodurile nu sunt gata
Dacă pod este listat ca Running, dar nu este într-o stare Ready, înseamnă verificarea gradului de pregătire (sondă de pregătire) eșuează.
Când se întâmplă acest lucru, podul nu se conectează la serviciu și nici un trafic nu circulă către acesta. Eșecul testului de pregătire este cauzat de probleme în aplicație. În acest caz, pentru a găsi eroarea, trebuie să analizați secțiunea Events în ieșirea comenzii kubectl describe.
2. Diagnosticare service
Dacă păstăile sunt listate ca Running и Ready, dar încă nu există niciun răspuns din partea aplicației, ar trebui să verificați setările serviciului.
Serviciile sunt responsabile pentru direcționarea traficului către poduri, în funcție de etichetele acestora. Prin urmare, primul lucru pe care trebuie să-l faceți este să verificați câte poduri funcționează cu serviciul. Pentru a face acest lucru, puteți verifica punctele finale din serviciu:
kubectl describe service <service-name> | grep Endpoints Punctul final este o pereche de valori ale formularului <IP-адрес:порт>și cel puțin o astfel de pereche trebuie să fie prezentă în ieșire (adică cel puțin un pod funcționează cu serviciul).
Daca sectiunea Endpoins gol, sunt posibile două opțiuni:
- nu există pod-uri cu eticheta corectă (sugestie: verificați dacă spațiul de nume este selectat corect);
- Există o eroare la etichetele serviciului din selector.
Dacă vedeți o listă de puncte finale, dar tot nu puteți accesa aplicația, atunci cel mai probabil vinovat este o eroare targetPort în descrierea serviciului.
Cum se verifică funcționalitatea serviciului?
Indiferent de tipul de serviciu, puteți utiliza comanda kubectl port-forward pentru a te conecta la el:
kubectl port-forward service/<service-name> 3000:80aici:
-
<service-name>- numele serviciului; - 3000 este portul pe care îl deschideți pe computer;
- 80 - port pe partea de serviciu.
3. Diagnosticarea intrării
Dacă ai citit până aici, atunci:
- păstăile sunt listate ca
RunningиReady; - serviciul distribuie cu succes traficul între poduri.
Cu toate acestea, încă nu puteți accesa aplicația.
Aceasta înseamnă că, cel mai probabil, controlerul Ingress nu este configurat corect. Deoarece controlerul Ingress este o componentă terță parte a clusterului, există diferite metode de depanare în funcție de tipul său.
Dar înainte de a recurge la utilizarea instrumentelor speciale pentru a configura Ingress, puteți face ceva foarte simplu. Utilizări de intrare serviceName и servicePort pentru a vă conecta la serviciu. Trebuie să verificați dacă sunt configurate corect. Puteți face acest lucru folosind comanda:
kubectl describe ingress <ingress-name> Dacă coloana Backend gol, există o mare probabilitate de eroare de configurare. Dacă backend-urile sunt la locul lor, dar aplicația nu este încă accesibilă, atunci problema poate fi legată de:
- Intrare setări de accesibilitate de pe internetul public;
- setările de accesibilitate ale clusterului de pe internetul public.
Puteți identifica problemele cu infrastructura conectându-vă direct la podul Ingress. Pentru a face acest lucru, mai întâi găsiți podul Ingress Controller (poate fi într-un alt spațiu de nume):
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 Utilizați comanda describepentru a seta portul:
kubectl describe pod nginx-ingress-controller-6fc5bcc
--namespace kube-system
| grep PortsÎn cele din urmă, conectați-vă la pod:
kubectl port-forward nginx-ingress-controller-6fc5bcc 3000:80 --namespace kube-systemAcum toate cererile către portul 3000 de pe computer vor fi redirecționate către portul 80 al podului.
Merge acum?
- Dacă da, atunci problema este cu infrastructura. Este necesar să aflați exact cum este direcționat traficul către cluster.
- Dacă nu, atunci problema este cu controlerul Ingress.
Dacă nu puteți face controlerul Ingress să funcționeze, va trebui să-l depanați.
Există multe varietăți de controlere Ingress. Cele mai populare sunt Nginx, HAProxy, Traefik etc. (pentru mai multe informații despre soluțiile existente, consultați - aprox. traducere) Ar trebui să consultați ghidul de depanare din documentația relevantă a controlerului. Deoarece este cel mai popular controler Ingress, am inclus câteva sfaturi în articol pentru a rezolva problemele legate de acesta.
Depanarea controlerului Ingress Nginx
Proiectul Ingress-nginx are un oficial . Echipă kubectl ingress-nginx poate fi folosit pentru:
- analiza jurnalelor, backend-urilor, certificatelor etc.;
- conexiuni la Ingress;
- studiind configurația actuală.
Următoarele trei comenzi vă vor ajuta în acest sens:
-
kubectl ingress-nginx lint- controalenginx.conf; -
kubectl ingress-nginx backend— explorează backend-ul (similar cukubectl describe ingress <ingress-name>); -
kubectl ingress-nginx logs— verifică jurnalele.
Rețineți că, în unele cazuri, poate fi necesar să specificați spațiul de nume corect pentru controlerul Ingress folosind steag --namespace <name>.
Rezumat
Depanarea Kubernetes poate fi o provocare dacă nu știi de unde să începi. Ar trebui să abordați întotdeauna problema de jos în sus: începeți cu pod-uri și apoi treceți la service și Ingress. Tehnicile de depanare descrise în acest articol pot fi aplicate altor obiecte, cum ar fi:
- Jobs inactiv și CronJobs;
- StatefulSets și DaemonSets.
Îmi exprim recunoștința , и pentru comentarii și completări valoroase.
PS de la traducator
Citește și pe blogul nostru:
- «»;
- «»;
- «»;
- «".
Sursa: www.habr.com
