Notu. transl.: Ĉi tiu artikolo estas parto de la projektmaterialoj publikigitaj en la publika domeno , trejnado de kompanioj kaj individuaj administrantoj por labori kun Kubernetes. En ĝi, Daniele Polencic, projektestro, dividas vidajn instrukciojn pri kiaj paŝoj fari en kazo de ĝeneralaj problemoj kun aplikaĵoj kurantaj sur la K8s-areo.

TL;DR: jen diagramo, kiu helpos vin sencimigi deplojon en Kubernetes:
Fluodiagramo por trovi kaj ripari erarojn en areto. La originalo (en la angla) haveblas ĉe и .
Dum deplojado de aplikaĵo al Kubernetes, estas kutime tri komponantoj, kiujn vi devas difini:
- deplojo - ĉi tio estas speco de recepto por krei kopiojn de la aplikaĵo, nomataj guŝoj;
- servo — interna ŝarĝbalancilo, kiu distribuas trafikon inter podoj;
- Ingreso — priskribo de kiel trafiko venos de la ekstera mondo al la Servo.
Jen rapida grafika resumo:
1) En Kubernetes, aplikoj ricevas trafikon de la ekstera mondo per du tavoloj de ŝarĝbalanciloj: interna kaj ekstera.

2) La interna ekvilibro nomiĝas Servo, la ekstera nomiĝas Eniro.

3) Deplojo kreas podojn kaj kontrolas ilin (ili ne estas kreitaj permane).

Ni diru, ke vi volas disfaldi simplan aplikaĵon Saluton mondo. La YAML-agordo por ĝi aspektos jene:
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: /La difino estas sufiĉe longa kaj estas facile konfuziĝi pri kiel la komponantoj rilatas unu al la alia.
Ekzemple:
- Kiam vi uzu la havenon 80 kaj kiam vi uzu 8080?
- Ĉu mi kreu novan havenon por ĉiu servo por ke ili ne konfliktu?
- Ĉu etikednomoj gravas? Ĉu ili estu ĉie samaj?
Antaŭ ol koncentriĝi pri senararigado, ni memoru kiel la tri komponantoj rilatas unu al la alia. Ni komencu per Deplojo kaj Servo.
Rilato inter Deplojo kaj Servo
Vi estos surprizita, sed Deplojo kaj Servo neniel estas ligitaj. Anstataŭe, Servo montras rekte al Pods, preterirante Deplojon.
Tiel, ni interesiĝas pri kiel Pods kaj Servoj rilatas unu al la alia. Tri aferoj por memori:
- Elektilo (
selector) por Servo devas kongrui kun almenaŭ unu Pod-etikedo. -
targetPortdevas kongruicontainerPortujo ene de la Pod. -
portServo povas esti io ajn. Malsamaj servoj povas uzi la saman havenon ĉar ili havas malsamajn IP-adresojn.
La sekva diagramo reprezentas ĉion ĉi supre en grafika formo:
1) Imagu, ke la servo direktas trafikon al certa pod:

2) Kreante pod, vi devas specifi containerPort por ĉiu ujo en guŝoj:

3) Kreante servon, vi devas specifi port и targetPort. Sed kiu estas uzata por konekti al la ujo?

4) Vojo targetPort. Ĝi devas kongrui containerPort.

5) Ni diru en la ujo estas malfermita pordo 3000. Tiam la valoro targetPort devus esti la sama.

En la YAML-dosiero, etikedoj kaj ports / targetPort devas kongrui:
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 # <<< Kio pri la etikedo track: canary ĉe la supro de la sekcio Deployment? Ĉu ĝi devus kongrui?
Ĉi tiu etikedo estas deploj-specifa kaj ne estas uzata de la servo por direkti trafikon. Alivorte, ĝi povas esti forigita aŭ asignita malsama valoro.
Kio pri la elektilo matchLabels?
Ĝi ĉiam devas kongrui kun la etikedoj de la Pod, ĉar ĝi estas uzata de Deployment por spuri podojn.
Ni supozu, ke vi faris la ĝustajn redaktojn. Kiel kontroli ilin?
Vi povas kontroli la pod-etikedon per la sekva komando:
kubectl get pods --show-labelsAŭ, se balgoj apartenas al pluraj aplikoj:
kubectl get pods --selector any-name=my-app --show-labels Kie any-name=my-app estas etikedo any-name: my-app.
Ĉu restas malfacilaĵoj?
Vi povas konektiĝi al la pod! Por fari tion, vi devas uzi la komandon port-forward en kubectl. Ĝi permesas vin konekti al la servo kaj kontroli la konekton.
kubectl port-forward service/<service name> 3000:80Jen:
-
service/<service name>— servonomo; en nia kazo estasmy-service; - 3000 estas la haveno, kiu devas esti malfermita en la komputilo;
- 80 - haveno specifita en la kampo
portservo.
Se la konekto estis establita, tiam la agordoj estas ĝustaj.
Se la konekto malsukcesas, estas problemo kun la etikedoj aŭ la havenoj ne kongruas.
Rilato inter Servo kaj Eniro
La sekva paŝo en havigi aliron al la aplikaĵo implikas agordi Ingress. Ingress devas scii kiel trovi servon, poste trovi podojn kaj direkti trafikon al ili. Ingress trovas la postulatan servon laŭ nomo kaj malferma haveno.
En la priskribo de Eniro kaj Servo du parametroj devas kongrui:
-
servicePorten Eniro devas kongrui kun la parametroporten Servo; -
serviceNameen Ingress devas kongrui kun la kamponameen Servo.
La sekva diagramo resumas la havenkonektoj:
1) Kiel vi jam scias, Servo aŭskultas certan port:

2) Eniro havas parametron nomitan servicePort:

3) Ĉi tiu parametro (servicePort) ĉiam devas kongrui port en la Difino de Servo:

4) Se haveno 80 estas specifita en Servo, tiam necesas tion servicePort estis ankaŭ egala al 80:

En la praktiko, vi devas atenti la jenajn liniojn:
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: /Kiel kontroli ĉu Ingress funkcias?
Vi povas uzi la metodon kun kubectl port-forward, sed anstataŭ la servo vi devas konekti al la Ingress-regilo.
Unue vi devas eltrovi la nomon de la pod kun la Ingress-regilo:
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 Trovu la Ingress-podon (ĝi povas esti en malsama nomspaco) kaj rulu la komandon describepor ekscii la havennumerojn:
kubectl describe pod nginx-ingress-controller-6fc5bcc
--namespace kube-system
| grep Ports
Ports: 80/TCP, 443/TCP, 18080/TCPFine, konektu al la pod:
kubectl port-forward nginx-ingress-controller-6fc5bcc 3000:80 --namespace kube-systemNun ĉiufoje kiam vi sendas peton al la haveno 3000 en via komputilo, ĝi estos plusendita al la haveno 80 de la pod kun la Ingress-regilo. Irante al , vi devus vidi la paĝon generitan de la aplikaĵo.
Resumo de havenoj
Ni rememoru denove, kiuj havenoj kaj etikedoj devas kongrui:
- La elektilo en la Servodifino devas kongrui kun la etikedo de la pod;
-
targetPorten la difino Servo devas kongruicontainerPortujo ene de balgo; -
porten la difino Servo povas esti io ajn. Malsamaj servoj povas uzi la saman havenon ĉar ili havas malsamajn IP-adresojn; -
servicePortEniro devas kongruiporten la difino de Servo; - La servonomo devas kongrui kun la kampo
serviceNameen Eniro.
Bedaŭrinde, ne sufiĉas scii kiel ĝuste strukturi YAML-agordon.
Kio okazas kiam aferoj misfunkcias?
La pod eble ne komenciĝas aŭ ĝi povas kraŝi.
3 Paŝoj por Diagnozi Aplikajn Problemojn en Kubernetes
Antaŭ ol vi komencas sencimigi vian deplojon, vi devas bone kompreni kiel funkcias Kubernetes.
Ĉar ĉiu aplikaĵo elŝutita en K8s havas tri komponentojn, ili devus esti elpurigitaj en certa ordo, komencante de la malsupro.
- Unue vi devas certigi, ke la guŝoj funkcias, poste...
- Kontrolu ĉu la servo provizas trafikon al la podoj, kaj tiam...
- Kontrolu ĉu Ingress estas agordita ĝuste.
Vida reprezentado:
1) Vi devus komenci serĉi problemojn de la fundo. Unue kontrolu, ke balgoj havas statusojn Ready и Running:

