Una guia visual per resoldre problemes de Kubernetes

Nota. transl.: Aquest article forma part dels materials del projecte disponibles gratuïtament aprendre8sque ensenya a empreses i administradors individuals a treballar amb Kubernetes. En ell, Daniele Polencic, líder del projecte, comparteix una guia visual sobre quins passos cal seguir si hi ha problemes generals amb les aplicacions que s'executen en un clúster K8s.

Una guia visual per resoldre problemes de Kubernetes

TL;DR: Aquí teniu un diagrama que us ajudarà a depurar el vostre desplegament de Kubernetes:

Una guia visual per resoldre problemes de Kubernetes

Diagrama de flux per trobar i corregir errors en un clúster. L'original (en anglès) està disponible a PDF и com a imatge.

Quan es desplega una aplicació a Kubernetes, normalment hi ha tres components que cal definir:

  • Desplegament - aquesta és una recepta per crear còpies de l'aplicació, anomenada pods;
  • servei - un equilibrador de càrrega intern que distribueix el trànsit entre pods;
  • Ingrés - una descripció de com arribarà el trànsit del món exterior al Servei.

Aquí teniu un breu resum gràfic:

1) A Kubernetes, les aplicacions reben trànsit del món exterior mitjançant dues capes d'equilibradors de càrrega: intern i extern.

Una guia visual per resoldre problemes de Kubernetes

2) L'equilibrador intern s'anomena Servei, l'extern és Ingress.

Una guia visual per resoldre problemes de Kubernetes

3) El desplegament crea pods i els supervisa (no es creen manualment).

Una guia visual per resoldre problemes de Kubernetes

Suposem que voleu desplegar una aplicació senzilla al mateix temps Hola món. La configuració de YAML serà així:

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 definició és força llarga i és fàcil confondre's sobre com es relacionen els components entre si.

Per exemple:

  • Quan he d'utilitzar el port 80 i quan he d'utilitzar 8080?
  • S'ha de crear un port nou per a cada servei perquè no entren en conflicte?
  • Importen els noms de les etiquetes? Haurien de ser iguals a tot arreu?

Abans de centrar-nos en la depuració, repassem com es relacionen els tres components. Comencem amb el desplegament i el servei.

Relació entre el desplegament i el servei

Us sorprendrà, però els desplegaments i els serveis no estan connectats de cap manera. En lloc d'això, el Servei apunta directament als Pods, sense passar pel desplegament.

Per tant, ens interessa com es relacionen els Pods i els Serveis. Tres coses a recordar:

  1. Selector (selector) per a un Servei ha de coincidir com a mínim amb una etiqueta Pod.
  2. targetPort ha de coincidir amb containerPort contenidor dins del Pod.
  3. port El servei pot ser qualsevol cosa. Diferents serveis poden utilitzar el mateix port perquè tenen diferents adreces IP.

El diagrama següent representa tot allò anterior en forma gràfica:

1) Imagineu que el servei envia trànsit a un pod determinat:

Una guia visual per resoldre problemes de Kubernetes

2) Quan creeu un pod, heu de configurar containerPort per a cada recipient en beines:

Una guia visual per resoldre problemes de Kubernetes

3) Quan creeu un servei, heu d'especificar port и targetPort. Però per quin d'ells passa la connexió amb el contenidor?

Una guia visual per resoldre problemes de Kubernetes

4) A través targetPort. Ha de coincidir amb containerPort.

Una guia visual per resoldre problemes de Kubernetes

5) Suposem que el port 3000 està obert al contenidor, llavors el valor targetPort hauria de ser el mateix.

Una guia visual per resoldre problemes de Kubernetes

Al fitxer YAML, les etiquetes i ports / targetPort ha de coincidir amb:

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

Què passa amb l'etiqueta track: canary a la part superior de la secció de Desplegament? Hauria de coincidir?

Aquesta etiqueta és específica del desplegament i el servei no l'utilitza per encaminar el trànsit. En altres paraules, es pot eliminar o assignar un valor diferent.

Què passa amb el selector matchLabels?

Sempre ha de coincidir amb les etiquetes del pod, ja que Deployment l'utilitza per fer un seguiment dels pods.

Suposem que heu fet les edicions correctes. Com comprovar-los?

Podeu comprovar l'etiqueta dels pods amb l'ordre següent:

kubectl get pods --show-labels

O, si els pods són propietat de diverses aplicacions:

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

On any-name=my-app és una etiqueta any-name: my-app.

