
Goddag alle!Â
Mit navn er Nikita, jeg er teamleder for ingeniĂžrteamet hos Cian. En af mine opgaver i virksomheden er at reducere antallet af hĂŠndelser relateret til infrastrukturen i produktionen til nul.
Det, vi vil tale om nedenfor, har forĂ„rsaget os meget smerte, og formĂ„let med denne artikel er at forhindre andre i at gentage vores fejl eller i hvert fald minimere deres indflydelse.Â
PrĂŠambel
For lĂŠnge siden, da Cian bestod af monolitter, og der slet ikke var nogen tegn pĂ„ mikrotjenester, mĂ„lte vi tilgĂŠngeligheden af ressourcen ved at tjekke 3â5 sider.Â
Hvis de svarede â alt var godt, hvis de ikke svarede i lang tid â alert. Hvor lang tid de skulle vĂŠre nede for at blive betragtet som en hĂŠndelse, blev besluttet af folk pĂ„ mĂžder. IngeniĂžrteamet deltager altid i efterforskningen af hĂŠndelsen. NĂ„r undersĂžgelsen er afsluttet, skrives en postmortem â en slags rapport pĂ„ e-mail i formatet: hvad der skete, hvor lĂŠnge det varede, hvad vi gjorde i Ăžjeblikket, hvad vi vil gĂžre i fremtiden.Â
Hovedsiderne pÄ hjemmesiden eller hvordan vi ved, at vi har ramt bunden
Â
For at kunne forstĂ„ prioriteten af fejlen, har vi fremhĂŠvet de mest kritiske sider for forretningsfunktionen. Ud fra dem tĂŠller vi antallet af succesfulde/ikke-succesfulde anmodninger og timeouts. PĂ„ den mĂ„de mĂ„ler vi uptime.Â
Lad os sige, at vi har fastslĂ„et, at der er en rĂŠkke supervigtige sektioner af hjemmesiden, der er ansvarlige for den primĂŠre service â sĂžgning og indsendelse af annoncer. Hvis antallet af anmodninger, der afsluttes med en fejl, overstiger 1%, er det en kritisk hĂŠndelse. Hvis procentdelen af fejl under primetime overstiger 0,1% i lĂžbet af 15 minutter, betragtes dette ogsĂ„ som en kritisk hĂŠndelse. Disse kriterier dĂŠkker stĂžrstedelen af hĂŠndelserne, Ăžvrige falder uden for denne artikel.

