Nota. transl.: Stu articulu face parte di i materiali di u prugettu publicati in u duminiu publicu , cumpagnie di furmazione è amministratori individuali per travaglià cù Kubernetes. In questu, Daniele Polencic, capu di prughjettu, sparte struzzioni visuale nantu à quali passi da piglià in casu di prublemi generali cù l'applicazioni in esecuzione nantu à u cluster K8s.

TL; DR: quì hè un diagramma chì vi aiuterà à debug implementazione in Kubernetes:
Diagrama di flussu per truvà è risolve errori in un cluster. L'uriginale (in inglese) hè dispunibule à и .
Quandu implementate una applicazione in Kubernetes, ci sò tipicamente trè cumpunenti chì avete bisognu di definisce:
- Mudellu - questu hè un tipu di ricetta per creà copie di l'applicazione, chjamata pods;
- Service - equilibratore di carica interna chì distribuisce u trafficu trà pods;
- Ingress - una descrizzione di cumu u trafficu ghjunghjerà da u mondu esternu à u serviziu.
Eccu un riassuntu gràficu rapidu:
1) In Kubernetes, l'applicazioni ricevenu u trafficu da u mondu esternu per mezu di dui strati di balancers di carica: internu è esternu.

2) U balancer internu hè chjamatu Service, quellu esternu hè chjamatu Ingress.

3) A implementazione crea pods è i monitorizza (ùn sò micca creati manualmente).

Dicemu chì vulete implementà una applicazione simplice à la Hola Monde. A cunfigurazione YAML per questu serà cusì:
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: /A definizione hè abbastanza longa è hè faciule per cunfundà cumu i cumpunenti sò in relazione trà elli.
Per esempiu:
- Quandu duvete aduprà u portu 80 è quandu avete aduprà 8080?
- Deve creà un novu portu per ogni serviziu per ùn cunflittu?
- I nomi di l'etichetta importanu? Duveranu esse listessi in ogni locu ?
Prima di fucalizza nantu à u debugging, ricurdatemu cumu i trè cumpunenti sò in relazione trà elli. Cuminciamu cù Impiegazione è Serviziu.
Relazione trà Impiegazione è Serviziu
Serete sorpresu, ma Impiegazione è Serviziu ùn sò micca cunnessi. Invece, u serviziu punta direttamente à Pods, bypassendu u Deployment.
Cusì, ci interessa cumu i Pods è i servizii sò ligati l'un à l'altru. Trè cose da ricurdà:
- selettore (
selector) per u serviziu deve currisponde à almenu una etichetta Pod. -
targetPortdeve currispondecontainerPortrécipient à l'intérieur du Pod. -
portU serviziu pò esse qualcosa. Diversi servizii ponu utilizà u stessu portu perchè anu indirizzi IP differenti.
U schema seguente rapprisenta tuttu ciò chì sopra in forma grafica:
1) Imagine chì u serviziu dirige u trafficu à un certu pod:

2) Quandu crea un pod, duvete specificà containerPort per ogni cuntainer in pods:

3) Quandu crea un serviziu, deve specificà port и targetPort. Ma quale hè utilizatu per cunnette à u cuntinuu?

4) Via targetPort. Deve currisponde containerPort.

5) Dicemu chì u portu 3000 hè apertu in u containeru targetPort deve esse u listessu.

In u schedariu YAML, etichette è ports / targetPort deve currisponde à:
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 # <<< E l'etichetta track: canary à a cima di a sezione di Deployment ? Duverebbe currisponde à ?
Questa etichetta hè specifica di implementazione è ùn hè micca utilizata da u serviziu per indirizzà u trafficu. In altre parolle, pò esse sguassatu o attribuitu un valore diversu.
Chì ci hè di u selettore matchLabels?
Deve sempre currisponde à l'etichette di u Pod, postu chì hè utilizatu da Deployment per seguità pods.
Assumimu chì avete fattu l'edizioni currette. Cumu verificà elli?
Pudete cuntrollà l'etichetta di u pod cù u cumandimu seguitu:
kubectl get pods --show-labelsO, se i pods appartenenu à parechje applicazioni:
kubectl get pods --selector any-name=my-app --show-labels Induve any-name=my-app hè una etichetta any-name: my-app.
Ci hè ancu difficultà ?
Pudete cunnette à u pod! Per fà questu, avete bisognu di utilizà u cumandamentu port-forward in kubectl. Permette di cunnette à u serviziu è verificate a cunnessione.
kubectl port-forward service/<service name> 3000:80Eccu:
-
service/<service name>- nome di serviziu; in u nostru casu hèmy-service; - 3000 hè u portu chì deve esse apertu nantu à l'urdinatore;
- 80 - portu specificatu in u campu
portserviziu.
Se a cunnessione hè stata stabilita, i paràmetri sò curretti.
Se a cunnessione falla, ci hè un prublema cù l'etichette o i porti ùn currispondenu micca.
Relazione trà u serviziu è l'ingressu
U prossimu passu per furnisce l'accessu à l'applicazione implica a creazione di Ingress. Ingress hà bisognu di sapè cumu truvà un serviziu, dopu truvà pods è u trafficu direttu à elli. Ingress trova u serviziu necessariu per nome è portu apertu.
In a descrizzione di l'Ingressu è u Serviziu, dui paràmetri anu da cuncordà:
-
servicePortin Ingress deve currisponde à u paràmetruportin serviziu; -
serviceNamein Ingress deve currisponde à u campunamein serviziu.
U schema seguente riassume e cunnessione portu:
1) Cum'è sapete digià, Service ascolta un certu port:

2) Ingress hà un paràmetru chjamatu servicePort:

3) Stu paràmetru (servicePort) deve sempre cuncordà port in a definizione di serviziu:

4) Se u portu 80 hè specificatu in Service, allora hè necessariu chì servicePort era ancu uguale à 80:

In a pratica, avete bisognu di attentu à e seguenti linee:
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: /Cumu verificà se Ingress hè in esecuzione?
Pudete aduprà u metudu cù kubectl port-forward, ma invece di u serviziu avete bisognu di cunnette à u controller Ingress.
Prima avete bisognu di truvà u nome di u pod cù u controller 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 Truvate u pod di Ingress (pò esse in un spaziu di nomi diversu) è eseguite u cumandamentu describeper sapè i numeri di portu:
kubectl describe pod nginx-ingress-controller-6fc5bcc
--namespace kube-system
| grep Ports
Ports: 80/TCP, 443/TCP, 18080/TCPInfine, cunnette à u pod:
kubectl port-forward nginx-ingress-controller-6fc5bcc 3000:80 --namespace kube-systemAvà ogni volta chì mandate una dumanda à u portu 3000 in u vostru urdinatore, serà trasmessu à u portu 80 di u pod cù u controller Ingress. Andendu à , duvete vede a pagina generata da l'applicazione.
Riassuntu di i porti
Ricurdemu una volta di più quali porti è etichette devenu cuncordà:
- U selettore in a definizione di u serviziu deve currisponde à l'etichetta di u pod;
-
targetPortin a definizione Serviziu deve currispondenucontainerPortcuntainer in un pod; -
portin a definizione Service pò esse qualcosa. Diversi servizii ponu utilizà u stessu portu perchè anu indirizzi IP differenti; -
servicePortL'ingressu deve cuncordàportin a definizione di serviziu; - U nomu di serviziu deve currisponde à u campu
serviceNamein Ingress.
Sfurtunatamente, ùn hè micca abbastanza per sapè cumu strutturate bè una cunfigurazione YAML.
Chì succede quandu e cose vanu male?
U pod ùn pò micca principià o si pò crash.
3 Passi per diagnosticà i prublemi di l'applicazione in Kubernetes
Prima di inizià a debugging di a vostra implementazione, avete bisognu di avè una bona cunniscenza di cumu funziona Kubernetes.
Siccomu ogni applicazione scaricata in K8s hà trè cumpunenti, deve esse debugged in un certu ordine, partendu da u fondu.
- Prima ci vole à assicurà chì i baccelli funzionanu, dopu ...
- Verificate se u serviziu furnisce u trafficu à i pods, è dopu ...
- Verificate se Ingress hè cunfiguratu bè.
Rappresentazione visuale:
1) Avete da principià à circà i prublemi da u fondu. Prima verificate chì i pods anu statutu Ready и Running:

