Netramesh - легкаважнае service mesh рашэнне

У працэсе пераходу ад маналітнага дадатку да мікрасэрвіснай архітэктуры мы сутыкаемся з новымі праблемамі.

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

Netramesh - легкаважнае service mesh рашэнне

Я доўга шукаў інструмент, які дапамог бы справіцца з такімі праблемамі (пісаў пра гэта на Хабры: 1, 2), але ў выніку зрабіў уласнае апенсорснае рашэнне. У артыкуле я расказваю пра перавагі падыходу service mesh і дзялюся новым інструментам для яго рэалізацыі.

Размеркаваны tracing з'яўляецца распаўсюджаным рашэннем праблемы пошуку памылак у размеркаваных сістэмах. Але што калі ў сістэме яшчэ не ўкаранёны такі падыход да збору інфармацыі аб сеткавых узаемадзеяннях, ці, што горш, у частцы сістэмы ён ужо спраўна працуе, а ў частцы яго няма, бо ён не дададзены ў старыя сэрвісы? Для вызначэння дакладнага каранёвага чынніку праблемы неабходна мець поўную карціну таго, што адбываецца ў сістэме. Асабліва важна разумець, якія менавіта мікрасэрвісы ўдзельнічаюць у асноўных крытычных для бізнэсу шляхах.

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

Service mesh падыход

Галоўнай ідэяй service mesh падыходу з'яўляецца даданне яшчэ аднаго інфраструктурнага пласта над сеткай, які дазволіць нам рабіць любыя рэчы з міжсэрвісным узаемадзеяннем. Большасць рэалізацый працуюць наступным чынам: да кожнага мікрасэрвісу дадаецца дадатковы sidecar кантэйнер з празрыстым проксі, праз які прапускаецца ўвесь уваходны і выходны трафік сэрвісу. І гэта тое самае месца, дзе мы можам рабіць кліенцкае балансаванне, прымяняць палітыкі бяспекі, уводзіць абмежаванні на колькасць запытаў і збіраць важную інфармацыю па ўзаемадзеянні сэрвісаў у production.

Netramesh - легкаважнае service mesh рашэнне

Рашэнні

Ужо ёсць некалькі рэалізацый гэтага падыходу: Ісціё и linkerd2. Яны падаюць мноства магчымасцяў са скрынкі. Але адначасова з гэтым прыходзіць і вялікі overhead на рэсурсы. Прычым чым больш кластар, у якім працуе такая сістэма, тым больш спатрэбіцца рэсурсаў на падтрыманне новай інфраструктуры. У Авіта мы эксплуатуем kubernetes кластары, у якіх знаходзяцца тысячы асобнікаў сэрвісаў (і іх колькасць працягвае хутка расці). У бягучай рэалізацыі Istio спажывае ~300Mb аператыўнай памяці на кожны асобнік сэрвісу. З-за вялікай колькасці магчымасцяў празрыстае балансаванне таксама ўплывае на поўны час адказу сэрвісаў (аж да 10ms).

У выніку мы паглядзелі на тое, якія менавіта магчымасці нам патрэбныя прама зараз, і вырашылі, што асноўнае, з-за чаго мы пачалі ўкараняць такія рашэнні, была магчымасць збіраць tracing інфармацыю з усёй сістэмы празрыста. Таксама нам жадалася мець кантроль над узаемадзеяннем сэрвісаў і рабіць розныя маніпуляцыі з загалоўкамі, якія перадаюцца паміж сэрвісамі.

У выніку мы прыйшлі да свайго рашэння:  Netramesh.

Netramesh

Netramesh - гэта легкаважнае service mesh рашэнне з магчымасцю бясконцага маштабавання па-за залежнасцю ад колькасці сэрвісаў у сістэме.

Галоўнымі мэтамі новага рашэння з'яўляліся невялікі overhead па рэсурсах і высокая прадукцыйнасць. З асноўных магчымасцяў мы жадалі адразу мець магчымасць празрыста адпраўляць tracing span'ы ў нашу Jaeger сістэму.

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

Proizvoditelnost

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

Давайце паглядзім, якія вынікі атрымаліся.

RAM

Netramesh спажывае ~10Mb без трафіку і 50Mb максімальна з нагрузкай да 10000 RPS на XNUMX instance.

Istio envoy proxy заўсёды спажывае ~300Mb у нашых кластарах з тысячамі instance'ов. Гэта не дазваляе маштабаваць яго на ўвесь кластар.

Netramesh - легкаважнае service mesh рашэнне

Netramesh - легкаважнае service mesh рашэнне

C Netramesh мы атрымалі памяншэнне спажывання памяці ў ~10 разоў.

CPU

