Saga um DNS-pakka sem vantar frá tækniaðstoð Google Cloud
Frá Google Blog Editor: Hefur þú einhvern tíma velt því fyrir þér hvernig verkfræðingar Google Cloud Technical Solutions (TSE) höndla stuðningsbeiðnir þínar? TSE tækniaðstoðarverkfræðingar eru ábyrgir fyrir því að bera kennsl á og leiðrétta uppsprettur vandamála sem notendur hafa tilkynnt um. Sum þessara vandamála eru frekar einföld, en stundum rekst þú á miða sem krefst athygli nokkurra verkfræðinga í einu. Í þessari grein mun einn starfsmanna TSE segja okkur frá einu mjög erfiðu vandamáli frá nýlegri æfingu hans - ef DNS-pakka vantar. Í þessari sögu munum við sjá hvernig verkfræðingum tókst að leysa ástandið og hvaða nýja hluti þeir lærðu á meðan þeir lagfærðu villuna. Við vonum að þessi saga fræði þig ekki aðeins um djúpstæða villu, heldur gefi þér einnig innsýn í ferlana sem fylgja því að senda inn stuðningsmiða hjá Google Cloud.
Úrræðaleit er bæði vísindi og list. Það byrjar allt á því að byggja upp tilgátu um ástæðuna fyrir óstöðluðu hegðun kerfisins, eftir það er það prófað með tilliti til styrkleika. Hins vegar, áður en við setjum fram tilgátu, verðum við að skilgreina og móta vandamálið nákvæmlega. Ef spurningin hljómar of óljós, þá verður þú að greina allt vandlega; Þetta er „listin“ við bilanaleit.
Undir Google Cloud verða slík ferli veldisvísis flóknari þar sem Google Cloud reynir sitt besta til að tryggja friðhelgi notenda sinna. Vegna þessa hafa TSE verkfræðingar hvorki aðgang til að breyta kerfum þínum né getu til að skoða stillingar eins víða og notendur gera. Þess vegna, til að prófa einhverjar tilgátur okkar, getum við (verkfræðingar) ekki breytt kerfinu fljótt.
Sumir notendur trúa því að við munum laga allt eins og vélfræði í bílaþjónustu og einfaldlega senda okkur auðkenni sýndarvélar, en í raun fer ferlið fram á samtalsformi: safna upplýsingum, móta og staðfesta (eða hrekja) tilgátur, og á endanum byggist ákvörðunarvandamál á samskiptum við viðskiptavininn.
Vandamál sem um ræðir
Í dag höfum við sögu með góðum endi. Ein af ástæðunum fyrir farsælli úrlausn fyrirhugaðs máls er mjög nákvæm og nákvæm lýsing á vandanum. Hér að neðan má sjá afrit af fyrsta miðanum (breytt til að fela trúnaðarupplýsingar):
Þessi skilaboð innihalda mikið af gagnlegum upplýsingum fyrir okkur:
Sérstakur VM tilgreindur
Vandamálið sjálft er gefið til kynna - DNS virkar ekki
Tilgreint er hvar vandamálið lýsir sér - VM og ílát
Tilgreind eru skrefin sem notandinn tók til að bera kennsl á vandamálið.
Beiðnin var skráð sem „P1: Critical Impact - Service Unusable in production“, sem þýðir stöðugt eftirlit með aðstæðum 24/7 samkvæmt „Follow the Sun“ kerfinu (þú getur lesið meira um forgangsröðun notendabeiðna), með flutningi þess frá einu tækniaðstoðarteymi til annars með hverri tímabeltisbreytingu. Reyndar, þegar vandamálið barst teymi okkar í Zürich, hafði það þegar farið hringinn um heiminn. Á þessum tíma hafði notandinn gripið til mótvægisaðgerða, en óttaðist að ástandið í framleiðslunni endurtaki sig, þar sem undirrótin hafði ekki enn fundist.
Þegar miðinn barst til Zürich höfðum við þegar eftirfarandi upplýsingar við höndina:
Innihald /etc/hosts
Innihald /etc/resolv.conf
Output iptables-save
Samsett af liðinu ngrep pcap skrá
Með þessum gögnum vorum við tilbúin að hefja „rannsókn“ og bilanaleit.
Fyrstu skrefin okkar
Í fyrsta lagi skoðuðum við annála og stöðu lýsigagnaþjónsins og tryggðum að hann virkaði rétt. Lýsigagnaþjónninn svarar IP tölunni 169.254.169.254 og sér meðal annars um að stjórna lénsheitum. Við tékkuðum líka að eldveggurinn virki rétt með VM og lokar ekki pökkum.
Þetta var einhvers konar undarlegt vandamál: nmap athugunin vísaði á bug helstu tilgátu okkar um tap á UDP pakka, svo við fundum andlega upp nokkra fleiri valkosti og leiðir til að athuga þá:
Eru pakkar sleppt vali? => Athugaðu iptables reglur
Er það ekki of lítið? MTU? => Athugaðu úttak ip a show
Hefur vandamálið aðeins áhrif á UDP pakka eða TCP líka? => Ekið í burtu dig +tcp
Er pökkum sem myndast við grafa skilað? => Ekið í burtu tcpdump
Er libdns að virka rétt? => Ekið í burtu strace til að athuga sendingu pakka í báðar áttir
Hér ákveðum við að hringja í notandann til að leysa vandamál í beinni.
Meðan á símtalinu stendur getum við athugað ýmislegt:
Eftir nokkrar athuganir útilokum við iptables reglur frá listanum yfir ástæður
Við athugum netviðmót og leiðartöflur og tvisvar hvort MTU sé rétt
Við uppgötvum það dig +tcp google.com (TCP) virkar eins og það á að gera, en dig google.com (UDP) virkar ekki
Búinn að keyra í burtu tcpdump það er enn að virka dig, komumst við að því að verið er að skila UDP pökkum
Við keyrum í burtu strace dig google.com og við sjáum hvernig grafa kallar rétt sendmsg() и recvms(), hins vegar er sú seinni rofin af tímamörkum
Því miður er lok vaktarinnar komið og við neyðumst til að auka vandamálið á næsta tímabelti. Beiðnin vakti hins vegar áhuga hjá teyminu okkar og samstarfsmaður stingur upp á því að búa til upphaflega DNS pakkann með því að nota skraufléttu Python eininguna.
from scapy.all import *
answer = sr1(IP(dst="169.254.169.254")/UDP(dport=53)/DNS(rd=1,qd=DNSQR(qname="google.com")),verbose=0)
print ("169.254.169.254", answer[DNS].summary())
Þetta brot býr til DNS pakka og sendir beiðnina til lýsigagnaþjónsins.
Notandinn keyrir kóðann, DNS svarinu er skilað og forritið fær það sem staðfestir að ekkert vandamál sé á netkerfisstigi.
Eftir aðra „heimsferð“ kemur beiðnin aftur til teymisins okkar og ég yfirfæri hana algjörlega á sjálfan mig og held að það sé þægilegra fyrir notandann ef beiðnin hættir að hringsnúast á milli staða.
Í millitíðinni samþykkir notandinn vinsamlega að leggja fram skyndimynd af kerfismyndinni. Þetta eru mjög góðar fréttir: hæfileikinn til að prófa kerfið sjálfur gerir bilanaleit mun hraðari, því ég þarf ekki lengur að biðja notandann um að keyra skipanir, senda mér niðurstöðurnar og greina þær, ég get gert allt sjálfur!
Samstarfsmenn mínir eru farnir að öfunda mig svolítið. Í hádeginu ræðum við umskiptin en enginn hefur hugmynd um hvað er í gangi. Sem betur fer hefur notandinn sjálfur þegar gert ráðstafanir til að draga úr afleiðingunum og er ekkert að flýta okkur, svo við höfum tíma til að kryfja vandamálið. Og þar sem við höfum mynd, getum við keyrt hvaða próf sem vekur áhuga okkar. Frábært!
Að taka skref til baka
Ein vinsælasta viðtalsspurningin fyrir stöður kerfisfræðinga er: „Hvað gerist þegar þú smellir www.google.com? Spurningin er frábær, þar sem umsækjandinn þarf að lýsa öllu frá skelinni til notendarýmis, til kerfiskjarnans og síðan til netsins. Ég brosi: stundum reynast viðtalsspurningar gagnlegar í raunveruleikanum...
Ég ákveð að beita þessari HR spurningu á núverandi vandamál. Í grófum dráttum, þegar þú reynir að ákvarða DNS nafn, gerist eftirfarandi:
Forritið kallar á kerfissafn eins og libdns
libdns athugar kerfisstillinguna við hvaða DNS-þjón það ætti að hafa samband (á skýringarmyndinni er þetta 169.254.169.254, lýsigagnaþjónn)
libdns notar kerfissímtöl til að búa til UDP fals (SOKET_DGRAM) og senda UDP pakka með DNS fyrirspurn í báðar áttir
Í gegnum sysctl viðmótið geturðu stillt UDP stafla á kjarnastigi
Kjarninn hefur samskipti við vélbúnaðinn til að senda pakka yfir netið í gegnum netviðmótið
Yfirvísirinn grípur og sendir pakkann til lýsigagnaþjónsins þegar hann hefur samband við hann
Lýsigagnaþjónninn, af töfrum sínum, ákvarðar DNS nafnið og skilar svari með sömu aðferð
Leyfðu mér að minna þig á hvaða tilgátur við höfum þegar íhugað:
Tilgáta: Brotin bókasöfn
Próf 1: keyrðu strace í kerfinu, athugaðu að dig kallar rétt kerfiskall
Niðurstaða: Hringt er í rétt kerfissímtöl
Próf 2: nota srapy til að athuga hvort við getum ákvarðað nöfn sem fara framhjá kerfissöfnum
Niðurstaða: við getum
Próf 3: keyrðu rpm –V á libdns pakkanum og md5sum bókasafnsskrám
Niðurstaða: bókasafnskóðinn er alveg eins og kóðinn í virka stýrikerfinu
Próf 4: festu rótarkerfismynd notandans á VM án þessarar hegðunar, keyrðu chroot, athugaðu hvort DNS virkar
Niðurstaða: DNS virkar rétt
Niðurstaða byggð á prófum: vandamálið er ekki á bókasöfnunum
Tilgáta: Það er villa í DNS stillingunum
Próf 1: athugaðu tcpdump og athugaðu hvort DNS pakkar séu sendir og skilaðir rétt eftir að grafa er keyrt
Niðurstaða: pakkar eru sendir á réttan hátt
Próf 2: tékkaðu á þjóninum /etc/nsswitch.conf и /etc/resolv.conf
Niðurstaða: allt er rétt
Niðurstaða byggð á prófum: vandamálið er ekki með DNS uppsetninguna
Tilgáta: kjarni skemmdur
Próf: settu upp nýjan kjarna, athugaðu undirskrift, endurræstu
Niðurstaða: svipuð hegðun
Niðurstaða byggð á prófum: kjarninn er ekki skemmdur
Tilgáta: röng hegðun notandanetsins (eða netviðmóts netkerfisins)
Próf 1: Athugaðu eldveggstillingarnar þínar
Niðurstaða: eldveggurinn sendir DNS pakka á bæði hýsilinn og GCP
Próf 2: stöðva umferð og fylgjast með réttmæti sendingar og skila DNS beiðna
Niðurstaða: tcpdump staðfestir að gestgjafinn hafi fengið skilapakka
Niðurstaða byggð á prófum: vandamálið er ekki í netkerfinu
Tilgáta: lýsigagnaþjónninn virkar ekki
Próf 1: athugaðu lýsigagnaþjónsskrárnar fyrir frávik
Niðurstaða: Engin frávik eru í skránni
Próf 2: Framhjá lýsigagnaþjóninum í gegnum dig @8.8.8.8
Niðurstaða: Upplausn er rofin jafnvel án þess að nota lýsigagnaþjón
Niðurstaða byggð á prófum: vandamálið er ekki með lýsigagnaþjóninum
The botn lína: við prófuðum öll undirkerfi nema runtime stillingar!
Að kafa í Kernel Runtime Settings
Til að stilla keyrsluumhverfi kjarna geturðu notað skipanalínuvalkosti (grub) eða sysctl viðmótið. Ég leit inn /etc/sysctl.conf og hugsaðu bara, ég uppgötvaði nokkrar sérsniðnar stillingar. Mér leið eins og ég hefði gripið í eitthvað, ég fleygði öllum stillingum sem ekki voru netkerfi eða ekki tcp, eftir með fjallastillingunum net.core. Síðan fór ég þangað sem hýsingarheimildirnar voru í VM og byrjaði að beita stillingunum eina í einu, hverja eftir aðra, með bilaða VM, þar til ég fann sökudólginn:
net.core.rmem_default = 2147483647
Hér er það, DNS-brjótandi stillingar! Ég fann morðvopnið. En hvers vegna er þetta að gerast? Mig vantaði samt hvata.
Grunnstærð DNS pakka biðminni er stillt í gegnum net.core.rmem_default. Dæmigert gildi er einhvers staðar í kringum 200KiB, en ef þjónninn þinn fær mikið af DNS-pökkum gætirðu viljað auka biðminni. Ef biðminni er fullur þegar nýr pakki kemur, til dæmis vegna þess að forritið er ekki að vinna úr honum nógu hratt, þá muntu byrja að tapa pökkum. Viðskiptavinur okkar jók biðminni rétt vegna þess að hann var hræddur við gagnatap, þar sem hann var að nota forrit til að safna mælingum í gegnum DNS pakka. Gildið sem hann setti var hæsta mögulega: 231-1 (ef það er stillt á 231 mun kjarninn skila „ÓVALD RÖK“).
Allt í einu áttaði ég mig á því hvers vegna nmap og scapy virkuðu rétt: þeir voru að nota hráar fals! Raw innstungur eru frábrugðnar venjulegum innstungum: þær fara framhjá iptables og þær eru ekki í biðminni!
En hvers vegna veldur „of stór buffer“ vandamál? Það virkar greinilega ekki eins og ætlað er.
Á þessum tímapunkti gæti ég endurskapað vandamálið á mörgum kjarna og mörgum dreifingum. Vandamálið birtist þegar á 3.x kjarnanum og nú birtist það líka á 5.x kjarnanum.
Reyndar við ræsingu
sysctl -w net.core.rmem_default=$((2**31-1))
DNS hætti að virka.
Ég byrjaði að leita að vinnugildum með einföldu tvíundarleitaralgrími og komst að því að kerfið virkaði með 2147481343, en þessi tala var tilgangslaust talnasett fyrir mér. Ég stakk upp á því að viðskiptavinurinn prófaði þetta númer og hann svaraði því til að kerfið virkaði með google.com, en gaf samt villu með öðrum lénum, svo ég hélt áfram rannsókn minni.
Ég er búinn að setja upp dropaúr, tól sem hefði átt að vera notað fyrr: það sýnir nákvæmlega hvar í kjarnanum pakki endar. Sökudólgurinn var hlutverkið udp_queue_rcv_skb. Ég sótti kjarnaheimildirnar og bætti við nokkrum aðgerðirprintk til að fylgjast með hvar nákvæmlega pakkinn endar. Ég fann fljótt rétta ástandið if, og starði einfaldlega á það í nokkurn tíma, því það var þá sem allt kom loksins saman í heila mynd: 231-1, merkingarlaus tala, óvirkt lén... Þetta var stykki af kóða í __udp_enqueue_schedule_skb:
if (rmem > (size + sk->sk_rcvbuf))
goto uncharge_drop;
Vinsamlegast athugið:
rmem er af gerðinni int
size er af gerðinni u16 (ómerkt sextán bita int) og geymir pakkastærðina
sk->sk_rcybuf er af gerðinni int og geymir biðminni stærð sem samkvæmt skilgreiningu er jöfn gildinu í net.core.rmem_default
Þegar sk_rcvbuf nálgast 231, samantekt pakkastærðar getur leitt til heiltölu yfirfall. Og þar sem það er int verður gildi þess neikvætt, þannig að skilyrðið verður satt þegar það ætti að vera rangt (þú getur lesið meira um þetta á tengill).
Hægt er að leiðrétta villuna á léttvægan hátt: með steypu unsigned int. Ég beitti lagfæringunni og endurræsti kerfið og DNS virkaði aftur.
Bragð af sigur
Ég sendi niðurstöður mínar til viðskiptavinarins og sendi LKML kjarnaplástur. Ég er ánægður: hvert púsl passar saman, ég get útskýrt nákvæmlega hvers vegna við fylgdumst með því sem við sáum og síðast en ekki síst, okkur tókst að finna lausn á vandamálinu þökk sé teymisvinnu okkar!
Rétt er að viðurkenna að málið reyndist sjaldgæft og sem betur fer fáum við sjaldan jafn flóknar beiðnir frá notendum.