Istio Circuit Breaker: адключаем няспраўныя кантэйнеры

Святы завяршыліся, і мы вяртаемся з нашым другім пастом з серыі па Istio Service Mesh.

Istio Circuit Breaker: адключаем няспраўныя кантэйнеры

Сённяшняя тэма - Circuit Breaker, што ў перакладзе на рускую электратэхнічны азначае "аўтаматычны выключальнік", у прастамоўі - "аўтамат абароны". Толькі ў Istio гэты аўтамат адключае не які караціў або перагружаны ланцуг, а няспраўныя кантэйнеры.

Як гэта павінна працаваць у ідэале

Калі мікрасэрвісы кіруюцца Kubernetes'ам, напрыклад, у рамках платформы OpenShift, яны аўтаматычна маштабуецца ўверх-уніз у залежнасці ад нагрузкі. Паколькі мікрасэрвісы працуюць у pod'ах, на адной канчатковай кропцы можа быць адразу некалькі асобнікаў кантэйнерызаванага мікрасэрвісу, а Kubernetes будзе маршрутызаваць запыты і балансаваць нагрузку паміж імі. І - у ідэале - усё гэта павінна выдатна працаваць.

Мы памятаем, што мікрасэрвісы - маленькія і эфемерныя. Эфемернасць, якая тут азначае прастату ўзнікнення і знікнення, часта недаацэньваюць. Нараджэнне і смерць чарговага асобніка мікрасэрвісу ў pod'е - рэчы цалкам чаканыя, OpenShift і Kubernetes з гэтым добра спраўляюцца, і ўсё выдатна працуе - але зноў жа ў тэорыі.

Як гэта працуе на самой справе

А зараз прадстаўце, што нейкі пэўны асобнік мікрасэрвісу, то бок кантэйнер, прыйшоў у непрыдатнасць: альбо не адказвае (памылка 503), альбо – што непрыемней – рэагуе, але занадта павольна. Інакш кажучы, ён падглючвае ці не адказвае на запыты, але з пула ён пры гэтым аўтаматычна не прыбіраецца. Што трэба рабіць у гэтым выпадку? Паўтарыць спробу? Прыбраць яго са схемы маршрутызацыі? І што значыць "занадта павольна" - колькі гэта ў лічбах, і хто іх вызначае? Можа, проста даць яму паўзу і паспрабаваць пазней? Калі так, то наколькі пазней?

Што такое Pool Ejection у Istio

І тут на дапамогу прыходзіць Istio са сваімі аўтаматамі абароны Circuit Breaker, якія часова прыбіраюць няспраўныя кантэйнеры з пула рэсурсаў маршрутызацыі і балансаванні нагрузкі, рэалізуючы працэдуру Pool Ejection.

Выкарыстоўваючы стратэгію выяўлення адхіленняў (outlier detection), Istio дэтэктуе крывыя pod'ы, якія выбіваюцца з агульнага шэрагу, і прыбірае іх з пула рэсурсаў на зададзены час, якое завецца "акно сну" (sleep window).

Каб паказаць, як гэта працуе ў Kubernetes на платформе OpenShift, пачнем са скрыншота нармальна працуючых мікрасэрвісаў з прыкладу ў рэпазітары Red Hat Developer Demos. Тут у нас есць два pod'а, v1 і v2, у кожным з якіх працуе па адным кантэйнеры. Калі правілы маршрутызацыі Istio не выкарыстоўваюцца, Kubernetes па змаўчанні прымяняе раўнамерна збалансаваную цыклічную маршрутызацыю:

Istio Circuit Breaker: адключаем няспраўныя кантэйнеры

Рыхтуемся да збою

Перш чым рабіць Pool Ejection, трэба стварыць правіла маршрутызацыі Istio. Дапушчальны, мы жадаем размяркоўваць запыты паміж pod'амі ў стаўленні 50/50. Акрамя таго, мы павялічым колькасць кантэйнераў v2 з аднаго да двух, вось так:

oc scale deployment recommendation-v2 --replicas=2 -n tutorial

Зараз задаем правіла маршрутызацыі, каб трафік размяркоўваўся паміж pod'амі ў стаўленні 50/50.

Istio Circuit Breaker: адключаем няспраўныя кантэйнеры
А вось як выглядае вынік працы гэтага правіла:

Istio Circuit Breaker: адключаем няспраўныя кантэйнеры
Можна прычапіцца, што на гэтым скрыне не 50/50, а 14:9, але з часам сітуацыя выправіцца.

Уладкоўваем збой

А зараз вывядзем са строю адзін з двух кантэйнераў v2, каб у нас быў адзін спраўны кантэйнер v1, адзін спраўны кантэйнер v2 і адзін няспраўны кантэйнер v2:

Istio Circuit Breaker: адключаем няспраўныя кантэйнеры

Чынім збой

Такім чынам, у нас ёсць няспраўны кантэйнер, і надышоў час Pool Ejection. З дапамогай вельмі простага канфіга мы выключым гэты збойны кантэйнер з любых схем маршрутызацыі на 15 секунд у разліку на тое, што ён сам вернецца ў спраўны стан (альбо перазапусціцца, альбо адновіць прадукцыйнасць). Вось як выглядае гэты канфіг і вынікі яго працы:

Istio Circuit Breaker: адключаем няспраўныя кантэйнеры
Istio Circuit Breaker: адключаем няспраўныя кантэйнеры
Як бачна, няспраўны кантэйнер v2 больш не выкарыстоўваецца пры маршрутызацыі запытаў, паколькі яго прыбралі з пула. Але па заканчэнні 15 секунд ён аўтаматычна вернецца ў пул. Уласна, мы толькі што паказалі, як працуе Pool Ejection.

Пачынаем будаваць архітэктуру

Pool Ejection у спалучэнні з магчымасцямі маніторынгу Istio дазваляе пачаць выбудоўваць фрэймворк аўтаматычнай замены няспраўных кантэйнераў, каб скараціць, а то і зусім ухіліць прастоі і збоі.

У NASA ёсць адзін гучны дэвіз - Failure Is Not an Option, аўтарам якога лічыцца кіраўнік палётаў Джын Кранц. На рускую яго можна перавесці як «Параза – гэта не варыянт», і сэнс тут у тым, што ўсё можна прымусіць працаваць, маючы на ​​тое дастаткова волі. Аднак у рэальным жыцці адмовы не проста здараюцца, яны непазбежныя, усюды і ва ўсім. І як жа з імі спраўляцца ў выпадку мікрасэрвісу? На наш погляд, лепш належыць не на сілу волі, а на магчымасці кантэйнераў, Kubernetes, Red Hat OpenShift, І Ісціё.

Istio, як мы ўжо пісалі вышэй, рэалізуе выдатна зарэкамендавалую сябе ў фізічным свеце канцэпцыю аўтаматычных выключальнікаў. І як электрычны аўтамат адключае праблемны ўчастак ланцуга, так і праграмны Circuit Breaker у Istio размыкае сувязь паміж струменем запытаў і праблемным кантэйнерам, калі з канчатковай кропкай нешта не ў парадку, напрыклад, калі сервер зваліўся ці пачаў тармазіць.

Прычым у другім выпадку праблем толькі больш, паколькі тормазы аднаго кантэйнера не толькі выклікаюць каскад затрымак у якія звяртаюцца да яго сэрвісах і, як следства, змяншаюць прадукцыйнасць сістэмы ў цэлым, але і спараджаюць паўтор запытаў да і так ужо павольна працавальнаму сэрвісу, што толькі пагаршае сітуацыю .

Circuit Breaker у тэорыі

