Med vÀnliga hÀlsningar!
Jag heter Nikita, jag Àr teamledare för Cians ingenjörsteam. Ett av mina ansvarsomrÄden pÄ företaget Àr att minska antalet incidenter relaterade till infrastruktur i produktionen till noll.
Det som kommer att diskuteras nedan gav oss mycket smÀrta, och syftet med den hÀr artikeln Àr att förhindra att andra mÀnniskor upprepar vÄra misstag eller Ätminstone minimerar deras inverkan.
ingressen
För lÀnge sedan, nÀr Cian bestod av monoliter, och det inte fanns nÄgra antydan om mikrotjÀnster Ànnu, mÀtte vi tillgÀngligheten av en resurs genom att kontrollera 3-5 sidor.
De svarar - allt Ă€r bra, om de inte svarar pĂ„ lĂ€nge - varna. Hur lĂ€nge de behövde vara lediga frĂ„n jobbet för att det skulle anses vara en incident bestĂ€mdes av folk pĂ„ möten. Ett team av ingenjörer var alltid involverat i utredningen av hĂ€ndelsen. NĂ€r utredningen var klar skrev de en obduktion â en slags rapport via mejl i formatet: vad hĂ€nde, hur lĂ€nge det varade, vad vi gjorde i stunden, vad vi kommer att göra i framtiden.
Sidans huvudsidor eller hur vi förstÄr att vi har nÄtt botten
För att pÄ nÄgot sÀtt förstÄ prioriteringen av felet har vi identifierat de mest kritiska webbplatssidorna för affÀrsfunktionalitet. Med hjÀlp av dem rÀknar vi antalet lyckade/misslyckade förfrÄgningar och timeouts. SÄ hÀr mÀter vi upptid.
LÄt oss sÀga att vi fick reda pÄ att det finns ett antal superviktiga delar av webbplatsen som Àr ansvariga för huvudtjÀnsten - att söka och skicka in annonser. Om antalet förfrÄgningar som misslyckas överstiger 1 % Àr detta en kritisk incident. Om felfrekvensen inom 15 minuter under bÀsta sÀndningstid överstiger 0,1 %, anses detta ocksÄ vara en kritisk incident. Dessa kriterier tÀcker de flesta av incidenterna, resten ligger utanför ramen för denna artikel.
Topp bÀsta incidenter Cian
SÄ vi har definitivt lÀrt oss att faststÀlla det faktum att en incident intrÀffade.
Nu beskrivs varje incident i detalj och Äterspeglas i Jira-eposet. Förresten: för detta startade vi ett separat projekt, kallat det FAIL - bara epos kan skapas i det.
Om du samlar alla misslyckanden under de senaste Ären Àr ledarna:
- mssql-relaterade incidenter;
- incidenter orsakade av yttre faktorer;
- admin fel.
LÄt oss titta mer i detalj pÄ administratörers misstag, liksom nÄgra andra intressanta misslyckanden.
Femte plats - "RĂ€tta ordning i DNS"
Det var en stormig tisdag. Vi bestÀmde oss för att ÄterstÀlla ordningen i DNS-klustret.
Jag ville överföra interna DNS-servrar frÄn bind till powerdns, och tilldela helt separata servrar för detta, dÀr det inte finns nÄgot förutom DNS.
Vi placerade en DNS-server pÄ varje plats i vÄra DC:er, och ögonblicket kom att flytta zoner frÄn bind till powerdns och byta infrastrukturen till nya servrar.
Mitt under flytten, av alla servrar som specificerades i lokala cachingbindningar pÄ alla servrar, Äterstod bara en, som fanns i datacentret i St. Petersburg. Denna DC förklarades frÄn början som icke-kritisk för oss, men blev plötsligt en enda punkt av misslyckande.
Det var under denna flyttperiod som kanalen mellan Moskva och St Petersburg föll ner. Vi var faktiskt lÀmnade utan DNS i fem minuter och kom upp igen nÀr hostaren ÄtgÀrdade problemet.
Slutsatser:
Om vi ââtidigare försummade externa faktorer under förberedelserna för arbetet, finns de nu ocksĂ„ med i listan över vad vi förbereder oss för. Och nu strĂ€var vi efter att sĂ€kerstĂ€lla att alla komponenter Ă€r reserverade n-2, och under arbetets gĂ„ng kan vi sĂ€nka denna nivĂ„ till n-1.
- NÀr du gör upp en handlingsplan, markera de punkter dÀr tjÀnsten kan misslyckas och tÀnk igenom ett scenario dÀr allt gick "frÄn dÄligt till vÀrre" i förvÀg.
- Distribuera interna DNS-servrar över olika geolokaliseringar/datacenter/rack/switchar/ingÄngar.
- Installera en lokal cachande DNS-server pÄ varje server, som omdirigerar förfrÄgningar till de huvudsakliga DNS-servrarna, och om den inte Àr tillgÀnglig kommer den att svara frÄn cachen.
FjÀrde plats - "RÀtta ordning i Nginx"
En vacker dag beslutade vĂ„rt team att "vi har fĂ„tt nog av det hĂ€r", och processen med att omstrukturera nginx-konfigurationer började. HuvudmĂ„let Ă€r att fĂ„ konfigurationerna till en intuitiv struktur. Tidigare var allt "historiskt etablerat" och bar ingen logik. Nu har varje server_name flyttats till en fil med samma namn och alla konfigurationer har distribuerats till mappar. Konfigurationen innehĂ„ller förresten 253949 rader eller 7836520 tecken och tar upp nĂ€stan 7 megabyte. Ăversta strukturnivĂ„:
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.conf
Det blev mycket bÀttre, men i processen med att döpa om och distribuera konfigurationer hade nÄgra av dem fel tillÀgg och inkluderades inte i include *.conf-direktivet. Som ett resultat blev vissa vÀrdar otillgÀngliga och returnerade 301 till huvudsidan. PÄ grund av att svarskoden inte var 5xx/4xx mÀrktes detta inte direkt utan först pÄ morgonen. Efter det började vi skriva tester för att kontrollera infrastrukturkomponenter.
Slutsatser:
- Strukturera dina konfigurationer korrekt (inte bara nginx) och tÀnk igenom strukturen i ett tidigt skede av projektet. PÄ sÄ sÀtt kommer du att göra dem mer förstÄeliga för teamet, vilket i sin tur kommer att minska TTM.
- Skriv tester för vissa infrastrukturkomponenter. Till exempel: kontrollera att alla nyckelservernamn ger korrekt status + svarstext. Det rÀcker med att bara ha nÄgra skript till hands som kontrollerar komponentens grundlÀggande funktioner, för att inte frenetiskt komma ihÄg klockan 3 vad mer som behöver kontrolleras.
Tredje plats - "Plötsligt fick utrymme i Cassandra"
Data vÀxte stadigt och allt var bra tills det ögonblick dÄ reparationen av stora utrymmen började misslyckas i Cassandra-klustret, eftersom komprimering inte kunde fungera pÄ dem.
En stormig dag förvandlades klungan nÀstan till en pumpa, nÀmligen:
- det fanns cirka 20 % av det totala utrymmet kvar i klustret;
- Det Àr omöjligt att lÀgga till noder helt, eftersom rensningen inte gÄr igenom efter att en nod lagts till pÄ grund av brist pÄ utrymme pÄ partitionerna;
- produktiviteten sjunker gradvis eftersom packning inte fungerar;
- Klustret Àr i nödlÀge.
Avsluta - vi lade till ytterligare 5 noder utan rensning, varefter vi började systematiskt ta bort dem frÄn klustret och gÄ in i dem igen, som tomma noder som hade slut pÄ utrymme. Det gick Ät mycket mer tid Àn vi skulle önska. Det fanns en risk för att klustret helt eller delvis skulle vara otillgÀngligt.
Slutsatser:
- PÄ alla cassandra-servrar bör inte mer Àn 60 % av utrymmet pÄ varje partition vara upptaget.
- De bör laddas med högst 50 % cpu.
- Du bör inte glömma kapacitetsplaneringen och behöver tÀnka igenom den för varje komponent, baserat pÄ dess specifika egenskaper.
- Ju fler noder i klustret, desto bÀttre. Servrar som innehÄller en liten mÀngd data överbelastas snabbare, och ett sÄdant kluster Àr lÀttare att Äteruppliva.
Andra plats - "Data försvann frÄn konsuls nyckel-vÀrdelagring"
För tjÀnsteupptÀckt anvÀnder vi, som mÄnga, konsul. Men vi anvÀnder ocksÄ dess nyckel-vÀrde för blÄgrön layout av monoliten. Den lagrar information om aktiva och inaktiva uppströms, som byter plats under driftsÀttning. För detta ÀndamÄl skrevs en driftsÀttningstjÀnst som samverkade med KV. Vid nÄgot tillfÀlle försvann uppgifterna frÄn KV. à terstÀlld frÄn minnet, men med ett antal fel. Som ett resultat, under uppladdningen, fördelades belastningen pÄ uppströmsströmmarna ojÀmnt, och vi fick mÄnga 502-fel pÄ grund av att backends var överbelastade pÄ CPU:n. Som ett resultat av detta flyttade vi frÄn konsul KV till postgres, varifrÄn det inte lÀngre Àr sÄ lÀtt att ta bort dem.
Slutsatser:
- TjÀnster utan tillstÄnd bör inte innehÄlla data som Àr kritiska för driften av webbplatsen. Till exempel, om du inte har behörighet i ES, skulle det vara bÀttre att neka Ätkomst pÄ nÀtverksnivÄ överallt dÀr det inte behövs, lÀmna bara de nödvÀndiga, och Àven stÀlla in action.destructive_requires_name: true.
- Ăva pĂ„ sĂ€kerhetskopierings- och Ă„terstĂ€llningsmekanismen i förvĂ€g. Gör till exempel ett skript i förvĂ€g (till exempel i python) som kan sĂ€kerhetskopiera och Ă„terstĂ€lla.
Första plats - "Captain Unobvious"
Vid nÄgot tillfÀlle mÀrkte vi en ojÀmn fördelning av belastningen pÄ nginx uppströms i fall dÀr det fanns 10+ servrar i backend. PÄ grund av det faktum att round-robin skickade förfrÄgningar frÄn 1:a till sista uppströms i ordning, och varje nginx-reload började om, fick de första uppströmsarna alltid fler förfrÄgningar Àn resten, vilket ledde till att de arbetade lÄngsammare och hela sajten led. Detta blev allt mer mÀrkbart i takt med att trafikmÀngden ökade. Att bara uppdatera nginx för att aktivera slumpmÀssigt fungerade inte - vi mÄste göra om ett gÀng lua-kod som inte tog fart pÄ version 1.15 (vid det ögonblicket). Vi var tvungna att patcha vÄr nginx 1.14.2 och introducerade slumpmÀssigt stöd i den. Detta löste problemet. Denna bugg vinner kategorin "Kapten Non-Obviousness".
Slutsatser:
Det var vÀldigt intressant och spÀnnande att utforska denna bugg).
- Organisera din övervakning sÄ att den hjÀlper dig att snabbt hitta sÄdana fluktuationer. Till exempel kan du anvÀnda ELK för att övervaka rps pÄ varje backend av varje uppströms, övervaka deras svarstid frÄn nginx synvinkel. I det hÀr fallet hjÀlpte detta oss att identifiera problemet.
Som ett resultat kunde de flesta av misslyckandena ha undvikits med en mer noggrann instÀllning till vad du gjorde. Vi mÄste alltid komma ihÄg Murphys lag: Allt som kan gÄ fel kommer att gÄ fel, och bygga komponenter baserat pÄ det.
KĂ€lla: will.com