Выкарыстанне CPU адносна роўна пад нагрузкай. Яно залежыць ад колькасці запытаў у адзінку часу да sidecar. Значэнні пры 3000 запытах у секунду ў піку:

Netramesh - легкаважнае service mesh рашэнне

Netramesh - легкаважнае service mesh рашэнне

Ёсць яшчэ адзін важны момант: Netramesh - рашэнне без control plane і без нагрузкі не спажывае працэсарны час. З Istio sidecar'ы заўсёды абнаўляюць endpoint'ы сэрвісаў. У выніку мы можам бачыць такую ​​карціну без нагрузкі:

Netramesh - легкаважнае service mesh рашэнне

Мы выкарыстоўваем HTTP/1 для ўзаемадзеяння паміж сэрвісамі. Павелічэнне часу адказу ў Istio пры праксіраванні праз envoy было да 5-10ms, што дастаткова шмат для сэрвісаў, якія гатовыя адказваць за мілісекунду. З Netramesh гэты час паменшылася да 0.5-2ms.

маштабаванасць

Невялікая колькасць рэсурсаў, якая затрачваецца кожным проксі, дае магчымасць размяшчаць яго побач з кожным сэрвісам. Netramesh наўмысна быў створаны без control plane кампанента для простага падтрымання легкаважнасці кожнага sidecar'а. Часта ў service mesh рашэннях control plane распаўсюджвае service discovery інфармацыю ў кожны sidecar. Разам з ёй прыязджае і інфармацыя аб timeout'ах, наладах балансавання. Усё гэта дазваляе рабіць шмат карысных рэчаў, але, нажаль, раздзімае sidecar'ы ў памеры.

Service discovery

Netramesh - легкаважнае service mesh рашэнне

Netramesh не дадае якіх-небудзь дадатковых механізмаў для абслугоўвання кампутара. Увесь трафік праксіруецца празрыста праз netra sidecar.

Netramesh падтрымлівае HTTP/1 прыкладны пратакол. Для яго вызначэння выкарыстоўваецца канфігуруемы спіс партоў. Звычайна ў сістэме ёсць некалькі портаў, па якіх адбываецца ўзаемадзеянне па HTTP. Напрыклад, у нас для ўзаемадзеяння сэрвісаў і вонкавых запытаў выкарыстоўваюцца 80, 8890, 8080. У такім выпадку іх можна задаць з дапамогай зменнай асяроддзя NETRA_HTTP_PORTS.

Калі вы карыстаецеся Kubernetes у якасці аркестратара і яго механізм Service сутнасцяў для внутрикластерного ўзаемадзеянні паміж сэрвісамі, то механізм застаецца роўна такім жа. Спачатку мікрасэрвіс атрымлівае service IP адрас з дапамогай kube-dns і адчыняе новае злучэнне да яго. Гэта злучэнне усталёўваецца спачатку з лакальным netra-sidecar і ўсе TCP пакеты першапачаткова прылятаюць менавіта ў netra. Далей ужо netra-sidecar усталёўвае злучэнне з першапачатковай кропкай прызначэння. NAT на pod IP на нодзе застаецца роўна такім жа як і без netra.

Размеркаваны tracing і пракідванне кантэксту

Netramesh дае функцыянальнасць, неабходную для адпраўкі tracing span'аў аб HTTP узаемадзеянні. Netra-sidecar парсят HTTP пратакол, вымяраюць затрымкі запытаў, дастаюць неабходную інфармацыю з HTTP header'аў. У канчатковым рахунку мы атрымліваем усе trace'ы ў адзінай Jaeger сістэме. Для тонкай канфігурацыі можна таксама выкарыстоўваць зменныя асяроддзі, якія падае афіцыйная бібліятэка. jaeger go library.

Netramesh - легкаважнае service mesh рашэнне

Netramesh - легкаважнае service mesh рашэнне

Але ёсць праблема. Пакуль сэрвісы не будуць генераваць і пракідваць спецыяльны uber загаловак, мы не ўбачым злучаныя tracing span'ы ў сістэме. А гэта тое, што нам неабходна для хуткага пошуку прычыны праблем. Тут Netramesh зноў мае рашэньне. Проксі чытаюць HTTP загалоўкі і, калі ў іх няма uber trace id, генеруюць яго. Netramesh таксама захоўвае інфармацыю аб уваходных і выходных запытах у sidecar і супастаўляе іх шляхам узбагачэння неабходнымі загалоўкамі выходных запытаў. Усё, што неабходна рабіць у сэрвісах - пракідваць усяго адзін загаловак X-Request-Id, які можна сканфігураваць з дапамогай зменнай асяроддзя NETRA_HTTP_REQUEST_ID_HEADER_NAME. Для кіравання памерам context'а ў Netramesh, можна задаваць наступныя зменныя асяроддзі: NETRA_TRACING_CONTEXT_EXPIRATION_MILLISECONDS (час, на працягу якога будзе захоўвацца кантэкст) і NETRA_TRACING_CONTEXT_CLEANUP_INTERVAL (перыядычнасць падчысткі кантэксту).

Таксама магчыма камбінаваць некалькі шляхоў у вашай сістэме шляхам маркіравання іх спецыяльным сесійным маркерам. Netra дазваляе ўсталяваць HTTP_HEADER_TAG_MAP для ператварэння HTTP загалоўкаў у адпаведныя tracing span тэгі. Гэта можа быць асабліва карысна для тэсціравання. Пасля праходжання функцыянальнага тэсту, можна паглядзець якая частка сістэмы была закранута, адфільтраваўшы па які адпавядае session ключу.

Вызначэнне крыніцы запыту

Для вызначэння таго, адкуль прыйшоў запыт, можна карыстацца функцыяналам аўтаматычнага дадання загалоўка з крыніцай. З дапамогай зменнай асяроддзя NETRA_HTTP_X_SOURCE_HEADER_NAME можна задаць імя загалоўка, якое будзе аўтаматычна ўстанаўлівацца. З дапамогай NETRA_HTTP_X_SOURCE_VALUE можна задаць значэнне, у якое будзе ўсталёўвацца X-Source загаловак на ўсе выходныя запыты.

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

Роўтынг трафіку і вантробы Netramesh

Netramesh складаецца з двух асноўных кампанентаў. Першы, netra-init, усталёўвае сеткавыя правілы для перахопу трафіку. Ён выкарыстоўвае iptables redirect правілы для перахопу за ўсё, альбо часткі трафіку на sidecar, які з'яўляецца другім галоўным кампанентам Netramesh. Можна наладзіць, якія менавіта парты трэба перахапляць на ўваходныя і выходныя TCP сесіі: INBOUND_INTERCEPT_PORTS, OUTBOUND_INTERCEPT_PORTS.

Таксама ў інструменце ёсць цікавая магчымасць - імавернасны роўтынг. Калі выкарыстоўваць Netramesh выключна для збору tracing span'аў, то ў production асяроддзі можна зэканоміць рэсурсы і ўключыць імавернасны роўтынг з дапамогай зменных. NETRA_INBOUND_PROBABILITY и NETRA_OUTBOUND_PROBABILITY (ад 0 да 1). Значэнне па змаўчанні роўна 1 (перахапляецца ўвесь трафік).

Пасля паспяховага перахопу netra sidecar прымае новае злучэнне і выкарыстоўвае SO_ORIGINAL_DST опцыю сокета для атрымання першапачатковай кропкі прызначэння. Затым Netra адчыняе новае злучэнне да першапачатковага IP-адрасу і ўсталёўвае двухбаковае TCP-зносіны паміж бакамі, слухаючы ўвесь які праходзіць трафік. Калі порт вызначаны як HTTP, Netra спрабуе парсіць яго і трэйсіць. Калі парсінг HTTP аказваецца няўдалым, Netra робіць фолбэк на TCP і празрыста праксіруе байты.

Пабудова графа залежнасцяў

Пасля атрымання вялікай колькасці tracing інфармацыі ў Jaeger, хочацца атрымаць поўны граф узаемадзеянняў у сістэме. Але калі ваша сістэма досыць нагружана і за дзень назапашваюцца мільярды tracing span'ов, зрабіць іх агрэгацыю становіцца не гэтак простай задачай. Ёсць афіцыйны спосаб для гэтага: spark-dependencies. Тым не менш ён зойме гадзіннік для пабудовы поўнага графа і прымусіць выпампаваць з Jaeger увесь dataset за мінулыя суткі.

Калі вы выкарыстоўваеце Elasticsearch для захоўвання tracing span'аў, можна скарыстацца просты ўтылітай на Golang, Якая пабудуе такі ж граф за хвіліны, выкарыстоўваючы асаблівасці і магчымасці Elasticsearch.

Netramesh - легкаважнае service mesh рашэнне

Як выкарыстоўваць Netramesh

Netra можна проста дадаць да любога сэрвісу, які працуе пад кіраваннем любога аркестратара. Можна паглядзець прыклад тут.

На бягучы момант у Netra няма магчымасці аўтаматычнага ўкаранення sidecar'а да сэрвісаў, але ёсць планы на рэалізацыю.

Будучыня Netramesh

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

У будучыні Netramesh атрымае падтрымку іншых пратаколаў прыкладнога ўзроўня апроч HTTP. У найбліжэйшай будучыні з'явіцца магчымасць L7 роўтынгу.

Выкарыстоўвайце Netramesh, калі вы сутыкаецеся з такімі праблемамі, і пішыце нам пытанні і прапановы.

Крыніца: habr.com

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