Circuit Breaker - гэта проксі, які кантралюе паток да запытаў да канчатковай кропкі. Калі гэтая кропка перастае працаваць ці - у залежнасці ад зададзеных налад - пачынае тармазіць, проксі разрывае сувязь з кантэйнерам. Трафік пасля гэтага перанакіроўваецца на іншыя кантэйнеры, ну проста з-за балансавання нагрузкі. Сувязь застаецца растуленай (open) на працягу зададзенага акна сну, скажам, дзве хвіліны, а затым лічыцца напаўразмкнутай (half-open). Спроба даслаць наступны запыт вызначае далейшы стан сувязі. Калі з сэрвісам усё ОК, сувязь вяртаецца ў працоўны стан і зноў становіцца замкнёнай (closed). Калі ж з сэрвісам па-ранейшаму нешта не тое, сувязь размыкаецца і зноўку ўключаецца акно сну. Вось як выглядае спрошчаная дыяграма змены станаў Circuit Breaker:

Istio Circuit Breaker: адключаем няспраўныя кантэйнеры
Тут важна адзначыць, што ўсё гэта адбываецца на ўзроўні, так бы мовіць, сістэмнай архітэктуры. Таму ў нейкі момант вам давядзецца навучыць свае прыкладанні працаваць з Circuit Breaker, напрыклад, прадастаўляць у адказ значэнне па змаўчанні ці ж, калі гэта магчыма, ігнараваць існаванне сэрвісу. Для гэтага выкарыстоўваецца bulkhead pattern, але ён выходзіць за рамкі гэтага артыкула.

Circuit Breaker на практыцы

Для прыкладу мы запусцім на OpenShift дзве версіі нашага мікрасэрвісу рэкамендацый. Версія 1 будзе працаваць нармальна, а вось у v2 мы ўбудуем затрымку, каб імітаваць тормазы на серверы. Для прагляду вынікаў выкарыстоўваецца інструмент аблога:

siege -r 2 -c 20 -v customer-tutorial.$(minishift ip).nip.io

Istio Circuit Breaker: адключаем няспраўныя кантэйнеры
Усё быццам бы працуе, але якім коштам? На першы погляд у нас 100% даступнасць, але прыгледзьцеся - максімальная працягласць транзакцыі складае цэлых 12 секунд. Гэта відавочна вузкае месца, і яго трэба расшываць.

Для гэтага мы з дапамогай Istio выключым звароты да павольных кантэйнераў. Вось як выглядае адпаведны канфіг з выкарыстаннем Circuit Breaker:

Istio Circuit Breaker: адключаем няспраўныя кантэйнеры
Апошні радок з параметрам httpMaxRequestsPerConnection сігналізуе, што сувязь з павінна размыкацца пры спробе стварыць яшчэ адно - другое - падлучэнне ў дадатак да ўжо наяўнага. Паколькі наш кантэйнер імітуе які тармозіць сэрвіс, такія сітуацыі будуць перыядычна ўзнікаць, і тады Istio будзе вяртаць памылку 503, а вось што пакажа siege:

Istio Circuit Breaker: адключаем няспраўныя кантэйнеры

Добра, у нас ёсць Circuit Breaker, што далей?

Такім чынам, мы рэалізавалі аўтаматычнае адключэнне, зусім не чапаючы зыходны код саміх сэрвісаў. Выкарыстоўваючы Circuit Breaker і апісаную вышэй працэдуру Pool Ejection, мы можам прыбіраць з пула рэсурсаў тармазныя кантэйнеры датуль, пакуль яны не прыйдуць у норму, і правяраць іх стан з зададзенай перыядычнасцю у нашым прыкладзе, гэта дзве хвіліны (параметр sleepWindow).

Звярніце ўвагу, што здольнасць прыкладання рэагаваць на памылку 503 усё яшчэ задаецца на ўзроўні яго зыходнага кода. Існуе мноства стратэгій працы з Circuit Breaker, якія прымяняюцца ў залежнасці ад сітуацыі.

У наступным пасце: раскажам аб трасіроўцы і маніторынгу, якія ўжо ўбудаваны або лёгка дадаюцца ў Istio, а таксама аб тым, як уносіць памылкі ў сістэму наўмысна.

Крыніца: habr.com

Дадаць каментар