
Alla gott!Â
Jag heter Nikita och Àr teamledare för ingenjörerna pÄ Cian. En av mina uppgifter i företaget Àr att minska antalet incidenter relaterade till infrastrukturen i produktion till noll.
Det som kommer att diskuteras hĂ€r har orsakat oss mycket smĂ€rta, och mĂ„let med denna artikel Ă€r att förhindra andra frĂ„n att upprepa vĂ„ra misstag eller Ă„tminstone minimera deras pĂ„verkan.Â
Inledning
LĂ€nge sedan, nĂ€r Cian bestod av monoliter och det inte fanns nĂ„gra indikationer pĂ„ mikrotjĂ€nster, mĂ€tte vi tillgĂ€ngligheten av resurser genom att kontrollera 3â5 sidor.Â
Svarar de â allt Ă€r bra, svarar de inte under en lĂ€ngre tid â alarm. Hur lĂ€nge de ska vara nere för att det ska rĂ€knas som en incident avgjordes av folk pĂ„ möten. Ingenjörsteamet deltog alltid i utredningen av incidenten. NĂ€r utredningen var klar skrev vi en postmortem â en slags rapport som skickades via e-post i formatet: vad som hĂ€nde, hur lĂ€nge det varade, vad man gjorde i stunden, vad vi kommer att göra i framtiden.Â
Huvudsidorna pÄ webbplatsen eller hur vi vet att vi har nÄtt botten
Â
För att kunna förstĂ„ prioriteten av fel har vi identifierat de mest kritiska sidorna för affĂ€rsfunktionaliteten pĂ„ webbplatsen. Genom dem rĂ€knar vi antalet lyckade/olyckade förfrĂ„gningar och tidsöverskridanden. PĂ„ sĂ„ sĂ€tt mĂ€ter vi uptime.Â
Anta att vi har kommit fram till att det finns ett antal superviktiga delar av webbplatsen som ansvarar för huvudservicen â sökning och publicering av annonser. Om antalet förfrĂ„gningar som avslutades med ett fel överstiger 1% â Ă€r det en kritisk incident. Om felprocenten under 15 minuter i primetime överstiger 0,1% â dĂ„ rĂ€knas det ocksĂ„ som en kritisk incident. Dessa kriterier tĂ€cker merparten av incidenterna, medan andra ligger utanför ramen för denna artikel.

Topp bÀsta incidenterna pÄ Cian
SĂ„ vi har definitivt lĂ€rt oss att identifiera nĂ€r en incident har intrĂ€ffat.Â
Nu Ă€r varje incident detaljerat beskriven och Ă„terspeglas i en epic i Jira. För övrigt: för detta har vi skapat ett separat projekt, som vi kallade FAIL â dĂ€r man endast kan skapa epics.Â
Om man samlar alla misslyckanden frĂ„n de senaste Ă„ren, sĂ„ ligger följande i topp:Â
- incidenter relaterade till mssql;
- incidenter orsakade av externa faktorer;
- adminfel.
Vi kommer att stanna vid adminfelen mer i detalj, samt nÄgra andra intressanta misslyckanden.
Femte plats â "Vi ordnar upp i DNS"
Det var en ruggig tisdag. Vi bestĂ€mde oss för att organisera DNS-klustret.Â
Vi ville migrera interna DNS-servrar frĂ„n bind till powerdns, och avsatte helt separata servrar för detta, dĂ€r det endast fanns DNS.Â
Vi placerade en DNS-server i varje plats i vĂ„ra datacenter, och nu kom stunden att flytta zonerna frĂ„n bind till powerdns och byta infrastrukturen till de nya servrarna.Â
I den mest intensiva fasen av flytten, servrar, som som angivits i lokala cachande bind-servrar pÄ alla servrar, Äterstod bara en, som lÄg i datacentret i Sankt Petersburg. Detta datacenter hade frÄn början deklarerats som icke-kritiskt för oss, men blev plötsligt en single point of failure.
Just under denna flytt kraschade kanalen mellan Moskva och Sankt Petersburg. Vi befann oss faktiskt utan DNS i fem minuter och Ă„terhĂ€mtade oss nĂ€r hostingleverantören problemen Ă„tgĂ€rdades.Â
Slutsatser:
Tidigare har vi Äsidosatt externa faktorer nÀr vi förberett oss för arbetet, men nu har vi Àven inkluderat dem i listan över vad vi förbereder oss pÄ. Och nu strÀvar vi efter att alla komponenter Àr reservdelar n-2, och under arbetets gÄng kan vi sÀnka denna nivÄ till n-1.
- Under upprÀttandet av handlingsplanen, markera punkter dÀr tjÀnsten kan falla och tÀnk igenom scenarier dÀr allt gÄr "fruktansvÀrt fel" i förvÀg.
- Distribuera interna DNS-servrar över olika geolokationer/datacenter/stÀll/omkopplare/inmatningar.
- Installera en lokal cachande DNS-server pĂ„ varje server, som omdirigerar förfrĂ„gningar till de primĂ€ra DNS-servrarna, och i hĂ€ndelse av att den inte Ă€r tillgĂ€nglig kommer den att svara frĂ„n cachen.Â
FjĂ€rde plats â "Ordning i Nginx"
En vacker dag bestĂ€mde vĂ„rt team att "det Ă€r nog nu", och processen för refaktorering av nginx-konfigurationerna startade. HuvudmĂ„let var att ge konfigurationerna en intuitivt begriplig struktur. Tidigare var allt "historiskt betingat" och bar ingen logik. Nu har vi flyttat varje server_name till en namngiven fil och sorterat alla konfigurationer i mappar. För övrigt innehĂ„ller konfigurationen 253949 rader eller 7836520 tecken och Ă€r nĂ€stan 7 megabyte stor. Den övergripande strukturens nivĂ„:Â
Nginx-struktur
âââ 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.confDet har blivit betydligt bĂ€ttre, men under omdöpning och fördelning av konfigar fick en del av dem fel filĂ€ndelse och kom inte med i direktivet include *.conf. Som en följd av detta blev vissa vĂ€rdar otillgĂ€ngliga och Ă„tergav 301 till startsidan. Eftersom svarskoden inte var 5xx/4xx, mĂ€rkte vi det inte genast, utan först pĂ„ morgonen. Efter detta började vi skriva tester för att kontrollera infrastrukturkomponenter.
Slutsatser:Â
- Strukturera konfigurationerna korrekt (inte bara nginx) och tÀnk igenom strukturen i ett tidigt skede av projektet. PÄ sÄ sÀtt gör du dem mer begripliga för teamet, vilket i sin tur minskar TTM.
- Skriv tester för vissa infrastrukturkomponenter. Till exempel: kontrollera att alla viktiga server_name ger rĂ€tt status, + svarstext. Det rĂ€cker att ha bara nĂ„gra skript till hands som kontrollerar de grundlĂ€ggande funktionerna i komponenten, sĂ„ att du inte panikartat ska försöka komma ihĂ„g vad mer som behöver kontrolleras mitt i natten.Â
Tredje plats â "Plötsligt tog det slut pĂ„ utrymme i Cassandra"
Data vĂ€xte stadigt, och allt gick bra tills det ögonblick dĂ„ reparationen av stora keyspaces i Cassandra-klustret började misslyckas, eftersom de inte kan genomföra kompaktion.Â
En blödig dag nÀstan förvandlades klustret till en pumpa, nÀmligen:
- det Äterstod cirka 20% totalt i klustret;
- det gÄr inte att helt lÀgga till noder, eftersom cleanup inte genomförs efter att noder lagts till pÄ grund av brist pÄ utrymme pÄ partitionerna;
- prestandan faller försiktigt, eftersom kompaktionen inte fungerar;Â
- klustret arbetar i nödlÀge.