2) Se la balgoj estas pretaj (Ready), vi devus ekscii ĉu la servo distribuas trafikon inter podoj:

3) Fine, vi devas analizi la rilaton inter la servo kaj la Eniro:

1. Diagnozo de podoj
Plejofte la problemo rilatas al la pod. Certigu, ke balgoj estas listigitaj kiel Ready и Running. Vi povas kontroli ĉi tion per la komando:
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 En la komanda eligo supre, la lasta pod estas listigita kiel Running и Ready, tamen, ĉi tio ne estas la kazo por la aliaj du.
Kiel kompreni kio misfunkciis?
Estas kvar utilaj komandoj por diagnozi podojn:
-
kubectl logs <имя pod'а>permesas al vi ĉerpi ŝtipojn el ujoj en balgo; -
kubectl describe pod <имя pod'а>permesas al vi vidi liston de eventoj asociitaj kun la pod; -
kubectl get pod <имя pod'а>permesas vin akiri la YAML-agordon de pod stokita en Kubernetes; -
kubectl exec -ti <имя pod'а> bashpermesas al vi lanĉi interagan komandan ŝelon en unu el la podujoj
Kiun vi elektu?
La fakto estas, ke ne ekzistas universala komando. Kombinaĵo de ĉi tiuj devus esti uzata.
Tipaj podproblemoj
Estas du ĉefaj specoj de pod-eraroj: lanĉaj eraroj kaj rultempaj eraroj.
Komencaj eraroj:
-
ImagePullBackoff -
ImageInspectError -
ErrImagePull -
ErrImageNeverPull -
RegistryUnavailable -
InvalidImageName
Rultempaj eraroj:
-
CrashLoopBackOff -
RunContainerError -
KillContainerError -
VerifyNonRootError -
RunInitContainerError -
CreatePodSandboxError -
ConfigPodSandboxError -
KillPodSandboxError -
SetupNetworkError -
TeardownNetworkError
Iuj eraroj estas pli oftaj ol aliaj. Jen kelkaj el la plej oftaj eraroj kaj kiel ripari ilin.
ImagePullBackOff
Ĉi tiu eraro okazas kiam Kubernetes ne povas akiri bildon por unu el la podujoj. Jen la tri plej oftaj kialoj por ĉi tio:
- La nomo de la bildo estas malĝusta - ekzemple, vi faris eraron en ĝi, aŭ la bildo ne ekzistas;
- Neekzistanta etikedo estis specifita por la bildo;
- La bildo estas konservita en privata registro kaj Kubernetes ne havas permeson aliri ĝin.
La unuaj du kialoj estas facile elimineblaj - nur korektu la bildonomon kaj etikedon. En la kazo de ĉi-lasta, vi devas enigi akreditaĵojn por la fermita registro en Sekreta kaj aldoni ligilojn al ĝi en podoj. En la dokumentado de Kubernetes kiel tio povas esti farita.
Kraŝa Buklo Malŝaltita
Kubenetes ĵetas eraron CrashLoopBackOff, se la ujo ne povas komenci. Ĉi tio kutime okazas kiam:
- Estas cimo en la aplikaĵo, kiu malhelpas ĝin lanĉi;
- Ujo ;
- La Liveness-testo malsukcesis tro multajn fojojn.
Vi devas provi atingi la ŝtipojn de la ujo por ekscii la kialon de ĝia malsukceso. Se estas malfacile aliri la protokolojn ĉar la ujo rekomencas tro rapide, vi povas uzi la jenan komandon:
kubectl logs <pod-name> --previousĜi montras erarmesaĝojn de la antaŭa enkarniĝo de la ujo.
RunContainerError
Ĉi tiu eraro okazas kiam la ujo ne komenciĝas. Ĝi respondas al la momento antaŭ ol la aplikaĵo estas lanĉita. Ĝi estas kutime kaŭzita de malĝustaj agordoj, ekzemple:
- provante munti neekzistantan volumenon kiel ConfigMap aŭ Sekretoj;
- provo munti nurlegeblan volumon kiel lego-skribi.
La teamo taŭgas por analizi tiajn erarojn kubectl describe pod <pod-name>.
Pods estas en Pritraktata stato
Fojo kreita, la balgo restas en la ŝtato Pending.
Kial ĉi tio okazas?
Jen la eblaj kialoj (mi supozas, ke la planilo funkcias bone):
- La areto ne havas sufiĉajn rimedojn, kiel pretigpovon kaj memoron, por funkcii la pod.
- La objekto estas instalita en la taŭga nomspaco
ResourceQuotakaj kreado de pod kaŭzos la nomspacon preterpasi la kvoton. - Pod estas ligita al Pritraktata
PersistentVolumeClaim.
En ĉi tiu kazo, oni rekomendas uzi la komandon kubectl describe kaj kontrolu la sekcion Events:
kubectl describe pod <pod name> En kazo de eraroj rilataj al ResourceQuotas, oni rekomendas vidi la grapolprotokolojn uzante la komandon
kubectl get events --sort-by=.metadata.creationTimestampPods ne estas Pretaj
Se pod estas listigita kiel Running, sed ne estas en stato Ready, signifas kontroli ĝian pretecon (preteca sondo) malsukcesas.
Kiam tio okazas, la pod ne konektas al la servo kaj neniu trafiko fluas al ĝi. La fiasko de la preteca testo estas kaŭzita de problemoj en la aplikaĵo. En ĉi tiu kazo, por trovi la eraron, vi devas analizi la sekcion Events en la komanda eligo kubectl describe.
2. Servaj diagnozoj
Se balgoj estas listigitaj kiel Running и Ready, sed ankoraŭ ne estas respondo de la aplikaĵo, vi devus kontroli la servo-agordojn.
Servoj respondecas pri direktado de trafiko al podoj depende de siaj etikedoj. Tial, la unua afero, kiun vi devas fari, estas kontroli kiom da podoj funkcias kun la servo. Por fari tion, vi povas kontroli la finpunktojn en la servo:
kubectl describe service <service-name> | grep Endpoints Finpunkto estas paro de valoroj de la formo <IP-адрес:порт>, kaj almenaŭ unu tia paro devas ĉeesti en la eligo (tio estas, almenaŭ unu pod funkcias kun la servo).
Se sekcio Endpoins malplena, du opcioj estas eblaj:
- ne ekzistas podoj kun la ĝusta etikedo (sugesto: kontrolu ĉu la nomspaco estas ĝuste elektita);
- Estas eraro en la servaj etikedoj en la elektilo.
Se vi vidas liston de finpunktoj sed ankoraŭ ne povas aliri la aplikaĵon, tiam la verŝajna kulpulo estas cimo en targetPort en la priskribo de la servo.
Kiel kontroli la funkciojn de la servo?
Sendepende de la speco de servo, vi povas uzi la komandon kubectl port-forward por konekti al ĝi:
kubectl port-forward service/<service-name> 3000:80Jen:
-
<service-name>— servonomo; - 3000 estas la haveno, kiun vi malfermas en la komputilo;
- 80 - haveno ĉe la servoflanko.
3. Diagnozo de eniro
Se vi legis ĉi tien, tiam:
- balgoj estas listigitaj kiel
RunningиReady; - la servo sukcese distribuas trafikon inter podoj.
Tamen, vi ankoraŭ ne povas "atingi" la aplikaĵon.
Ĉi tio signifas, ke la Ingress-regilo plej verŝajne ne estas agordita ĝuste. Ĉar la Ingress-regilo estas triaparta komponento en la areto, ekzistas malsamaj sencimigaj metodoj depende de ĝia tipo.
Sed antaŭ ol vi uzas specialajn ilojn por agordi Ingress, vi povas fari ion tre simplan. Enir-uzoj serviceName и servicePort por konekti al la servo. Vi devas kontroli ĉu ili estas ĝuste agorditaj. Vi povas fari tion uzante la komandon:
kubectl describe ingress <ingress-name> Se kolumno Backend malplena, estas alta probablo de agorda eraro. Se la backends estas en loko, sed la aplikaĵo ankoraŭ ne estas alirebla, tiam la problemo eble rilatas al:
- Eniri alireblajn agordojn de la publika Interreto;
- agordoj de alirebleco de cluster de la publika Interreto.
Vi povas identigi problemojn kun la infrastrukturo konektante rekte al la Ingress-podo. Por fari tion, unue trovu la Ingress Controller pod (ĝi povas esti en malsama nomspaco):
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 Uzu la komandon describepor agordi la havenon:
kubectl describe pod nginx-ingress-controller-6fc5bcc
--namespace kube-system
| grep PortsFine, konektu al la pod:
kubectl port-forward nginx-ingress-controller-6fc5bcc 3000:80 --namespace kube-systemNun ĉiuj petoj al haveno 3000 en la komputilo estos redirektitaj al haveno 80 de la pod.
Ĉu ĝi funkcias nun?
- Se jes, tiam la problemo estas kun la infrastrukturo. Necesas ekscii ĝuste kiel trafiko estas direktita al la areto.
- Se ne, tiam la problemo estas kun la Ingress-regilo.
Se vi ne povas funkcii la Ingress-regilon, vi devos sencimigi ĝin.
Estas multaj varioj de Ingress-regiloj. La plej popularaj estas Nginx, HAProxy, Traefik, ktp. (por pliaj informoj pri ekzistantaj solvoj, vidu - ĉ. traduk.) Vi devus raporti al la gvidilo pri solvo de problemoj en la koncerna dokumentaro pri regilo. Ĉar la estas la plej populara Ingress-regilo, ni inkluzivis kelkajn konsiletojn en la artikolo por solvi problemojn rilatajn al ĝi.
Sencimigi la Ingress Nginx-regilon
La projekto Ingress-nginx havas oficialulon . Teamo kubectl ingress-nginx povas esti uzata por:
- analizo de protokoloj, backends, atestiloj, ktp.;
- ligoj al Ingress;
- studante la nunan agordon.
La sekvaj tri komandoj helpos vin pri tio:
-
kubectl ingress-nginx lint- ĉekojnginx.conf; -
kubectl ingress-nginx backend— esploras la malantaŭon (simila alkubectl describe ingress <ingress-name>); -
kubectl ingress-nginx logs— kontrolas la protokolojn.
Notu, ke en iuj kazoj vi eble bezonos specifi la ĝustan nomspacon por la Ingress-regilo uzante la flagon --namespace <name>.
Resumo
Solvi Kubernetes povas esti malfacila se vi ne scias kie komenci. Vi ĉiam devas alproksimiĝi al la problemo de malsupre supren: komencu per podoj, kaj poste transiru al la servo kaj Eniro. La sencimigaj teknikoj priskribitaj en ĉi tiu artikolo povas esti aplikitaj al aliaj objektoj, kiel ekzemple:
- idle Jobs kaj CronJobs;
- StatefulSets kaj DaemonSets.
Mi esprimas mian dankemon , и por valoraj komentoj kaj aldonoj.
PS de tradukisto
Legu ankaŭ en nia blogo:
- «»;
- «»;
- «»;
- «".
fonto: www.habr.com