Queden dificultats?

Pots connectar-te a un pod! Per a això cal utilitzar l'ordre port-forward en kubectl. Permet connectar-se al servei i comprovar la connexió.

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

Aquí:

  • service/<service name> - nom del servei; en el nostre cas ho és my-service;
  • 3000 és el port que voleu obrir a l'ordinador;
  • 80 - port especificat al camp port servei.

Si la connexió s'ha establert correctament, la configuració és correcta.

Si no s'ha pogut establir la connexió, hi ha un problema amb les etiquetes o els ports no coincideixen.

Relació entre Servei i Ingress

El següent pas per proporcionar accés a l'aplicació està relacionat amb la configuració de l'Ingress. Ingress ha de saber com trobar el servei, després trobar els pods i enviar-hi trànsit. Ingress troba el servei desitjat pel nom i el port obert.

A la descripció d'Ingress i Service, dos paràmetres han de coincidir:

  1. servicePort a Ingress ha de coincidir amb el paràmetre port en servei;
  2. serviceName a Ingress ha de coincidir amb el camp name en servei.

El diagrama següent resumeix les connexions del port:

1) Com ja sabeu, Servei escolta alguns port:

Una guia visual per resoldre problemes de Kubernetes

2) Ingress té un paràmetre anomenat servicePort:

Una guia visual per resoldre problemes de Kubernetes

3) Aquest paràmetre (servicePort) sempre ha de coincidir port a la definició de servei:

Una guia visual per resoldre problemes de Kubernetes

4) Si s'especifica el port 80 al servei, és necessari que això servicePort també era igual a 80:

Una guia visual per resoldre problemes de Kubernetes

A la pràctica, cal parar atenció a les línies següents:

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

Com comprovar si Ingress funciona?

Podeu utilitzar el mètode amb kubectl port-forward, però en comptes d'un servei, cal que us connecteu al controlador Ingress.

Primer heu d'esbrinar el nom del pod amb el controlador 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

Cerqueu el pod Ingress (pot ser en un espai de noms diferent) i executeu l'ordre describeper esbrinar els números de port:

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

Finalment, connecteu-vos al pod:

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

Ara, cada vegada que envieu una sol·licitud al port 3000 de la màquina, es redirigirà al port 80 del pod Ingress. Anar a http://localhost:3000, hauríeu de veure la pàgina generada per l'aplicació.

Resum per ports

Recordem de nou quins ports i etiquetes han de coincidir:

  1. El selector de la definició del servei ha de coincidir amb l'etiqueta del pod;
  2. targetPort a la definició del servei ha de coincidir containerPort un recipient dins d'una beina;
  3. port a la definició del servei pot ser qualsevol cosa. Diferents serveis poden utilitzar el mateix port perquè tenen diferents adreces IP;
  4. servicePort L'entrada ha de coincidir port en la definició del servei;
  5. El nom del servei ha de coincidir amb el camp serviceName a Ingress.

Per desgràcia, no n'hi ha prou amb saber estructurar correctament una configuració YAML.

Què passa quan alguna cosa va malament?

És possible que el pod no s'iniciï o que s'estigui bloquejant.

3 passos per resoldre problemes d'aplicacions a Kubernetes

Abans de començar a depurar la vostra implementació, heu de tenir una bona comprensió de com funciona Kubernetes.

Com que hi ha tres components a cada aplicació baixada a K8s, depureu-los en un ordre determinat, començant per la part inferior.

  1. Primer heu d'assegurar-vos que les beines funcionen, després...
  2. Comproveu si el servei està enviant trànsit als pods i, a continuació...
  3. Comproveu si Ingress està configurat correctament.

Representació visual:

1) Comenceu a buscar problemes des de baix. Primer comproveu que les beines tenen estats Ready и Running:

Una guia visual per resoldre problemes de Kubernetes

2) Si les beines estan a punt (Ready), hauríeu d'esbrinar si el servei distribueix el trànsit entre pods:

Una guia visual per resoldre problemes de Kubernetes

3) Finalment, cal analitzar la connexió entre el servei i Ingress:

Una guia visual per resoldre problemes de Kubernetes

1. Diagnòstic de pods

En la majoria dels casos, el problema està relacionat amb la beina. Assegureu-vos que les beines figuren com a Ready и Running. Podeu comprovar-ho amb l'ordre:

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

A la sortida de l'ordre anterior, l'últim pod apareix com a Running и Ready, però aquest no és el cas dels altres dos.

Com entendre què va fallar?

Hi ha quatre ordres útils per diagnosticar pods:

  1. kubectl logs <имя pod'а> permet extreure registres dels contenidors d'una beina;
  2. kubectl describe pod <имя pod'а> us permet veure la llista d'esdeveniments associats al pod;
  3. kubectl get pod <имя pod'а> us permet obtenir la configuració YAML d'un pod emmagatzemat a Kubernetes;
  4. kubectl exec -ti <имя pod'а> bash us permet executar un intèrpret d'ordres interactiu en un dels contenidors del pod

Quina triar?

El fet és que no hi ha cap comandament universal. S'ha d'utilitzar una combinació d'ells.

Problemes comuns de les beines

Hi ha dos tipus principals d'errors de pod: errors d'inici i errors d'execució.

Errors de llançament:

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

Errors en temps d'execució:

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

Alguns errors són més comuns que d'altres. Aquests són alguns dels errors més comuns i com solucionar-los.

ImagePullBackOff

Aquest error es produeix quan Kubernetes no pot obtenir una imatge per a un dels contenidors del pod. Aquests són els tres motius més habituals per a això:

  1. El nom de la imatge és incorrecte; per exemple, us heu equivocat o la imatge no existeix;
  2. S'ha especificat una etiqueta no vàlida per a la imatge;
  3. La imatge s'emmagatzema en un registre privat i Kubernetes no té permís per accedir-hi.

Els dos primers motius són fàcils de solucionar: només cal que arregleu el nom i l'etiqueta de la imatge. En el cas d'aquest últim, cal introduir les credencials del registre privat a Secret i afegir-hi enllaços en pods. A la documentació de Kubernetes hi ha un exemple com es pot fer.

Desactiva el bucle de bloqueig

Kubenetes llança un error CrashLoopBackOffsi el contenidor no pot arrencar. Això sol passar quan:

  1. L'aplicació té un error que impedeix que s'executi;
  2. envàs configurat incorrectament;
  3. La prova de Liveness ha fallat massa vegades.

Cal intentar arribar als registres des del contenidor per esbrinar el motiu del seu fracàs. Si és difícil accedir als registres perquè el contenidor es reinicia massa ràpidament, podeu utilitzar l'ordre següent:

kubectl logs <pod-name> --previous

Imprimeix missatges d'error de la reencarnació anterior del contenidor.

RunContainerError

Aquest error es produeix quan el contenidor no es pot iniciar. Correspon al moment anterior a l'inici de la sol·licitud. Normalment es deu a una configuració incorrecta, com ara:

  • intentant muntar un volum inexistent com ara ConfigMap o Secrets;
  • intentant muntar un volum de només lectura com a lectura-escriptura.

L'ordre és molt adequat per analitzar aquests errors. kubectl describe pod <pod-name>.

Beines a l'estat Pendent

Després de la creació, la beina roman a l'estat Pending.

Per què passa això?

Aquestes són les possibles causes (suposo que el programador funciona bé):

  1. El clúster no té prou recursos, com ara la potència de processament i la memòria, per executar el pod.
  2. S'estableix un objecte a l'espai de noms adequat ResourceQuota i crear un pod farà que l'espai de noms surti de la quota.
  3. Pod lligat a Pendent PersistentVolumeClaim.

En aquest cas, es recomana utilitzar l'ordre kubectl describe i la secció de comprovació Events:

kubectl describe pod <pod name>

En cas d'errors relacionats amb ResourceQuotas, es recomana veure els registres del clúster mitjançant l'ordre

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

Les beines no estan a punt

Si pod apareix com a Running, però no és a l'estat Ready, significa comprovar la seva disposició (sonda de preparació) falla.

Quan això passa, el pod no es connecta al servei i no s'hi envia trànsit. El fracàs de la prova de preparació és causat per problemes en l'aplicació. En aquest cas, per trobar l'error, cal analitzar la secció Events a la sortida d'ordres kubectl describe.

2. Diagnòstic del servei

Si les beines apareixen com a Running и Ready, però encara no hi ha resposta de l'aplicació, hauríeu de comprovar la configuració del servei.

Els serveis es dediquen a dirigir el trànsit als pods en funció de les seves etiquetes. Per tant, el primer que cal fer és comprovar quants pods funcionen amb el servei. Per fer-ho, podeu comprovar els punts finals del servei:

kubectl describe service <service-name> | grep Endpoints

El punt final és un parell de valors del formulari <IP-адрес:порт>, i almenys un d'aquests parells ha d'estar present a la sortida (és a dir, almenys un pod està treballant amb el servei).

Si secció Endpoins buit, hi ha dues opcions:

  1. no hi ha pods amb l'etiqueta correcta (suggeriment: comproveu si l'espai de noms és correcte);
  2. hi ha un error a les etiquetes del servei del selector.

Si veieu una llista de punts finals però encara no podeu accedir a l'aplicació, el culpable probable és un error targetPort a la descripció del servei.

Com comprovar si el servei funciona?

Independentment del tipus de servei, podeu utilitzar l'ordre kubectl port-forward per connectar-hi:

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

Aquí:

  • <service-name> - nom del servei;
  • 3000 és el port que obriu a l'ordinador;
  • 80 - port al costat de servei.

3. Diagnòstic d'entrada

Si has llegit fins aquí, aleshores:

  • les beines s'enumeren com a Running и Ready;
  • el servei distribueix amb èxit el trànsit entre pods.

Tanmateix, encara no podeu "accedir" a l'aplicació.

Això vol dir que el controlador Ingress probablement està mal configurat. Com que el controlador Ingress és un component de tercers del clúster, hi ha diferents mètodes de depuració segons el seu tipus.

Però abans de recórrer a l'ajuda d'eines especials per configurar Ingress'a, podeu fer una cosa molt senzilla. Usos d'entrada serviceName и servicePort per connectar-se al servei. Cal comprovar si estan configurats correctament. Podeu fer-ho amb l'ordre:

kubectl describe ingress <ingress-name>

Si columna Backend està buit, hi ha una alta probabilitat d'error de configuració. Si els backend estan al seu lloc, però l'aplicació encara no és accessible, el problema pot estar relacionat amb:

  • Entra a la configuració d'accessibilitat des d'Internet pública;
  • Configuració d'accessibilitat del clúster des d'Internet pública.

Podeu identificar problemes amb la infraestructura connectant-vos directament al pod Ingress. Per fer-ho, primer cerqueu el pod del controlador Ingress (pot estar en un espai de noms diferent):

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

Utilitza l'equip describeper configurar el port:

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

Finalment, connecteu-vos al pod:

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

Ara totes les sol·licituds del port 3000 de l'ordinador es redirigiran al port 80 del pod.

Funciona ara?

  • Si és així, el problema és la infraestructura. Cal esbrinar exactament com s'encamina el trànsit al clúster.
  • Si no, el problema és amb el controlador d'entrada.

Si no podeu fer que el controlador Ingress funcioni, haureu de depurar-lo.

Hi ha moltes varietats de controladors d'entrada. Els més populars són Nginx, HAProxy, Traefik, etc. (per obtenir més informació sobre les solucions existents, vegeu la nostra ressenya -aprox. trad.) Consulteu la guia de resolució de problemes a la documentació del controlador adequat. Perquè el Entrada Nginx és el controlador d'entrada més popular, hem inclòs alguns consells sobre com tractar-lo en aquest article.

Depuració d'un controlador d'entrada Nginx

El projecte Ingress-nginx té un oficial connector per a kubectl. equip kubectl ingress-nginx es pot utilitzar per a:

  • anàlisi de registres, backends, certificats, etc.;
  • connexió amb Ingress'u;
  • examinant la configuració actual.

Les tres ordres següents us ajudaran amb això:

  • kubectl ingress-nginx lint - xecs nginx.conf;
  • kubectl ingress-nginx backend - explora el backend (similar a kubectl describe ingress <ingress-name>);
  • kubectl ingress-nginx logs - Comprova els registres.

Tingueu en compte que, en alguns casos, pot ser necessari especificar l'espai de noms correcte per al controlador Ingress mitjançant el senyalador --namespace <name>.

Resum

La resolució de problemes de Kubernetes pot ser complicat si no sabeu per on començar. El problema sempre s'ha d'abordar des de baix cap amunt: començar amb pods, i després passar al servei i Ingress. Els mètodes de depuració descrits a l'article es poden aplicar a altres objectes, com ara:

  • Jobs inactius i CronJobs;
  • StatefulSets i DaemonSets.

Expresso el meu agraïment Gergely Risko, Daniel Weibel и Charles Christyraj per a comentaris i addicions valuoses.

PS del traductor

Llegeix també al nostre blog:

Font: www.habr.com

Afegeix comentari