UttrĂ€de â vi har lagt till ytterligare 5 noder utan rensning, efter vilket vi började systematiskt ta bort frĂ„n klustret och sedan Ă„terinföra, som tomma noder, dĂ€r det inte fanns nĂ„got utrymme kvar. Tiden som lagts ner har varit betydligt mer Ă€n vi hade önskat. Det fanns en risk för delvis eller fullstĂ€ndig otillgĂ€nglighet av klustret.Â
Slutsatser:
- PĂ„ alla servrar med Cassandra bör högst 60% av utrymmet vara anvĂ€nt pĂ„ varje partition.Â
- De bör vara belastade till högst 50% av CPU.
- Man bör inte bortse frÄn kapacitetsplanering och det mÄste övervÀgas för varje komponent beroende pÄ dess specifika behov.
- Ju fler noder i klustret, desto bĂ€ttre. Servrar som innehĂ„ller en liten mĂ€ngd data fĂ„r snabbare omstart, och ett sĂ„dant kluster Ă€r lĂ€ttare att Ă„terstĂ€lla.Â
Andra plats â 'Data försvann frĂ„n consul key-value storage'
För tjĂ€nsteupptĂ€ckten anvĂ€nder vi, precis som mĂ„nga andra, Consul. Men vi anvĂ€nder Ă€ven dess key-value för blue-green deployment av monoliten. DĂ€r lagras information om aktiva och inaktiva upstreams, som byter plats under deployment. För detta har en deploymenttjĂ€nst skrivits som interagerade med KV. Vid nĂ„got tillfĂ€lle försvann data frĂ„n KV. Vi Ă„terstĂ€llde det frĂ„n minnet, men med vissa fel. Som en följd av detta blev belastningen pĂ„ upstreams ojĂ€mt fördelad under distributionen, och vi fick mĂ„nga 502-fel pĂ„ grund av överbelastning av backend-maskinerna pĂ„ CPU. I slutĂ€ndan flyttade vi frĂ„n Consul KV till Postgres, dĂ€rifrĂ„n Ă€r det inte sĂ„ lĂ€tt att ta bort dem. Â
Slutsatser:
- TjĂ€nster utan nĂ„gon form av autentisering bör inte innehĂ„lla kritiska uppgifter för webbplatsens funktion. Till exempel, om du inte har autentisering i ES â skulle det vara bĂ€st att förbjuda Ă„tkomst pĂ„ nĂ€tverksnivĂ„ frĂ„n alla platser dĂ€r det inte behövs, lĂ€mna endast de nödvĂ€ndiga och dessutom göra action.destructive_requires_name: true.
- Ăva pĂ„ mekanismen för sĂ€kerhetskopiering och Ă„terstĂ€llning i förvĂ€g. Till exempel, skapa ett skript (till exempel pĂ„ Python) som kan bĂ„de sĂ€kerhetskopiera och Ă„terstĂ€lla.
Första plats â 'Kapten Otydlighet'Â
Vid nĂ„got tillfĂ€lle mĂ€rkte vi en ojĂ€mn belastning pĂ„ nginx upstreams nĂ€r det fanns fler Ă€n 10 servrar i backend. Eftersom round-robin dirigerade förfrĂ„gningar frĂ„n den första till den sista upstream i ordning, och varje reload av nginx började frĂ„n början, fick de första upstreams alltid fler förfrĂ„gningar Ă€n de andra. Som ett resultat arbetade de lĂ„ngsammare och hela webbplatsen drabbades. Detta blev allt mer pĂ„tagligt i takt med att trafiken ökade. Att bara uppdatera nginx för att inkludera random fungerade inte â vi var tvungna att göra om en massa lua-kod som inte gick att anvĂ€nda i version 1.15 (vid den tidpunkten). Vi var tvungna att patcha vĂ„r nginx 1.14.2 och införa stöd för random. Detta löste problemet. Denna bugg vinner i kategorin 'kapten uppenbarhet'.
Slutsatser:
Det var mycket intressant och spĂ€nnande att undersöka denna bugg).Â
- Bygg en övervakning som hjĂ€lper till att snabbt upptĂ€cka liknande fluktuationer. Till exempel kan man anvĂ€nda ELK för att övervaka rps för varje backend av varje upstream, och följa deras svarstider ur nginx:s perspektiv. I det hĂ€r fallet hjĂ€lpte det oss att identifiera problemet.Â
De flesta av felen kunde ha undvikits med en mer noggrann instĂ€llning till det man gör. Man mĂ„ste alltid komma ihĂ„g Murphys lag: Anything that can go wrong will go wrong, och bygga komponenter med den i Ă„tanke.Â
KĂ€lla: habr.com
