Визуално ръководство за отстраняване на неизправности в Kubernetes
Забележка. превод: Тази статия е част от свободно достъпните материали по проекта научите8sкойто учи компании и отделни администратори как да работят с Kubernetes. В него Даниеле Поленчич, ръководител на проекта, споделя визуално ръководство за това какви стъпки да предприемете, ако има общи проблеми с приложения, работещи на клъстер K8s.
TL;DR: Ето диаграма, която да ви помогне да отстраните грешки във вашето внедряване на Kubernetes:
Блок-схема за намиране и коригиране на грешки в клъстер. Оригиналът (на английски) е достъпен в PDF и като снимка.
Когато внедрявате приложение в Kubernetes, обикновено има три компонента, които трябва да бъдат дефинирани:
внедряване - това е рецепта за създаване на копия на приложението, наречени pods;
обслужване - вътрешен балансьор на натоварването, който разпределя трафика между подовете;
Влизане - описание на това как трафикът ще стигне от външния свят до Услугата.
Ето кратко графично резюме:
1) В Kubernetes приложенията получават трафик от външния свят чрез два слоя балансьори на натоварването: вътрешен и външен.
2) Вътрешният балансьор се нарича Service, външният е Ingress.
3) Внедряването създава подове и ги наблюдава (не се създават ръчно).
Да предположим, че искате да внедрите просто приложение a la Здравей, свят. YAML конфигурацията за него ще изглежда така:
Определението е доста дълго и е лесно да се объркате как компонентите са свързани помежду си.
Например:
Кога трябва да използвам порт 80 и кога трябва да използвам 8080?
Трябва ли да се създаде нов порт за всяка услуга, за да не влизат в конфликт?
Имената на етикетите имат ли значение? Навсякъде ли трябва да са еднакви?
Преди да се съсредоточим върху отстраняването на грешки, нека обобщим как трите компонента са свързани един с друг. Да започнем с внедряване и обслужване.
Връзка между внедряване и услуга
Ще се изненадате, но внедряването и услугите не са свързани по никакъв начин. Вместо това Услугата директно сочи към Pods, заобикаляйки Разгръщането.
По този начин се интересуваме от това как Pods и Services са свързани помежду си. Три неща, които трябва да запомните:
Селектор (selector) за услуга трябва да съответства на поне един етикет на Pod.
targetPort трябва да съвпада containerPort контейнер вътре в Pod.
port Service'a може да бъде всичко. Различни услуги могат да използват един и същ порт, защото имат различни IP адреси.
Следната диаграма представя всичко по-горе в графична форма:
1) Представете си, че услугата изпраща трафик към определен pod:
2) Когато създавате pod, трябва да зададете containerPort за всеки контейнер в капсули:
3) Когато създавате услуга, трябва да посочите port и targetPort. Но през кой от тях минава връзката с контейнера?
4) Чрез targetPort. Трябва да съвпада с containerPort.
5) Да предположим, че в контейнера е отворен порт 3000. Тогава стойността targetPort трябва да е същото.
В YAML файла, етикетите и ports / targetPort трябва да съвпада:
Какво ще кажете за етикета 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. Тя ви позволява да се свържете с услугата и да проверите връзката.
service/<service name> — име на услугата; в нашия случай е така my-service;
3000 е портът, който искате да отворите на компютъра;
80 - порт, посочен в полето port обслужване.
Ако връзката е установена успешно, тогава настройките са правилни.
Ако връзката не може да бъде установена, значи има проблем с етикетите или портовете не съвпадат.
Връзка между услуга и вход
Следващата стъпка в предоставянето на достъп до приложението е свързана с настройка на Ingress. Ingress трябва да знае как да намери услугата, след това да намери подовете и да изпрати трафик към тях. Ingress намира желаната услуга по име и отворен порт.
В описанието на Ingress и Service два параметъра трябва да съвпадат:
servicePort в Ingress трябва да съответства на параметъра port в експлоатация;
serviceName в Ingress трябва да съответства на полето name в Сервиз.
Следващата диаграма обобщава портовите връзки:
1) Както вече знаете, услугата слуша някои port:
2) Ingress има извикан параметър servicePort:
3) Този параметър (servicePort) трябва винаги да съвпадат port в дефиницията на услугата:
4) Ако порт 80 е указан в услугата, тогава е необходимо това servicePort също беше равно на 80:
На практика трябва да обърнете внимание на следните редове:
Сега всеки път, когато изпратите заявка до порт 3000 на машината, тя ще бъде пренасочена към порт 80 на Ingress pod. Отивам до http://localhost:3000, трябва да видите страницата, генерирана от приложението.
Обобщение по пристанища
Нека си припомним отново кои портове и етикети трябва да съвпадат:
Селекторът в дефиницията на услугата трябва да съответства на етикета на групата;
targetPort в дефиницията на услугата трябва да съвпадат containerPort контейнер вътре в капсула;
port в дефиницията на услугата може да бъде всичко. Различни услуги могат да използват един и същ порт, защото имат различни IP адреси;
servicePort Ingress трябва да съвпада port в дефиницията на услугата;
Името на услугата трябва да съответства на полето serviceName в Ingress.
Уви, не е достатъчно да знаете как правилно да структурирате YAML конфигурация.
Какво се случва, когато нещо се обърка?
Подът може да не стартира или да се срива.
3 стъпки за отстраняване на проблеми с приложения в Kubernetes
Преди да започнете да отстранявате грешки във вашето внедряване, трябва да разберете добре как работи Kubernetes.
Тъй като във всяко изтеглено приложение в K8s има три компонента, дебъгвайте ги в определен ред, като започнете отдолу.
Първо трябва да се уверите, че капсулите работят, след това...
Проверете дали услугата доставя трафик към модулите и след това...
Проверете дали Ingress е конфигуриран правилно.
Визуално представяне:
1) Започнете да търсите проблемите от дъното. Първо проверете дали капсулите имат състояния Ready и Running:
2) Ако шушулките са готови (Ready), трябва да разберете дали услугата разпределя трафик между подове:
3) И накрая, трябва да анализирате връзката между услугата и Ingress:
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, но това не е така за другите две.
Как да разберем какво се е объркало?
Има четири полезни команди за диагностициране на капсули:
kubectl logs <имя pod'а> ви позволява да извличате трупи от контейнери в капсула;
kubectl describe pod <имя pod'а> ви позволява да видите списъка със събития, свързани с под;
kubectl get pod <имя pod'а> ви позволява да получите YAML конфигурацията на под, съхранен в Kubernetes;
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. Ето трите най-чести причини за това:
Името на изображението е неправилно - например сте направили грешка в него или изображението не съществува;
Посочен е невалиден етикет за изображението;
Изображението се съхранява в частен регистър и Kubernetes няма разрешение за достъп до него.
Първите две причини са лесни за отстраняване - просто коригирайте името и тага на изображението. В случая на последното е необходимо да въведете идентификационни данни за частния регистър в Secret и да добавите връзки към него в подс. В документацията на Kubernetes има пример как може да се направи.
Crash Loop Back Off
Kubenetes извежда грешка CrashLoopBackOffако контейнерът не може да стартира. Това обикновено се случва, когато:
Приложението има грешка, която му пречи да работи;
Необходимо е да се опитате да стигнете до трупите от контейнера, за да разберете причината за неговия неуспех. Ако достъпът до регистрационните файлове е труден, защото контейнерът се рестартира твърде бързо, можете да използвате следната команда:
kubectl logs <pod-name> --previous
Той отпечатва съобщения за грешка от предишното прераждане на контейнера.
RunContainerError
Тази грешка възниква, когато контейнерът не може да стартира. Съответства на момента преди началото на приложението. Обикновено се причинява от неправилна конфигурация, като например:
опит за монтиране на несъществуващ том като ConfigMap или Secrets;
опитвайки се да монтирате том само за четене като четене-запис.
Командата е много подходяща за анализиране на такива грешки. kubectl describe pod <pod-name>.
Подовете в състояние на изчакване
След създаването групата остава в състоянието Pending.
Защо се случва това?
Ето възможните причини (предполагам, че планировчикът работи добре):
Клъстерът няма достатъчно ресурси, като мощност на обработка и памет, за да стартира групата.
Обектът е зададен в съответното пространство от имена ResourceQuota и създаването на под ще доведе до излизане на пространството от имена извън квотата.
Под, свързан с чакащ 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 празно, има две опции:
няма подове с правилния етикет (подсказка: проверете дали пространството от имена е правилно);
има грешка в служебните етикети в селектора.
Ако видите списък с крайни точки, но все още нямате достъп до приложението, тогава вероятният виновник е грешка в targetPort в описанието на услугата.
Как да проверите дали услугата работи?
Независимо от вида на услугата, можете да използвате командата kubectl port-forward за да се свържете с него:
Въпреки това, все още не можете да "докоснете" до приложението.
Това означава, че контролерът Ingress най-вероятно е неправилно конфигуриран. Тъй като контролерът Ingress е компонент на трета страна в клъстера, има различни методи за отстраняване на грешки в зависимост от неговия тип.
Но преди да прибегнете до помощта на специални инструменти за конфигуриране на Ingress'a, можете да направите нещо много просто. Ingress използва serviceName и servicePort за да се свържете с услугата. Трябва да проверите дали са конфигурирани правилно. Можете да направите това с командата:
kubectl describe ingress <ingress-name>
Ако колона Backend е празен, има голяма вероятност за грешка в конфигурацията. Ако задните части са налице, но приложението все още не е достъпно, тогава проблемът може да е свързан с:
Ingress настройки за достъпност от публичния интернет;
настройките за достъпност на клъстера от обществения интернет.
Можете да идентифицирате проблеми с инфраструктурата, като се свържете директно към Ingress pod. За да направите това, първо намерете модула на контролера Ingress (може да е в различно пространство от имена):
Сега всички заявки на порт 3000 на компютъра ще бъдат пренасочени към порт 80 на модула.
Работи ли сега?
Ако е така, значи проблемът е в инфраструктурата. Необходимо е да разберете как точно се насочва трафикът към клъстера.
Ако не, тогава проблемът е в контролера Ingress.
Ако не можете да накарате контролера Ingress да работи, ще трябва да го отстраните.
Има много разновидности на контролери Ingress. Най-популярните са Nginx, HAProxy, Traefik и др. (за повече информация относно съществуващите решения вижте нашия преглед - прибл. превод) Обърнете се към ръководството за отстраняване на неизправности в документацията за съответния контролер. Тъй като Ingress Nginx е най-популярният контролер на Ingress, в тази статия сме включили няколко съвета как да се справите с него.
Отстраняване на грешки на Nginx Ingress Controller
Проектът Ingress-nginx има официален плъгин за kubectl. екип kubectl ingress-nginx може да се използва за:
Моля, имайте предвид, че в някои случаи може да се наложи да посочите правилното пространство от имена за контролера Ingress, като използвате флага --namespace <name>.
Обобщение
Отстраняването на неизправности в Kubernetes може да бъде трудно, ако не знаете откъде да започнете. Към проблема винаги трябва да се подхожда отдолу нагоре: започнете с pods и след това преминете към услугата и Ingress. Методите за отстраняване на грешки, описани в статията, могат да бъдат приложени към други обекти, като например: