Топ факапаў Цыян

Топ факапаў Цыян

Добра ўсім! 

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

прэамбула

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

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

Асноўныя старонкі сайта ці як мы разумеем, што прабілі дно

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

Дапусцім, мы высветлілі, што ёсць шэраг суперважных раздзелаў сайта, якія адказваюць за асноўны сэрвіс - пошук і падачу аб'яваў. Калі колькасць запытаў, якія завяршыліся памылкай, перавышае 1%, - гэта крытычны інцыдэнт. Калі на працягу 15 хвілін у прайм-тайм працэнт памылак перавышае 0,1% - то гэта таксама лічыцца крытычным інцыдэнтам. Гэтыя крытэры пакрываюць большую частку інцыдэнтаў, астатнія выходзяць за рамкі гэтага артыкула.

Топ факапаў Цыян

Топ лепшых інцыдэнтаў Цыян

Такім чынам, мы сапраўды навучыліся вызначаць той факт, што інцыдэнт здарыўся. 

Цяпер кожны інцыдэнт у нас дэталёва апісаны і адлюстраваны ў эпіку Jira. Дарэчы: для гэтага мы завялі асобны праект, назвалі яго FAIL - у ім можна ствараць толькі эпікі. 

Калі сабраць усе фэйлы за апошнія некалькі гадоў, то лідзіруюць: 

  • інцыдэнты, звязаныя з mssql;
  • інцыдэнты, выкліканыя вонкавымі фактарамі;
  • памылкі адміна.

Спынімся больш дэталёва на памылках адмінаў, а таксама на некаторых іншых цікавых фэйлах.

Пятае месца - "Наводзім парадак у DNS"

Гэта быў дрэнны аўторак. Вырашылі мы навесці парадак у DNS-кластары. 

Захацелася перавесці ўнутраныя dns-серверы c bind на powerdns, вылучыўшы пад гэта цалкам асобныя серверы, дзе акрамя dns нічога няма. 

Размясцілі мы па адным dns-серверы ў кожнай лакацыі нашых ДЦ, і наступіў момант пераезду зон з bind у powerdns і пераключэнні інфраструктуры на новыя серверы. 

У самы разгар пераезду з усіх сервераў, якія былі пазначаны ў лакальных кэшуюць bind-ах на ўсіх серверах, застаўся толькі адзін, які быў у дата-цэнтры ў Санкт-Пецярбургу. Гэты ДЦ першапачаткова быў задэклараваны як некрытычны для нас, але раптоўна стаў single point of failure.
Якраз у такі перыяд пераезду ўпаў канал паміж Масквой і Санкт-Пецярбургам. Мы фактычна засталіся без DNS на пяць хвілін і падняліся, калі хостэр ухіліў непаладкі. 

Высновы:

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

  • Падчас складання плана дзеянняў адзначайце пункты, дзе сэрвіс можа зваліцца, і прадумвайце сцэнар, дзе ўсё пайшло "горш няма куды", загадзя.
  • Размяркоўвайце ўнутраныя dns-серверы па розных геолокациям/датацентрам/стойкам/камутатарам/уводам.
  • На кожным серверы стаўце лакальны які кэшуе dns-сервер, які перанакіроўвае запыты на асноўныя dns-серверы, а ў выпадку яго недаступнасці будзе адказваць з кэша. 

Чацвёртае месца - "Наводзім парадак у Nginx"

Аднаго дня наша каманда вырашыла, што «хопіць гэта трываць», і запусціўся працэс рэфактарынгу канфігаў nginx. Асноўная мэта - прывесці канфігі да інтуітыўна зразумелай структуры. Раней усё было «гістарычна склаўшымся» і логікі ў сабе ніякай не несла. Цяпер кожны server_name вынеслі ў аднайменны файл і размеркавалі ўсе канфігі па тэчках. Дарэчы - канфіг утрымоўвае ў сабе 253949 радкоў або 7836520 знака і займае амаль 7 мегабайт. Верхні ўзровень структуры: 

Nginx structure

├── access
│   ├── allow.list
...
│   └── whitelist.conf
├── geobase
│   ├── exclude.conf
...
│   └── geo_ip_to_region_id.conf
├── geodb
│   ├── GeoIP.dat
│   ├── GeoIP2-Country.mmdb
│   └── GeoLiteCity.dat
├── inc
│   ├── error.inc
...
│   └── proxy.inc
├── lists.d
│   ├── bot.conf
...
│   ├── dynamic
│   └── geo.conf
├── lua
│   ├── cookie.lua
│   ├── log
│   │   └── log.lua
│   ├── logics
│   │   ├── include.lua
│   │   ├── ...
│   │   └── utils.lua
│   └── prom
│       ├── stats.lua
│       └── stats_prometheus.lua
├── map.d
│   ├── access.conf
│   ├── .. 
│   └── zones.conf
├── nginx.conf
├── robots.txt
├── server.d
│   ├── cian.ru
│   │   ├── cian.ru.conf
│   │   ├── ...
│   │   └── my.cian.ru.conf
├── service.d
│   ├── ...
│   └── status.conf
└── upstream.d
    ├── cian-mcs.conf
    ├── ...
    └── wafserver.conf

Стала значна лепш, але падчас пераназвання і размеркаванні канфігаў частка з іх мела няправільнае пашырэнне і не патрапіла ў дырэктыву include *.conf. Як следства - частка хастоў стала недаступная і вяртала 301 на галоўную. З-за таго што код адказу быў не 5хх/4хх, гэта заўважылі не адразу, а толькі пад раніцу. Пасля гэтага мы пачалі пісаць тэсты на праверку інфраструктурных кампанентаў.

Высновы: 

  • Правільна структуруйце канфігі (не толькі nginx) і прадумвайце структуру на раннім этапе праекту. Дык вы зробіце іх больш зразумелымі камандзе, што ў сваю чаргу паменшыць ТТМ.
  • Для некаторых інфраструктурных кампанентаў пішыце тэсты. Напрыклад: праверка, што ўсе ключавыя server_name аддаюць правільны статут, + цела адказу. Досыць будзе мець пад рукой проста некалькі скрыптоў, якія правяраюць асноўныя функцыі кампанента, каб сутаргава не ўспамінаць у 3 гадзіны ночы, што ж яшчэ трэба праверыць. 

Трэцяе месца - "Раптам скончылася месца ў Cassandra"

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

У адзін дрэнны дзень кластар амаль ператварыўся ў гарбуз, а менавіта:

  • месцы заставалася каля 20% сумарна па кластары;
  • паўнавартасна дадаць ноды нельга, таму што не праходзіць cleanup пасля дадання ноды з-за недахопу месца на раздзелах;
  • прадукцыйнасць пакрысе падае, бо не працуе кампакцыя; 
  • кластар працуе ў аварыйным рэжыме.

Топ факапаў Цыян

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

Высновы:

  • На ўсіх серверах cassandra павінна быць занята не больш за 60% месца на кожным раздзеле. 
  • Загружаныя яны павінны быць не больш за на 50% па cpu.
  • Не варта забіваць на capacity planning і прадумваць яго трэба для кожнага кампанента, зыходзячы з яго спецыфікі.
  • Чым больш нод у кластары - тым лепш. Серверы, якія змяшчаюць невялікі аб'ём дадзеных, хутчэй пераналіваюцца, і такі кластар лягчэй рэанімаваць. 

Другое месца - "Зніклі дадзеныя з consul key-value storage"

Для service discovery мы, як і многія, выкарыстоўваем consul. Але ў нас яго key-value выкарыстоўваецца яшчэ і для blue-green выкладкі маналіта. Там захоўваецца інфармацыя пра актыўныя і неактыўныя апстрымы, якія мяняюцца месцамі падчас дэплою. Для гэтага быў напісаны сэрвіс дэплою, які ўзаемадзейнічаў з KV. У нейкі момант дадзеныя з KV зніклі. Аднавілі па памяці, але з шэрагам памылак. Як следства – пры выкладцы нагрузка на апстрымы размеркавалася нераўнамерна, а мы атрымалі шмат памылак 502 з-за перагрузкі бэкендаў па CPU. У выніку пераехалі з consul KV на postgres, адкуль выдаліць іх ужо не так проста.  

Высновы:

  • Сэрвісы без якой-небудзь аўтарызацыі не павінны змяшчаць у сабе крытычных для працы сайта дадзеных. Напрыклад, калі ў вас няма аўтарызацыі ў ES - лепш бы забараніць доступ на ўзроўні сеткі адусюль, дзе ён не патрэбен, пакінуць толькі неабходныя, а таксама зрабіць action.destructive_requires_name: true.
  • Адпрацоўвайце механізм рэзервовага капіявання і аднаўленні загадзя. Напрыклад, загадзя зрабіце скрыпт (напрыклад, на python), які ўмее і бекапіць і аднаўляць.

Першае месца - "Капітан невідавочна" 

У нейкі момант мы заўважылі нераўнамернае размеркаванне нагрузкі на апстрымы nginx у выпадках, калі ў бэкендзе было 10+ сервераў. З-за таго што round-robin накіроўваў запыты з 1 па апошні апстрым па парадку, і кожны релоад nginx пачынаў спачатку, на першыя апстрымы заўсёды прыходзілася больш запытаў, чым на астатнія. Як следства - яны працавалі павольней і пакутаваў увесь сайт. Гэта рабілася ўсё больш прыкметным па меры павелічэння колькасці трафіку. Проста абнавіць nginx для ўключэння random не выйшла трэба перарабляць кучу lua кода, які не ўзляцеў на версіі 1.15 (у той момант). Прыйшлося прапапатчыць наш nginx 1.14.2, укараніўшы ў яго падтрымку random. Гэта вырашыла праблему. Гэты баг перамагае ў намінацыі "капітан невідавочна".

Высновы:

Было вельмі цікава і захапляльна даследаваць гэты баг). 

  • Выбудуйце маніторынг так, каб ён дапамагаў знаходзіць падобныя флуктуацыі хутка. Напрыклад, можна выкарыстоўваць ELK для таго, каб назіраць за rps на кожны backend кожнага upstream, сачыць за іх часам адказу з пункту гледжання nginx. У дадзеным выпадку гэта нам і дапамагло выявіць праблему. 

У выніку большай часткі фэйлаў можна было б пазбегнуць пры больш скрупулёзным падыходзе да таго, што робіш. Трэба заўсёды памятаць аб законе Мэрфі: Anything that can go wrong will go wrong, і будаваць кампаненты, кіруючыся ім. 

Крыніца: habr.com

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