Визуално ръководство за отстраняване на неизправности в Kubernetes

Забележка. превод: Тази статия е част от свободно достъпните материали по проекта научите8sкойто учи компании и отделни администратори как да работят с Kubernetes. В него Даниеле Поленчич, ръководител на проекта, споделя визуално ръководство за това какви стъпки да предприемете, ако има общи проблеми с приложения, работещи на клъстер K8s.

Визуално ръководство за отстраняване на неизправности в Kubernetes

TL;DR: Ето диаграма, която да ви помогне да отстраните грешки във вашето внедряване на Kubernetes:

Визуално ръководство за отстраняване на неизправности в Kubernetes

Блок-схема за намиране и коригиране на грешки в клъстер. Оригиналът (на английски) е достъпен в PDF и като снимка.

Когато внедрявате приложение в Kubernetes, обикновено има три компонента, които трябва да бъдат дефинирани:

  • внедряване - това е рецепта за създаване на копия на приложението, наречени pods;
  • обслужване - вътрешен балансьор на натоварването, който разпределя трафика между подовете;
  • Влизане - описание на това как трафикът ще стигне от външния свят до Услугата.

Ето кратко графично резюме:

1) В Kubernetes приложенията получават трафик от външния свят чрез два слоя балансьори на натоварването: вътрешен и външен.

Визуално ръководство за отстраняване на неизправности в Kubernetes

2) Вътрешният балансьор се нарича Service, външният е Ingress.

Визуално ръководство за отстраняване на неизправности в Kubernetes

3) Внедряването създава подове и ги наблюдава (не се създават ръчно).

Визуално ръководство за отстраняване на неизправности в Kubernetes

Да предположим, че искате да внедрите просто приложение a la Здравей, свят. YAML конфигурацията за него ще изглежда така:

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

Определението е доста дълго и е лесно да се объркате как компонентите са свързани помежду си.

Например:

  • Кога трябва да използвам порт 80 и кога трябва да използвам 8080?
  • Трябва ли да се създаде нов порт за всяка услуга, за да не влизат в конфликт?
  • Имената на етикетите имат ли значение? Навсякъде ли трябва да са еднакви?

Преди да се съсредоточим върху отстраняването на грешки, нека обобщим как трите компонента са свързани един с друг. Да започнем с внедряване и обслужване.

Връзка между внедряване и услуга

Ще се изненадате, но внедряването и услугите не са свързани по никакъв начин. Вместо това Услугата директно сочи към Pods, заобикаляйки Разгръщането.

По този начин се интересуваме от това как Pods и Services са свързани помежду си. Три неща, които трябва да запомните:

  1. Селектор (selector) за услуга трябва да съответства на поне един етикет на Pod.
  2. targetPort трябва да съвпада containerPort контейнер вътре в Pod.
  3. port Service'a може да бъде всичко. Различни услуги могат да използват един и същ порт, защото имат различни IP адреси.

Следната диаграма представя всичко по-горе в графична форма:

1) Представете си, че услугата изпраща трафик към определен pod:

Визуално ръководство за отстраняване на неизправности в Kubernetes

2) Когато създавате pod, трябва да зададете containerPort за всеки контейнер в капсули:

Визуално ръководство за отстраняване на неизправности в Kubernetes

3) Когато създавате услуга, трябва да посочите port и targetPort. Но през кой от тях минава връзката с контейнера?

Визуално ръководство за отстраняване на неизправности в Kubernetes

4) Чрез targetPort. Трябва да съвпада с containerPort.

Визуално ръководство за отстраняване на неизправности в Kubernetes

5) Да предположим, че в контейнера е отворен порт 3000. Тогава стойността targetPort трябва да е същото.

Визуално ръководство за отстраняване на неизправности в Kubernetes

В YAML файла, етикетите и ports / targetPort трябва да съвпада:

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

Какво ще кажете за етикета track: canary в горната част на раздела Разгръщане? Трябва ли да съвпада?

Този етикет е специфичен за внедряването и не се използва от услугата за маршрутизиране на трафика. С други думи, той може да бъде премахнат или да му бъде присвоена различна стойност.

Ами селектора matchLabels?

Винаги трябва да съответства на етикетите на Pod, тъй като се използва от Deployment за проследяване на подс.

Да приемем, че сте направили правилните редакции. Как да ги проверим?

Можете да проверите етикета на подовете със следната команда:

kubectl get pods --show-labels

Или, ако капсулите са собственост на множество приложения:

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

където any-name=my-app е етикет any-name: my-app.

Остават ли трудности?

Можете да се свържете с под! За целта трябва да използвате командата port-forward в kubectl. Тя ви позволява да се свържете с услугата и да проверите връзката.

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

Тук:

  • service/<service name> — име на услугата; в нашия случай е така my-service;
  • 3000 е портът, който искате да отворите на компютъра;
  • 80 - порт, посочен в полето port обслужване.

Ако връзката е установена успешно, тогава настройките са правилни.

Ако връзката не може да бъде установена, значи има проблем с етикетите или портовете не съвпадат.

Връзка между услуга и вход

Следващата стъпка в предоставянето на достъп до приложението е свързана с настройка на Ingress. Ingress трябва да знае как да намери услугата, след това да намери подовете и да изпрати трафик към тях. Ingress намира желаната услуга по име и отворен порт.

В описанието на Ingress и Service два параметъра трябва да съвпадат:

  1. servicePort в Ingress трябва да съответства на параметъра port в експлоатация;
  2. serviceName в Ingress трябва да съответства на полето name в Сервиз.

Следващата диаграма обобщава портовите връзки:

1) Както вече знаете, услугата слуша някои port:

Визуално ръководство за отстраняване на неизправности в Kubernetes

2) Ingress има извикан параметър servicePort:

Визуално ръководство за отстраняване на неизправности в Kubernetes

3) Този параметър (servicePort) трябва винаги да съвпадат port в дефиницията на услугата:

Визуално ръководство за отстраняване на неизправности в Kubernetes

4) Ако порт 80 е указан в услугата, тогава е необходимо това servicePort също беше равно на 80:

Визуално ръководство за отстраняване на неизправности в Kubernetes

На практика трябва да обърнете внимание на следните редове:

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

Как да проверите дали Ingress работи?

Можете да използвате метода с kubectl port-forward, но вместо услуга, трябва да се свържете с контролера Ingress.

Първо трябва да разберете името на под с 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

Намерете Ingress pod (може да е в друго пространство от имена) и изпълнете командата describeза да разберете номерата на портовете:

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

Накрая се свържете с под:

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

Сега всеки път, когато изпратите заявка до порт 3000 на машината, тя ще бъде пренасочена към порт 80 на Ingress pod. Отивам до http://localhost:3000, трябва да видите страницата, генерирана от приложението.

Обобщение по пристанища

Нека си припомним отново кои портове и етикети трябва да съвпадат:

  1. Селекторът в дефиницията на услугата трябва да съответства на етикета на групата;
  2. targetPort в дефиницията на услугата трябва да съвпадат containerPort контейнер вътре в капсула;
  3. port в дефиницията на услугата може да бъде всичко. Различни услуги могат да използват един и същ порт, защото имат различни IP адреси;
  4. servicePort Ingress трябва да съвпада port в дефиницията на услугата;
  5. Името на услугата трябва да съответства на полето serviceName в Ingress.

Уви, не е достатъчно да знаете как правилно да структурирате YAML конфигурация.

Какво се случва, когато нещо се обърка?

Подът може да не стартира или да се срива.

3 стъпки за отстраняване на проблеми с приложения в Kubernetes

Преди да започнете да отстранявате грешки във вашето внедряване, трябва да разберете добре как работи Kubernetes.

Тъй като във всяко изтеглено приложение в K8s има три компонента, дебъгвайте ги в определен ред, като започнете отдолу.

  1. Първо трябва да се уверите, че капсулите работят, след това...
  2. Проверете дали услугата доставя трафик към модулите и след това...
  3. Проверете дали Ingress е конфигуриран правилно.

Визуално представяне:

1) Започнете да търсите проблемите от дъното. Първо проверете дали капсулите имат състояния Ready и Running:

Визуално ръководство за отстраняване на неизправности в Kubernetes

2) Ако шушулките са готови (Ready), трябва да разберете дали услугата разпределя трафик между подове:

Визуално ръководство за отстраняване на неизправности в Kubernetes

3) И накрая, трябва да анализирате връзката между услугата и Ingress:

Визуално ръководство за отстраняване на неизправности в Kubernetes

1. Под диагностика

В повечето случаи проблемът е свързан с под. Уверете се, че капсулите са посочени като Ready и Running. Можете да проверите това с командата:

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

В изхода на командата по-горе последният под е посочен като Running и Ready, но това не е така за другите две.

Как да разберем какво се е объркало?

Има четири полезни команди за диагностициране на капсули:

  1. kubectl logs <имя pod'а> ви позволява да извличате трупи от контейнери в капсула;
  2. kubectl describe pod <имя pod'а> ви позволява да видите списъка със събития, свързани с под;
  3. kubectl get pod <имя pod'а> ви позволява да получите YAML конфигурацията на под, съхранен в Kubernetes;
  4. kubectl exec -ti <имя pod'а> bash ви позволява да стартирате интерактивна командна обвивка в един от контейнерите на pod

Кое да избера?

Факт е, че няма универсална команда. Трябва да се използва комбинация от тях.

Често срещани проблеми с под

Има два основни типа грешки на pod: грешки при стартиране и грешки по време на изпълнение.

Грешки при стартиране:

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

Грешки по време на изпълнение:

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

Някои грешки са по-чести от други. Ето някои от най-често срещаните грешки и как да ги коригирате.

ImagePullBackOff

Тази грешка възниква, когато Kubernetes не може да получи изображение за един от контейнерите на pod. Ето трите най-чести причини за това:

  1. Името на изображението е неправилно - например сте направили грешка в него или изображението не съществува;
  2. Посочен е невалиден етикет за изображението;
  3. Изображението се съхранява в частен регистър и Kubernetes няма разрешение за достъп до него.

Първите две причини са лесни за отстраняване - просто коригирайте името и тага на изображението. В случая на последното е необходимо да въведете идентификационни данни за частния регистър в Secret и да добавите връзки към него в подс. В документацията на Kubernetes има пример как може да се направи.

Crash Loop Back Off

Kubenetes извежда грешка CrashLoopBackOffако контейнерът не може да стартира. Това обикновено се случва, когато:

  1. Приложението има грешка, която му пречи да работи;
  2. контейнер конфигуриран неправилно;
  3. Тестът за живост се провали твърде много пъти.

Необходимо е да се опитате да стигнете до трупите от контейнера, за да разберете причината за неговия неуспех. Ако достъпът до регистрационните файлове е труден, защото контейнерът се рестартира твърде бързо, можете да използвате следната команда:

kubectl logs <pod-name> --previous

Той отпечатва съобщения за грешка от предишното прераждане на контейнера.

RunContainerError

Тази грешка възниква, когато контейнерът не може да стартира. Съответства на момента преди началото на приложението. Обикновено се причинява от неправилна конфигурация, като например:

  • опит за монтиране на несъществуващ том като ConfigMap или Secrets;
  • опитвайки се да монтирате том само за четене като четене-запис.

Командата е много подходяща за анализиране на такива грешки. kubectl describe pod <pod-name>.

Подовете в състояние на изчакване

След създаването групата остава в състоянието Pending.

Защо се случва това?

Ето възможните причини (предполагам, че планировчикът работи добре):

  1. Клъстерът няма достатъчно ресурси, като мощност на обработка и памет, за да стартира групата.
  2. Обектът е зададен в съответното пространство от имена ResourceQuota и създаването на под ще доведе до излизане на пространството от имена извън квотата.
  3. Под, свързан с чакащ PersistentVolumeClaim.

В този случай се препоръчва да използвате командата kubectl describe и проверете секцията Events:

kubectl describe pod <pod name>

В случай на грешки, свързани с ResourceQuotas, се препоръчва да видите регистрационните файлове на клъстера с помощта на командата

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

Подовете не са готови

Ако под е посочен като Running, но не е в държавата Ready, означава проверка на готовността му (сонда за готовност) не успява.

Когато това се случи, подът не се свързва с услугата и към него не се изпраща трафик. Неуспехът на теста за готовност е причинен от проблеми в приложението. В този случай, за да намерите грешката, трябва да анализирате секцията Events в командния изход kubectl describe.

2. Сервизна диагностика

Ако шушулките са посочени като Running и Ready, но все още няма отговор от приложението, трябва да проверите настройките на услугата.

Услугите се занимават с маршрутизиране на трафика към подовете в зависимост от техните етикети. Следователно, първото нещо, което трябва да направите, е да проверите колко подове работят с услугата. За да направите това, можете да проверите крайните точки в услугата:

kubectl describe service <service-name> | grep Endpoints

Крайната точка е двойка стойности на формата <IP-адрес:порт>и поне една такава двойка трябва да присъства в изхода (т.е. поне един pod работи с услугата).

Ако раздел Endpoins празно, има две опции:

  1. няма подове с правилния етикет (подсказка: проверете дали пространството от имена е правилно);
  2. има грешка в служебните етикети в селектора.

Ако видите списък с крайни точки, но все още нямате достъп до приложението, тогава вероятният виновник е грешка в targetPort в описанието на услугата.

Как да проверите дали услугата работи?

Независимо от вида на услугата, можете да използвате командата kubectl port-forward за да се свържете с него:

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

Тук:

  • <service-name> — име на услугата;
  • 3000 е портът, който отваряте на компютъра;
  • 80 - порт от сервизната страна.

3. Ingress Diagnostics

Ако сте прочели дотук, тогава:

  • шушулките са посочени като Running и Ready;
  • услугата успешно разпределя трафика между подс.

Въпреки това, все още не можете да "докоснете" до приложението.

Това означава, че контролерът Ingress най-вероятно е неправилно конфигуриран. Тъй като контролерът Ingress е компонент на трета страна в клъстера, има различни методи за отстраняване на грешки в зависимост от неговия тип.

Но преди да прибегнете до помощта на специални инструменти за конфигуриране на Ingress'a, можете да направите нещо много просто. Ingress използва serviceName и servicePort за да се свържете с услугата. Трябва да проверите дали са конфигурирани правилно. Можете да направите това с командата:

kubectl describe ingress <ingress-name>

Ако колона Backend е празен, има голяма вероятност за грешка в конфигурацията. Ако задните части са налице, но приложението все още не е достъпно, тогава проблемът може да е свързан с:

  • Ingress настройки за достъпност от публичния интернет;
  • настройките за достъпност на клъстера от обществения интернет.

Можете да идентифицирате проблеми с инфраструктурата, като се свържете директно към Ingress pod. За да направите това, първо намерете модула на контролера 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

Използвайте екипа describeза да настроите порта:

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

Накрая се свържете с под:

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

Сега всички заявки на порт 3000 на компютъра ще бъдат пренасочени към порт 80 на модула.

Работи ли сега?

  • Ако е така, значи проблемът е в инфраструктурата. Необходимо е да разберете как точно се насочва трафикът към клъстера.
  • Ако не, тогава проблемът е в контролера Ingress.

Ако не можете да накарате контролера Ingress да работи, ще трябва да го отстраните.

Има много разновидности на контролери Ingress. Най-популярните са Nginx, HAProxy, Traefik и др. (за повече информация относно съществуващите решения вижте нашия преглед - прибл. превод) Обърнете се към ръководството за отстраняване на неизправности в документацията за съответния контролер. Тъй като Ingress Nginx е най-популярният контролер на Ingress, в тази статия сме включили няколко съвета как да се справите с него.

Отстраняване на грешки на Nginx Ingress Controller

Проектът Ingress-nginx има официален плъгин за kubectl. екип kubectl ingress-nginx може да се използва за:

  • анализ на логове, бекендове, сертификати и др.;
  • връзки към Ingress'u;
  • проверка на текущата конфигурация.

Следните три команди ще ви помогнат с това:

  • kubectl ingress-nginx lint - чекове nginx.conf;
  • kubectl ingress-nginx backend - изследва бекенда (подобно на kubectl describe ingress <ingress-name>);
  • kubectl ingress-nginx logs - проверява дневниците.

Моля, имайте предвид, че в някои случаи може да се наложи да посочите правилното пространство от имена за контролера Ingress, като използвате флага --namespace <name>.

Обобщение

Отстраняването на неизправности в Kubernetes може да бъде трудно, ако не знаете откъде да започнете. Към проблема винаги трябва да се подхожда отдолу нагоре: започнете с pods и след това преминете към услугата и Ingress. Методите за отстраняване на грешки, описани в статията, могат да бъдат приложени към други обекти, като например:

  • неактивни задачи и CronJobs;
  • StatefulSets и DaemonSets.

Изказвам своята благодарност Гергели Риско, Даниел Вайбел и Чарлз Кристирай за ценни коментари и допълнения.

PS от преводача

Прочетете също в нашия блог:

Източник: www.habr.com

Добавяне на нов коментар