Top bedste hĂŠndelser fra Cian
SĂ„ vi har helt sikkert lĂŠrt at bestemme, hvornĂ„r en hĂŠndelse er sket.Â
Nu er hver hĂŠndelse detaljeret beskrevet og reflekteret i en epik i Jira. For at sige det sĂ„dan: vi har startet et separat projekt, kaldte det FAIL â her kan man kun oprette epikker.Â
Hvis vi samler alle fejlene fra de seneste Ă„r, er de dominerende:Â
- hĂŠndelser relateret til mssql;
- hÊndelser forÄrsaget af eksterne faktorer;
- administratorfejl.
Lad os se nÊrmere pÄ administratorfejl samt nogle andre interessante fiaskoer.
Femte plads â "Vi organiserer DNS"
Det var en grĂ„ tirsdag. Vi besluttede at organisere DNS-klyngen.Â
Vi Ăžnskede at migrere interne dns-servere fra bind til powerdns, ved at dedikere fuldstĂŠndig separate servere, hvor der ikke er andet end dns.Â
Vi placerede en dns-server i hver af vores datacenters lokationer, og nu var tiden kommet til at migrere zoner fra bind til powerdns og skifte infrastrukturen til de nye servere.Â
I den mest hektiske periode af migreringen var der kun én tilbage servere, som var angivet i de lokale cache-bind pÄ alle servere, og den var i datacentret i Sankt Petersborg. Dette datacenter var oprindeligt blevet deklareret som ikke-kritisk for os, men blev pludselig et single point of failure.
Lige i denne migrationsperiode gik forbindelsen mellem Moskva og Sankt Petersborg ned. Vi var faktisk uden DNS i fem minutter og kom op igen, da hoster fejlen blev rettet.Â
Konklusioner:
Tidligere havde vi overset eksterne faktorer under forberedelserne til arbejdet, men nu medtager vi dem ogsÄ pÄ listen over, hvad vi forbereder os pÄ. Og nu strÊber vi efter, at alle komponenter er reserveret til n-2, og at vi under arbejdet kan sÊnke dette niveau til n-1.
- NÄr du laver handlingsplanen, skal du notere punkter, hvor tjenesten kan falde, og tÊnke pÄ scenarier, hvor alt gÄr "vÊrre end vÊrst", pÄ forhÄnd.
- Fordel interne dns-servere pÄ forskellige geolokationer/datacentre/rack/switches/indgange.
- Installer en lokal cache dns-server pĂ„ hver server, som omdirigerer forespĂžrgsler til de primĂŠre dns-servere, og i tilfĂŠlde af utilgĂŠngelighed vil svare fra cachen.Â
Fjerde plads â "Vi organiserer Nginx"
En skĂžn dag besluttede vores team, at "nu er det nok", og processen med at refaktorere nginx-konfigurationerne blev ivĂŠrksat. HovedmĂ„let er at give konfigurationerne en intuitiv struktur. Tidligere var alt "historisk opstĂ„et" og havde ingen logik i sig. Nu har vi flyttet hver server_name til en tilsvarende fil og kategoriseret alle konfigurationer i mapper. For at sige det mildt â konfigurationen indeholder 253949 linjer eller 7836520 tegn og fylder nĂŠsten 7 megabyte. Ăverste niveau af strukturen:Â
Nginx-struktur
âââ adgang
â Â âââ 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 blev markant bedre, men under omdĂžbning og fordeling af konfigurationer havde nogle af dem forkerte filendelser og kom ikke ind i direktivet include *.conf. Som fĂžlge heraf blev nogle hosts utilgĂŠngelige og returnerede 301 til forsiden. Fordi svarkoden ikke var 5xx/4xx, blev det ikke opdaget med det samme, men fĂžrst tidligt om morgenen. Derefter begyndte vi at skrive tests til kontrol af infrastrukturkomponenterne.
Konklusioner:Â
- Strukturer konfigurationerne korrekt (ikke kun nginx) og overvej strukturen tidligt i projektet. Det vil gÞre dem mere forstÄelige for teamet, hvilket i sin tur vil reducere TTM.
- Skriv tests for nogle infrastrukturkomponenter. For eksempel: kontrol, at alle nĂžgle server_name returnerer den korrekte status, + svarindholdet. Det er tilstrĂŠkkeligt at have bare et par scripts, der kontrollerer de grundlĂŠggende funktioner af komponenten, sĂ„ man ikke nervĂžst skal huske, hvad man ellers skal tjekke klokken 3 om natten.Â
Tredje plads â "Pludselig var der ikke mere plads i Cassandra"
Dataene voksede stĂžt, og alt var fint, indtil klustret Cassandra begyndte at fejle ved reparation af store keyspaces, fordi det ikke kunne gennemfĂžre compaction.Â
PĂ„ en dyster dag nĂŠsten forvandlede klustret sig til et grĂŠskar, nemlig:
- der var ca. 20% plads tilbage i hele klustret;
- det var ikke muligt at tilfÞje noder ordentligt, fordi cleanup ikke kunne gennemfÞres efter tilfÞjelsen af en node pÄ grund af pladsmangel pÄ partitionerne;
- ydelsen falder lidt, fordi compaction ikke virker;Â
- klustret kĂžrer i nĂždtilstand.

