Візуальнае кіраўніцтва па дыягностыцы няспраўнасцяў у Kubernetes
Заўв. перав.: Гэты артыкул уваходзіць у склад апублікаваных у свабодным доступе матэрыялаў праекта. learnk8s, які навучае працы з Kubernetes кампаніі і індывідуальных адміністратараў. У ёй Daniele Polencic, кіраўнік праекта, дзеліцца нагляднай інструкцыяй аб тым, якія крокі варта рабіць у выпадку ўзнікнення праблем агульнага характару ў прыкладанняў, запушчаных у кластары K8s.
TL;DR: вось схема, якая дапаможа вам адладзіць deployment у Kubernetes:
Блок-схема для пошуку і выпраўленні памылак у кластары. У арыгінале (на англійскай) яна даступная ў PDF и як малюнак.
Пры разгортванні прыкладання ў Kubernetes звычайна неабходна вызначыць тры кампаненты:
разгортванне - Гэта нейкі рэцэпт па стварэнні копій прыкладання, званых pod'амі;
абслугоўванне - унутраны балансавальнік нагрузкі, размяркоўвалы трафік па pod'ах;
Уваход - апісанне таго, як трафік будзе трапляць са знешняга свету да Service'у.
Вось кароткае графічнае рэзюмэ:
1) У Kubernetes прыкладанні атрымліваюць трафік з знешняга свету праз два пласта балансавальнікаў нагрузкі: унутраны і знешні.
2) Унутраны балансавальнік называецца Service, знешні - Ingress.
3) Deployment стварае pod'ы і сочыць за імі (яны не ствараюцца ўручную).
Выкажам здагадку, вы хочаце разгарнуць просценькі дадатак а-ля Прывітанне свет. YAML-канфігурацыя для яго будзе выглядаць наступным чынам:
А як наконт лэйбла track: canary у верхняй частцы падзелу Deployment? Ці павінен ён супадаць?
Гэты лэйбл адносіцца да разгортвання, і не выкарыстоўваецца сэрвісам для маршрутызацыі трафіку. Іншымі словамі, яго можна выдаліць ці прысвоіць іншае значэнне.
А што наконт селектара matchLabels?
Ён заўсёды павінен супадаць з лэйбламі Pod'а, паколькі выкарыстоўваецца Deployment'ам для адсочвання pod'аў.
Дапусцім, што вы ўнеслі правільныя праўкі. Як іх праверыць?
Праверыць лэйбл pod'аў можна наступнай камандай:
kubectl get pods --show-labels
Ці, калі pod'ы належаць некалькім прыкладанням:
kubectl get pods --selector any-name=my-app --show-labels
Дзе any-name=my-app - гэта лэйбл any-name: my-app.
Засталіся цяжкасці?
Можна далучыцца да pod'у! Для гэтага трэба выкарыстоўваць каманду port-forward у kubectl. Яна дазваляе далучыцца да сэрвісу і праверыць злучэнне.
service/<service name> - імя сэрвісу; у нашым выпадку гэта my-service;
3000 - порт, які патрабуецца адкрыць на кампутары;
80 - порт, прапісаны ў поле port сэрвісу.
Калі ўдалося ўсталяваць злучэнне, значыць налады дакладныя.
Калі злучэнне ўсталяваць не атрымалася, значыць праблема з лэйбламі ці порты не супадаюць.
Сувязь Service'а і Ingress'а
Наступны крок у забеспячэнні доступу да дадатку звязаны з наладай Ingress'а. Ingress павінен ведаць, як адшукаць сервіс, затым знайсці pod'ы і накіраваць да іх трафік. Ingress знаходзіць патрэбны сэрвіс па імені і адкрытым порце.
У апісанні Ingress і Service павінны супадаць два параметры:
servicePort у Ingress павінен супадаць з параметрам port у Service;
serviceName у Ingress павінна супадаць з полем name у Service.
Наступная схема падводзіць вынік па падлучэнні портаў:
1) Як вы ўжо ведаеце, Service слухае нейкі port:
2) У Ingress'а ёсць параметр, званы servicePort:
3) Гэты параметр (servicePort) заўсёды павінен супадаць з port у вызначэнні Service:
4) Калі ў Service зададзены порт 80, то неабходна, каб servicePort таксама быў роўны 80:
Цяпер кожны раз, калі вы будзеце пасылаць запыт на порт 3000 на кампутары, ён будзе перанакіроўвацца на порт 80 pod'а з кантролерам Ingress. Перайшоўшы на http://localhost:3000, Вы павінны будзеце ўбачыць старонку, створаную дадаткам.
Рэзюмэ па партах
Давайце яшчэ раз успомнім аб тым, якія парты і лэйблы павінны супадаць:
Селектар у вызначэнні Service павінен супадаць з лэйблам pod'а;
targetPort у вызначэнні Service павінен супадаць з containerPort кантэйнера ўнутры pod'а;
port у вызначэнні Service можа быць любым. Розныя сэрвісы могуць выкарыстоўваць адзін і той жа порт, паколькі ў іх розныя IP-адрасы;
servicePort Ingress'а павінен супадаць з port у вызначэнні Service;
Назва сэрвісу павінна супадаць з полем serviceName у Ingress'е.
Нажаль, нядосыць ведаць, як правільна структураваць YAML-канфігурацыю.
Што здараецца, калі нешта ідзе не так?
Магчыма, pod не запускаецца ці ён падае.
3 кроку для дыягностыкі няспраўнасцяў у прыкладаннях у Kubernetes
Перш чым прыступаць да адладкі deployment'а, неабходна мець добрае ўяўленне аб тым, як працуе Kubernetes.
Паколькі ў кожным скачаным у K8s дадатку маюцца тры кампаненты, праводзіць іх адладку варта ў вызначаным парадку, пачынальна з самага нізу.
Спачатку трэба пераканацца, што pod'ы працуюць, затым…
Праверыць, ці пастаўляе сэрвіс трафік pod'ам, а потым…
Праверыць, ці правільна наладжаны Ingress.
Візуальнае прадстаўленне:
1) Пачынаць пошук праблем варта з самага нізу. Перш праверце, што pod'ы маюць статуты Ready и Running:
2) Калі pod'ы гатовыя (Ready), варта высветліць, ці размяркоўвае сэрвіс трафік паміж pod'амі:
3) Нарэшце, трэба прааналізаваць сувязь сэрвісу і Ingress'а:
1. Дыягностыка pod'ов
У большасці выпадкаў праблема злучана з pod'ом. Пераканайцеся, што pod'ы значацца як 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
У выснове каманды, прыведзенай вышэй, апошні pod значыцца як Running и Ready, Аднак для двух іншых гэта не так.
Як зразумець, што пайшло не так?
Ёсць чатыры карысныя каманды для дыягностыкі pod'аў:
kubectl logs <имя pod'а> дазваляе атрымаць логі з кантэйнераў у pod'е;
kubectl describe pod <имя pod'а> дазваляе прагледзець спіс падзей, звязаных з pod'ом;
kubectl get pod <имя pod'а> дазваляе атрымаць YAML-канфігурацыю pod'а, якая захоўваецца ў Kubernetes;
kubectl exec -ti <имя pod'а> bash дазваляе запусціць інтэрактыўную камандную абалонку ў адным з кантэйнераў pod'а
Якую з іх абраць?
Справа ў тым, што няма ўніверсальнай каманды. Варта выкарыстоўваць іх камбінацыю.
Тыповыя праблемы pod'аў
Існуе два асноўных тыпу памылак pod'ов: памылкі падчас запуску (startup) і памылкі падчас працы (runtime).
Памылкі запуску:
ImagePullBackoff
ImageInspectError
ErrImagePull
ErrImageNeverPull
RegistryUnavailable
InvalidImageName
Runtime-памылкі:
CrashLoopBackOff
RunContainerError
KillContainerError
VerifyNonRootError
RunInitContainerError
CreatePodSandboxError
ConfigPodSandboxError
KillPodSandboxError
SetupNetworkError
TeardownNetworkError
Некаторыя памылкі сустракаюцца часцей за іншыя. Вось некалькі найболей распаўсюджаных памылак і спосабы іх ухілення.
ImagePullBackOff
Гэтая памылка з'яўляецца, калі Kubernetes не можа атрымаць выяву для аднаго з кантэйнераў pod'а. Вось тры самыя распаўсюджаныя прычыны гэтага:
Няслушна паказана імя выявы - напрыклад, вы зрабілі ў ім памылку, ці выява не існуе;
Пазначаны неіснуючы тэг для выявы;
Выява захоўваецца ў зачыненым рэестры, і ў Kubernetes няма паўнамоцтваў для доступу да яго.
Першыя дзве прычыны ліквідаваць лёгка - дастаткова паправіць імя выявы і тэг. У выпадку апошняй неабходна занесці ўліковыя дадзеныя да зачыненага рэестру ў Secret і дадаць спасылкі на яго ў pod'ы. У дакументацыі Kubernetes ёсць прыклад таго, як гэта можна зрабіць.
CrashLoopBackOff
Kubenetes выводзіць памылку CrashLoopBackOff, калі кантэйнер не можа запусціцца. Звычайна такое здараецца, калі:
У дадатку ёсць памылка, якая не дазваляе яго запусціць;
Тэст Liveness завяршыўся няўдала занадта шмат разоў.
Неабходна паспрабаваць дабрацца да логаў з кантэйнера, каб высветліць прычыну яго збою. Калі атрымаць доступ да логаў цяжка, паколькі кантэйнер занадта хутка перазапускаецца, можна скарыстацца наступнай камандай:
kubectl logs <pod-name> --previous
Яна выводзіць паведамленні аб памылках з папярэдняй рэінкарнацыі кантэйнера.
RunContainerError
Гэтая памылка ўзнікае, калі кантэйнер не ў стане запусціцца. Яна адпавядае моманту да запуску дадатку. Звычайна яе прычынай з'яўляецца няправільная настройка, напрыклад:
спроба прымантаваць неіснуючы тым, такі як ConfigMap ці Secrets;
спроба прымантаваць том тыпу read-only як read-write.
Для аналізу падобных памылак добра падыходзіць каманда. kubectl describe pod <pod-name>.
Pod'ы ў стане Pending
Пасля стварэння pod застаецца ў стане Pending.
Чаму такое адбываецца?
Вось магчымыя прычыны (я зыходжу са здагадкі, што планавальнік працуе нармальна):
У кластары недастаткова рэсурсаў, такіх як вылічальная магутнасць і памяць, для запуску pod'а.
У адпаведнай прасторы імёнаў усталяваны аб'ект ResourceQuota і стварэнне pod'а прывядзе да таго, што прастора імёнаў выйдзе за межы квоты.
Pod прывязаны да Pending PersistentVolumeClaim.
У гэтым выпадку рэкамендуецца карыстацца камандай kubectl describe і праверыць раздзел Events:
kubectl describe pod <pod name>
У выпадку памылак, звязаных з ResourceQuotas, рэкамендуецца прагледзець логі кластара з дапамогай каманды
kubectl get events --sort-by=.metadata.creationTimestamp
Pod'ы не ў стане Ready
Калі pod значыцца як Running, але не знаходзіцца ў стане Ready, значыць праверка яго гатоўнасці (readiness probe) завяршаецца няўдала.
Калі такое адбываецца, pod не падлучаецца да сэрвісу, і трафік на яго не паступае. Збой тэсту readiness выкліканы праблемамі ў дадатку. У гэтым выпадку для пошуку памылкі неабходна прааналізаваць падзел Events у выснове каманды kubectl describe.
2. Дыягностыка сэрвісаў
Калі pod'ы значацца як Running и Ready, але адказу ад прыкладання па-ранейшаму няма, варта праверыць настройкі сэрвісу.
Сэрвісы займаюцца маршрутызацыяй трафіку да pod'аў у залежнасці ад іх лэйблаў. Таму першае, што трэба зрабіць - праверыць, колькі pod'аў працуюць з сэрвісам. Для гэтага можна праверыць endpoint'ы ў сэрвісе:
kubectl describe service <service-name> | grep Endpoints
Endpoint - гэта пара значэнняў выгляду <IP-адрес:порт>, і ў выснове павінна прысутнічаць хаця б адна такая пара (гэта значыць з сэрвісам працуе хаця б адзін pod).
Калі раздзел Endpoins пусты, магчымыя два варыянты:
няма ніводнага pod'а з правільным лэйблам (падказка: праверце, ці правільна абраны namespace);
ёсць памылка ў лэйблах сэрвісу ў селектары.
Калі вы бачыце спіс endpoint'аў, але па-ранейшаму не можаце атрымаць доступ да дадатку, то верагодным вінаватым з'яўляецца памылка ў targetPort у апісанні сэрвісу.
Як праверыць працаздольнасць сэрвісу?
Незалежна ад тыпу сэрвісу, можна выкарыстоўваць каманду kubectl port-forward для падлучэння да яго:
Аднак вы па-ранейшаму не можаце дастукацца да прыкладання.
Гэта азначае, што, хутчэй за ўсё, няправільна настроены кантролер Ingress. Паколькі кантролер Ingress з'яўляецца іншым кампанентам у кластары, існуюць розныя метады адладкі ў залежнасці ад яго тыпу.
Але перш чым звярнуцца да дапамогі адмысловых прылад для налады Ingress'а, можна зрабіць нешта зусім простае. Ingress выкарыстоўвае serviceName и servicePort для падлучэння да сэрвісу. Неабходна праверыць, ці правільна яны настроены. Зрабіць гэта можна з дапамогай каманды:
kubectl describe ingress <ingress-name>
Калі слупок Backend пусты, высокая верагоднасць памылкі ў канфігурацыі. Калі бэкэнды на месцы, але доступу да дадатку па-ранейшаму няма, то праблема можа быць звязана з:
настройкамі даступнасці Ingress'а з публічнага інтэрнэту;
настройкамі даступнасці кластара з публічнага інтэрнэту.
Выявіць праблемы з інфраструктурай можна, падлучыўшыся напрамую да pod'у Ingress'а. Для гэтага спачатку знайдзіце pod Ingress-кантролера (ён можа знаходзіцца ў іншай прасторы імёнаў):
Цяпер усе запыты на порт 3000 на кампутары будуць перанакіроўвацца на порт 80 pod'а.
Ці працуе ён зараз?
Калі так, то праблема з інфраструктурай. Неабходна высветліць, як менавіта ажыццяўляецца маршрутызацыя трафіку ў кластар.
Калі не, то праблема з кантролерам Ingress.
Калі не атрымліваецца прымусіць працаваць кантролер Ingress, давядзецца правесці яго адладку.
Існуе шмат разнавіднасцяў кантролераў Ingress. Самымі папулярнымі з'яўляюцца Nginx, HAProxy, Traefik і інш. (падрабязней аб існуючых рашэннях гл. нашым аглядзе - заўв. перав.) Варта скарыстацца кіраўніцтвам па ўхіленні непаладак у дакументацыі які адпавядае кантролера. Паколькі Ingress Nginx з'яўляецца самым папулярным кантролерам Ingress, мы ўключылі ў артыкул некалькі парад па рашэнні звязаных з ім праблем.
Адладка кантролера Ingress Nginx
У праекту Ingress-nginx маецца афіцыйны убудова для kubectl. Каманду kubectl ingress-nginx можна выкарыстоўваць для:
аналізу логаў, бэкэндаў, сертыфікатаў і г.д.;
падлучэння да Ingress'у;
вывучэння бягучай канфігурацыі.
Дапамогуць вам у гэтым наступныя тры каманды:
kubectl ingress-nginx lint - правярае nginx.conf;
kubectl ingress-nginx backend - даследуе бэкэнд (па аналогіі з kubectl describe ingress <ingress-name>);
kubectl ingress-nginx logs - правярае логі.
Звярніце ўвагу: у некаторых выпадках можа спатрэбіцца пазначыць правільную прастору імёнаў для кантролера Ingress з дапамогай сцяга --namespace <name>.
Рэзюмэ
Дыягностыка ў Kubernetes можа аказацца няпростай задачай, калі не ведаць, з чаго пачаць. Да праблемы заўсёды варта падыходзіць па прынцыпе "знізу-уверх": пачынайце з pod'ов, а затым пераходзіце да сэрвісу і Ingress'у. Метады адладкі, апісаныя ў артыкуле, могуць прымяняцца і да іншых аб'ектаў, такім як: