Kubernetes: паскорце вашыя сэрвісы праз зняцце працэсарных абмежаванняў

Яшчэ ў 2016 годзе мы ў Buffer перайшлі на Kubernetes, і цяпер каля 60 нод (на AWS) і 1500 кантэйнераў працуюць на нашым k8s-кластары пад кіраваннем удар нагамі. Тым не менш, на мікрасэрвісы мы пераходзілі метадам спроб і памылак, і нават пасля некалькіх гадоў нашай працы з k8s мы дагэтуль сутыкаемся з новымі для сябе праблемамі. У гэтым пасце мы пагаворым пра працэсарныя абмежаванні: чаму мы лічылі іх добрай практыкай і чаму ў выніку яны аказаліся не такія добрыя.

Працэсарныя абмежаванні і тротлінг

Як і многія іншыя карыстальнікі Kubernetes, Google вельмі рэкамендуе наладжваць працэсарныя абмежаванні. Без такой налады кантэйнеры ў нодзе могуць заняць усе магутнасці працэсара, з-за чаго, у сваю чаргу, важныя Kubernetes-працэсы (напрыклад kubelet) перастануць рэагаваць на запыты. Такім чынам, настройка працэсарных абмежаванняў гэта добры спосаб абароны вашых нод.

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

Што можа здарыцца, калі мы не зададзім працэсарныя абмежаванні?

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

Праява праблемы тратлінгу і водгуку

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

Kubernetes: паскорце вашыя сэрвісы праз зняцце працэсарных абмежаванняў

Як можна бачыць ніжэй, мы задалі абмежаванне ў 800m (0.8 ці 80% ядра), і пікавыя значэння ў лепшым выпадку дасягаюць 200m (20% ядра). Здавалася б, да тротлінгу сэрвісу ў нас яшчэ досыць працэсарных магутнасцяў, аднак…

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

Сутыкнуўшыся з гэтым, мы неўзабаве выявілі некалькі рэсурсаў (праблема на github, прэзентацыя на zadano, пост на omio) пра падзенне прадукцыйнасці і часу водгуку сэрвісаў з-за тратлінгу.

Чаму мы назіраем тротлінг пры нізкай нагрузцы працэсара? Кароткая версія гучыць так: "у ядры Linux ёсць баг, з-за якога спрацоўвае неабавязковы тротлінг кантэйнераў з зададзенымі працэсарнымі абмежаваннямі". Калі вас цікавіць прырода праблемы, вы можаце азнаёміцца ​​з прэзентацыяй (відэа и тэкставы варыянты) за аўтарствам Дэйва Чылука (Dave Chiluk).

Зняцце працэсарных абмежаванняў (з асаблівай асцярожнасцю)

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

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

Kubernetes: паскорце вашыя сэрвісы праз зняцце працэсарных абмежаванняў
Дзелавая перапіска па надзённым пытанні.

Як абараніць вашы ноды пры зняцці абмежаванняў?

Ізаляванне "неабмежаваных" сэрвісаў:

У мінулым мы ўжо назіралі, як некаторыя ноды пападалі ў стан notReady, у першую чаргу з-за сэрвісаў, якія спажывалі занадта шмат рэсурсаў.

Мы вырашылі размясціць такія сэрвісы ў асобныя ("пазначаныя") ноды, каб тыя не перашкаджалі "звязаным" сэрвісам. У выніку дзякуючы адзнакам да некаторых нодаў і даданню параметру toleration («талератнасць») да «незвязаных» сэрвісаў, мы дамагліся большага кантролю над кластарам, і нам стала лягчэй вызначаць праблемы з нодамі. Каб самастойна правесці аналагічныя працэсы, вы можаце азнаёміцца ​​з дакументацыяй.

Kubernetes: паскорце вашыя сэрвісы праз зняцце працэсарных абмежаванняў

Прызначэнне карэктнага запыту працэсара і памяці:

Больш за ўсё мы баяліся, што працэс зжарэ занадта шмат рэсурсаў і нода перастане адказваць на запыты. Бо цяпер (дзякуючы Datadog) мы маглі выразна назіраць за ўсімі сэрвісамі на нашым кластары, я прааналізаваў некалькі месяцаў працы тых з іх, якія мы планавалі прызначыць "незвязанымі". Я проста задаў максімальнае выкарыстанне працэсара з запасам у 20%, і такім чынам вылучыў месца ў нодзе на выпадак, калі k8s будзе спрабаваць прызначаць іншыя сэрвісы ў ноду.

Kubernetes: паскорце вашыя сэрвісы праз зняцце працэсарных абмежаванняў