Udgangen â vi har tilfĂžjet fem ekstra noder uden cleanup, hvorefter vi begyndte systematisk at fjerne dem fra klyngen og genindsĂŠtte dem som tomme noder, hvor der ikke var plads tilbage. Tiden brugt hertil har vĂŠret betydeligt mere, end vi Ăžnskede. Der var en risiko for delvis eller total utilgĂŠngelighed af klyngen.Â
Konklusioner:
- PĂ„ alle servere mĂ„ cassandra ikke have mere end 60% af pladsen optaget i hver partition.Â
- De mÄ ikke vÊre mere end 50% belastet pÄ CPU.
- Man bĂžr ikke overse kapacitetsplanlĂŠgning, og det skal overvejes for hver komponent ud fra dens specifikation.
- Jo flere noder i klyngen, desto bedre. Servere med smĂ„ datamĂŠngder genopretter hurtigere, og en sĂ„dan klynge er lettere at genoplive.Â
Andet sted â «Data forsvandt fra consul key-value storage»
Til service discovery bruger vi, ligesom mange, consul. Men vi bruger ogsĂ„ dens key-value til blue-green deployment af monoliten. Her opbevares oplysninger om aktive og inaktive upstreams, som udskiftes under deployment. Der blev skrevet en deploy-service, som interagerede med KV. PĂ„ et tidspunkt forsvandt dataene fra KV. Vi genskabte det fra hukommelsen, men med en rĂŠkke fejl. Som fĂžlge heraf blev belastningen pĂ„ upstreams ikke fordelt jĂŠvnt under deployment, og vi fik mange 502-fejl pĂ„ grund af overbelastning af backendene pĂ„ CPU. I sidste ende flyttede vi fra consul KV til postgres, hvorfra det ikke er sĂ„ nemt at slette dem. Â
Konklusioner:
- Tjenester uden nogen form for autentifikation mĂ„ ikke indeholde kritiske data, der er nĂždvendige for webstedets funktion. For eksempel, hvis du ikke har autentifikation i ES â er det bedst at forhindre adgang pĂ„ netvĂŠrksniveau fra alle steder, hvor det ikke er nĂždvendigt, kun lade de nĂždvendige vĂŠre, samt at gĂžre action.destructive_requires_name: true.
- Arbejd med mekanismen for backup og genopretning pÄ forhÄnd. For eksempel, lav et script (for eksempel pÄ python), der kan bÄde tage backup og genoprette.
FĂžrste sted â «Kaptajn Ă„benbarhed»Â
PĂ„ et tidspunkt bemĂŠrkede vi en ujĂŠvn fordeling af belastningen pĂ„ nginx upstreams, nĂ„r der var 10+ servere i backend. Da round-robin dirigerede anmodninger fra den fĂžrste til den sidste upstream i rĂŠkkefĂžlge, og hver genstart af nginx startede forfra, fik de fĂžrste upstreams altid flere anmodninger end de andre. Som fĂžlge heraf arbejdede de langsommere, hvilket pĂ„virkede hele hjemmesiden. Dette blev stadig mere tydeligt i takt med, at trafikmĂŠngden steg. At opdatere nginx for at inkludere random lĂžste ikke problemet â vi skulle genarbejde en masse lua-kode, der ikke fungerede pĂ„ version 1.15 (pĂ„ det tidspunkt). Vi endte med at patch vores nginx 1.14.2 og indfĂžre understĂžttelse af random. Dette lĂžste problemet. Denne fejl vinder prisen for 'kaptejn uvidenhed'.
Konklusioner:
Det var meget interessant og spĂŠndende at undersĂžge denne fejl).Â
- Organiser overvĂ„gningen, sĂ„ den hurtigt hjĂŠlper med at finde sĂ„danne flingeringer. For eksempel kan man bruge ELK til at overvĂ„ge rps pĂ„ hver backend af hver upstream og fĂžlge deres svartider set fra nginx. I dette tilfĂŠlde hjalp det os med at identificere problemet.Â
De fleste fejl kunne vĂŠre undgĂ„et med en mere omhyggelig tilgang til det, man laver. Man skal altid huske pĂ„ Murphys lov: Anything that can go wrong will go wrong, og bygge komponenterne med det i mente.Â
Kilde: habr.com