2) Se i baccelli sò pronti (Ready), duvete sapè se u serviziu distribuisce u trafficu trà pods:

3) Infine, avete bisognu di analizà a cunnessione trà u serviziu è l'Ingress:

1. Diagnostics di pods
In a maiò parte di i casi, u prublema hè ligata à u pod. Assicuratevi chì i podi sò listati cum'è Ready и Running. Pudete verificà questu utilizendu u cumandimu:
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 In l'output di cumanda sopra, l'ultimu pod hè listatu cum'è Running и Ready, però, questu ùn hè micca u casu per l'altri dui.
Cumu capisce ciò chì hè andatu male?
Ci sò quattru cumandamenti utili per diagnosticà pods:
-
kubectl logs <имя pod'а>permette di estrarre logs da cuntenituri in un pod; -
kubectl describe pod <имя pod'а>permette di vede una lista di avvenimenti assuciati cù u pod; -
kubectl get pod <имя pod'а>permette di ottene a cunfigurazione YAML di un pod almacenatu in Kubernetes; -
kubectl exec -ti <имя pod'а> bashpermette di lancià una cunchiglia di cumanda interattiva in unu di i cuntenituri di pod
Qualessu duvete sceglie ?
U fattu hè chì ùn ci hè un cumandamentu universale. Una cumminazzioni di sti deve esse usatu.
Problemi tipici di pod
Ci hè dui tipi principali di errori di pod: errori di startup è errori di runtime.
Errori di startup:
-
ImagePullBackoff -
ImageInspectError -
ErrImagePull -
ErrImageNeverPull -
RegistryUnavailable -
InvalidImageName
Errori di runtime:
-
CrashLoopBackOff -
RunContainerError -
KillContainerError -
VerifyNonRootError -
RunInitContainerError -
CreatePodSandboxError -
ConfigPodSandboxError -
KillPodSandboxError -
SetupNetworkError -
TeardownNetworkError
Certi errori sò più cumuni cà altri. Eccu alcuni di l'errori più cumuni è cumu per riparà.
ImagePullBackOff
Questu errore si trova quandu Kubernetes ùn hè micca capace di ottene una maghjina per unu di i cuntenituri di pod. Eccu i trè motivi più cumuni per questu:
- U nome di l'imaghjini hè sbagliatu - per esempiu, avete fattu un sbagliu in questu, o l'imaghjini ùn esiste micca;
- Un tag inesistente hè statu specificatu per l'imaghjini;
- L'imaghjini hè guardatu in un registru privatu è Kubernetes ùn hà micca permessu di accede.
I primi dui motivi sò faciuli di eliminà - solu curreghja u nome di l'imaghjini è u tag. In u casu di l'ultimi, avete bisognu di inserisce credenziali per u registru chjusu in Secret è aghjunghje ligami à questu in pods. In a documentazione di Kubernetes cumu si pò fà questu.
Crash Loop Back Off
Kubenetes tira un errore CrashLoopBackOff, se u cuntinuu ùn pò micca principià. Questu succede di solitu quandu:
- Ci hè un bug in l'applicazione chì impedisce di lancià;
- Cuntinutu ;
- A prova di Liveness hà fallutu troppu volte.
Avete da pruvà à ghjunghje à i logs da u cuntinuu per sapè u mutivu di u so fallimentu. Se hè difficiule d'accede à i logs perchè u cuntinuu riavvia troppu rapidamente, pudete aduprà u cumandimu seguente:
kubectl logs <pod-name> --previousMostra i missaghji di errore da l'incarnazione precedente di u cuntinuu.
RunContainerError
Stu errore si verifica quandu u cuntinuu falla per inizià. Hè currisponde à u mumentu prima chì l'applicazione hè lanciata. Di solitu hè causatu da paràmetri sbagliati, per esempiu:
- tentativu di muntà un voluminu inesistente cum'è ConfigMap o Secrets;
- un tentativu di muntà un voluminu di sola lettura cum'è lettura-scrittura.
U squadra hè bè adattatu per analizà tali errori kubectl describe pod <pod-name>.
I pods sò in u statu Pending
Una volta creatu, u pod resta in u statu Pending.
Perchè sta succeta?
Eccu i ragiuni pussibuli (sugnu chì u pianificatore funziona bè):
- U cluster ùn hà micca abbastanza risorse, cum'è a putenza di trasfurmazioni è a memoria, per eseguisce u pod.
- L'ughjettu hè stallatu in u spaziu di nome appropritatu
ResourceQuotaè a creazione di un pod farà chì u spaziu di nomi per andà oltre a quota. - Pod hè ligatu à Pending
PersistentVolumeClaim.
In stu casu, hè cunsigliatu à aduprà u cumandamentu kubectl describe è verificate a rùbbrica Events:
kubectl describe pod <pod name> In casu d'errori ligati à ResourceQuotas, hè cunsigliatu per vede i logs di cluster usendu u cumandamentu
kubectl get events --sort-by=.metadata.creationTimestampI podi ùn sò micca pronti
Se pod hè listatu cum'è Running, ma ùn hè micca in un statu Ready, significa cuntrollà a so prontezza (sonda di prontezza) falla.
Quandu succede questu, u pod ùn cunnetta micca à u serviziu è ùn ci hè micca trafficu. U fallimentu di a prova di prontezza hè causatu da prublemi in l'applicazione. In questu casu, per truvà l'errore, avete bisognu di analizà a rùbbrica Events in l'output di cumandamentu kubectl describe.
2. Diagnostica di serviziu
Se i podi sò listati cum'è Running и Ready, ma ùn ci hè ancu risposta da l'applicazione, duvete verificà i paràmetri di u serviziu.
I servizii sò rispunsevuli di indirizzà u trafficu à i pods secondu e so etichette. Dunque, a prima cosa chì duvete fà hè di verificà quantu pods travaglianu cù u serviziu. Per fà questu, pudete cuntrollà i punti finali in u serviziu:
kubectl describe service <service-name> | grep Endpoints Endpoint hè un paru di valori di a forma <IP-адрес:порт>, è almenu un tali paru deve esse presente in u output (vale à dì, almenu un pod travaglia cù u serviziu).
Se rùbbrica Endpoins viotu, duie opzioni sò pussibuli:
- ùn ci hè micca pods cù l'etichetta curretta (suggerimentu: verificate se u spaziu di nome hè sceltu bè);
- Ci hè un errore in l'etichette di serviziu in u selettore.
Se vede una lista di punti finali, ma ùn pò ancu accede à l'applicazione, allora u probabile culprit hè un bug in targetPort in a descrizzione di u serviziu.
Cumu verificà a funziunalità di u serviziu?
Indipendentemente da u tipu di serviziu, pudete aduprà u cumandamentu kubectl port-forward per cunnette à questu:
kubectl port-forward service/<service-name> 3000:80Eccu:
-
<service-name>- nome di serviziu; - 3000 hè u portu chì avete apertu nantu à l'urdinatore;
- 80 - portu à u latu di serviziu.
3. Diagnostica di Ingress
Se avete lettu finu à quì, allora:
- pods sò listati cum'è
RunningиReady; - u serviziu distribuisce bè u trafficu trà pods.
Tuttavia, ùn pudete ancu ghjunghje à l'app.
Questu significa chì u controller Ingress ùn hè micca prubabilmente cunfiguratu bè. Siccomu u controller Ingress hè un cumpunente di terzu in u cluster, ci sò diversi metudi di debugging secondu u so tipu.
Ma prima di ricurdà à utilizà strumenti speciali per cunfigurà Ingress, pudete fà qualcosa assai simplice. Usi di ingressu serviceName и servicePort per cunnette à u serviziu. Avete bisognu di verificà s'ellu sò cunfigurati bè. Pudete fà questu cù u cumandimu:
kubectl describe ingress <ingress-name> Si culonna Backend viotu, ci hè una alta probabilità di un errore di cunfigurazione. Se i backend sò in u locu, ma l'applicazione ùn hè ancu accessibile, u prublema pò esse ligata à:
- Ingressu paràmetri di accessibilità da l'Internet publicu;
- paràmetri di accessibilità di cluster da l'Internet publicu.
Pudete identificà prublemi cù l'infrastruttura cunnettendu direttamente à u pod Ingress. Per fà questu, truvate prima u pod di Ingress Controller (pò esse in un spaziu di nomi diversu):
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 Aduprà u cumandamentu describeper stabilisce u portu:
kubectl describe pod nginx-ingress-controller-6fc5bcc
--namespace kube-system
| grep PortsInfine, cunnette à u pod:
kubectl port-forward nginx-ingress-controller-6fc5bcc 3000:80 --namespace kube-systemAvà tutte e dumande à u portu 3000 nantu à l'urdinatore seranu rediretti à u portu 80 di u pod.
Funziona avà ?
- Sì sì, allora u prublema hè cù l'infrastruttura. Hè necessariu di sapè esattamente cumu u trafficu hè direttu à u cluster.
- Se no, allura u prublema hè cù u controller Ingress.
Se ùn pudete micca ottene u cuntrollu Ingress per travaglià, avete da debug.
Ci hè parechje varietà di controller Ingress. I più populari sò Nginx, HAProxy, Traefik, etc. (per più infurmazione nantu à e soluzioni esistenti, vede - ca. trad.) Duvete riferite à a guida di risoluzione di prublemi in a documentazione pertinente di u controller. Perchè u hè u controller Ingress più pupulare, avemu inclusu qualchi cunsiglii in l'articulu per risolve i prublemi ligati à questu.
Debugging u controller Ingress Nginx
U prughjettu Ingress-nginx hà un ufficiale . squadra kubectl ingress-nginx pò esse usatu per:
- analisi di logs, backends, certificati, etc.;
- cunnessione à Ingress;
- studià a cunfigurazione attuale.
I seguenti trè cumandamenti vi aiuteranu cù questu:
-
kubectl ingress-nginx lint- cuntrollinginx.conf; -
kubectl ingress-nginx backend- esplora u backend (simile àkubectl describe ingress <ingress-name>); -
kubectl ingress-nginx logs- cuntrolla i logs.
Innota chì in certi casi pudete bisognu di specificà u spaziu di nome currettu per u controller Ingress usendu a bandiera --namespace <name>.
Resumen
A risoluzione di i prublemi di Kubernetes pò esse sfida se ùn sapete micca da induve cumincià. Avete sempre avvicinà u prublema da u fondu in u fondu: principià cù pods, è poi passà à u serviziu è Ingress. I tecnichi di debugging descritti in questu articulu ponu esse appiicati à altri oggetti, cum'è:
- Jobs inattivu è CronJobs;
- StatefulSets è DaemonSets.
Esprimu a mo gratitùdine , и per cumenti preziosi è aghjunte.
PS da u traduttore
Leghjite puru nant'à u nostru blog:
- «";
- «";
- «";
- «».
Source: www.habr.com