Як можна бачыць на графіцы, максімальная нагрузка на працэсар дасягнула 242m CPU ядраў (0.242 ядра працэсара). За запыт працэсара дастаткова ўзяць лік крыху большы ад гэтага значэння. Звярніце ўвагу, што паколькі сэрвісы арыентаваны на карыстальнікаў, віновыя значэнні нагрузкі супадаюць з трафікам.

Зрабіце тое ж самае з выкарыстаннем памяці і запытамі, і вуаля - вы ўсё наладзілі! Для большай бяспекі вы можаце дадаць гарызантальнае аўтаскаляванне подаў. Такім чынам кожны раз, калі нагрузка на рэсурсы будзе высокая, аўтаскаляванне створыць новыя поды, і kubernetes размяркуе іх у ноды са свабодным месцам. На выпадак калі месца не застанецца ў самым кластары, вы можаце задаць сабе абвестку або наладзіць даданне новых нод праз іх аўтаскаляванне.

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

Вынікі

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

Kubernetes: паскорце вашыя сэрвісы праз зняцце працэсарных абмежаванняў

Найлепшага выніку мы дабіліся на нашай галоўнай старонцы (buffer.com), там сэрвіс паскорыўся ў дваццаць два разы!

Kubernetes: паскорце вашыя сэрвісы праз зняцце працэсарных абмежаванняў

Ці выпраўлены баг ядра Linux?

Ды, баг ужо выпраўлены, і фікс дададзены ў ядро дыстрыбутываў версіі 4.19 і вышэй.

Тым не менш, пры чытанні праблемы kubernetes на github за другое верасня 2020 года мы ўсё яшчэ сутыкаемся са згадваннямі некаторых Linux-праектаў з аналагічным багам. Я мяркую, што ў некаторых дыстрыбутывах Linux усё яшчэ ёсць гэтая памылка і зараз толькі вядзецца праца над яе выпраўленнем.

Калі ваша версія дыстрыбутыва ніжэй 4.19, я б парэкамендаваў абнавіцца да апошняй, але вам у любым выпадку варта паспрабаваць зняць працэсарныя абмежаванні і паглядзець ці захаваецца тротлінг. Ніжэй можна азнаёміцца ​​з няпоўным спісам кіраўнікоў Kubernetes сэрвісаў і Linux дыстрыбутываў:

  • Debian: фікс інтэграваны ў апошнюю версію дыстрыбутыва, папойка, і выглядае дастаткова свежым (жнівень 2020 года). Некаторыя папярэднія версіі таксама могуць быць пафікшаны.
  • Ubuntu: фікс інтэграваны ў апошнюю версію Ubuntu Focal Fossa 20.04/XNUMX
  • EKS абзавёўся фіксам яшчэ у снежні 2019 года. Калі ваша версія ніжэй за гэтую, варта абнавіць AMI.
  • kops: З чэрвеня 2020 года у kops 1.18+ асноўнай выявай хаста стане Ubuntu 20.04. Калі ваша версія kops старэй, вам, верагодна, давядзецца пачакаць фікса. Мы і самі зараз чакаем.
  • GKE (Google Cloud): Фікс інтэграваны у студзені 2020 года, аднак праблемы з тротлінгам усё яшчэ назіраюцца.

Што рабіць, калі фікс выправіў праблему з тротлінгам?

Я не ўпэўнены, што праблема поўнасцю вырашана. Калі мы дабяромся да версіі ядра з фіксам, я пратэстую кластар і абнаўлю пост. Калі нехта ўжо абнавіўся, я з цікавасцю азнаёмлюся з вашымі вынікамі.

Заключэнне

  • Калі вы працуеце з Docker-кантэйнерамі пад Linux (не важна Kubernetes, Mesos, Swarm ці яшчэ якімі), вашы кантэйнеры могуць губляць у прадукцыйнасці з-за тратлінгу;
  • Паспрабуйце абнавіцца да апошняй версіі вашага дыстрыбутыва ў надзеі, што баг ужо пафіксілі;
  • Зняцце працэсарных абмежаванняў вырашыць праблему, але гэта небяспечны прыём, які варта ўжываць з асаблівай асцярожнасцю (лепш спачатку абнавіць ядро ​​і параўнаць вынікі);
  • Калі вы знялі працэсарныя абмежаванні, уважліва адсочвайце выкарыстанне працэсара і памяці, і пераканайцеся, што вашыя рэсурсы працэсара перавышаюць спажыванне;
  • Бяспечным варыянтам будзе аўтаскаляванне подаў для стварэння новых подаў у выпадку высокай нагрузкі на жалеза, каб kubernetes прызначаў іх у вольныя ноды.

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

PS Тут аўтар вядзе перапіску з чытачамі і каментатарамі (на англійскай).


Крыніца: habr.com

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