Google Cloud техникалық қолдауынан DNS пакеттерінің жоқтығы туралы әңгіме

Google блог редакторынан: Google Cloud Technical Solutions (TSE) инженерлері қолдау сұрауларыңызды қалай өңдейтінін ойлап көрдіңіз бе? TSE техникалық қолдау инженерлері пайдаланушы хабарлаған ақаулық көздерін анықтауға және түзетуге жауапты. Бұл мәселелердің кейбірі өте қарапайым, бірақ кейде сіз бірден бірнеше инженердің назарын қажет ететін билетті кездестіресіз. Бұл мақалада TSE қызметкерлерінің бірі өзінің соңғы тәжірибесінен өте күрделі мәселе туралы айтып береді - DNS пакеттерінің жетіспеу жағдайы. Бұл әңгімеде біз инженерлер жағдайды қалай шеше алғанын және қатені түзету кезінде қандай жаңа нәрселерді үйренгенін көреміз. Бұл оқиға сізді терең қате туралы хабардар етіп қана қоймайды, сонымен қатар Google Cloud арқылы қолдау билетін толтыру процестері туралы түсінік береді деп үміттенеміз.

Google Cloud техникалық қолдауынан DNS пакеттерінің жоқтығы туралы әңгіме

Ақаулықтарды жою ғылым да, өнер де. Мұның бәрі жүйенің стандартты емес мінез-құлқының себебі туралы гипотеза құрудан басталады, содан кейін оның күші тексеріледі. Дегенмен, гипотезаны тұжырымдамас бұрын, мәселені нақты анықтап, нақты тұжырымдауымыз керек. Егер сұрақ тым түсініксіз болып көрінсе, онда бәрін мұқият талдауға тура келеді; Бұл ақауларды жоюдың «өнері».

Google Cloud астында мұндай процестер экспоненциалды түрде күрделене түседі, өйткені Google Cloud өз пайдаланушыларының құпиялылығына кепілдік беруге бар күшін салады. Осыған байланысты TSE инженерлерінің жүйелеріңізді өңдеуге рұқсаты жоқ, не конфигурацияларды пайдаланушылар сияқты кеңірек қарау мүмкіндігі жоқ. Сондықтан кез келген гипотезаны тексеру үшін біз (инженерлер) жүйені жылдам өзгерте алмаймыз.

Кейбір пайдаланушылар біз автокөлік қызметіндегі механика сияқты барлығын түзетеміз деп сенеді және бізге виртуалды машинаның идентификаторын жібереміз, ал шын мәнінде бұл процесс сөйлесу форматында өтеді: ақпарат жинау, гипотезаларды қалыптастыру және растау (немесе жоққа шығару), және, сайып келгенде, шешім қабылдау мәселелері клиентпен қарым-қатынасқа негізделген.

Қарастырылып отырған мәселе

Бүгін бізде жақсы аяқталатын оқиға бар. Ұсынылған істің сәтті шешілу себептерінің бірі - мәселенің өте егжей-тегжейлі және нақты сипатталуы. Төменде сіз бірінші билеттің көшірмесін көре аласыз (құпия ақпаратты жасыру үшін өңделген):
Google Cloud техникалық қолдауынан DNS пакеттерінің жоқтығы туралы әңгіме
Бұл хабарламада біз үшін көптеген пайдалы ақпарат бар:

  • Арнайы VM көрсетілген
  • Мәселенің өзі көрсетілген - DNS жұмыс істемейді
  • Мәселе қай жерде көрінетіні көрсетіледі - VM және контейнер
  • Мәселені анықтау үшін пайдаланушы жасаған қадамдар көрсетілген.

Сұраныс «P1: Критикалық әсер - өндірісте пайдалануға жарамсыз қызмет» ретінде тіркелді, бұл «Күнге еру» схемасы бойынша тәулік бойы жағдайды тұрақты бақылауды білдіреді (бұл туралы толығырақ оқуға болады). пайдаланушы сұраныстарының басымдықтары), әр уақыт белдеуі ауысқан сайын оны бір техникалық қолдау тобынан екіншісіне ауыстыру арқылы. Шындығында, мәселе Цюрихтегі біздің командаға жеткенше, ол жер шарын айналып үлгерді. Осы уақытқа дейін пайдаланушы жеңілдету шараларын қабылдады, бірақ өндірістегі жағдайдың қайталануынан қорықты, себебі түпкі себеп әлі ашылмаған.

Билет Цюрихке жеткенде бізде келесі ақпарат болды:

  • Мазмұны /etc/hosts
  • Мазмұны /etc/resolv.conf
  • қорытынды iptables-save
  • Команда жинаған ngrep pcap файлы

Осы деректермен біз «тергеу» және ақауларды жою кезеңін бастауға дайын болдық.

Біздің алғашқы қадамдарымыз

Ең алдымен, біз метадеректер серверінің журналдары мен күйін тексеріп, оның дұрыс жұмыс істеп тұрғанына көз жеткіздік. Метадеректер сервері 169.254.169.254 IP мекенжайына жауап береді және басқалармен қатар домен атауларын басқаруға жауапты. Біз сондай-ақ брандмауэрдің VM-мен дұрыс жұмыс істейтінін және пакеттерді блоктамайтынын екі рет тексердік.

Бұл біртүрлі мәселе болды: nmap тексеруі UDP пакеттерін жоғалту туралы негізгі гипотезаны жоққа шығарды, сондықтан біз ойша тағы бірнеше нұсқалар мен оларды тексеру жолдарын ойлап таптық:

  • Пакеттерді таңдап тастайды ма? => iptables ережелерін тексеріңіз
  • Тым кішкентай емес пе? МТУ? => Шығаруды тексеріңіз ip a show
  • Мәселе тек UDP пакеттеріне немесе TCP-ге де әсер ете ме? => Кетіңіз dig +tcp
  • Dig генерацияланған пакеттер қайтарылды ма? => Кетіңіз tcpdump
  • libdns дұрыс жұмыс істей ме? => Кетіңіз strace екі бағытта пакеттердің берілуін тексеру

Мұнда ақаулықтарды жою үшін пайдаланушыны тікелей эфирде шақыруды шештік.

Қоңырау кезінде біз бірнеше нәрсені тексере аламыз:

  • Бірнеше тексеруден кейін біз iptables ережелерін себептер тізімінен шығарамыз
  • Біз желілік интерфейстерді және маршруттау кестелерін тексереміз және MTU дұрыстығын екі рет тексереміз
  • Біз мұны ашамыз dig +tcp google.com (TCP) қажетінше жұмыс істейді, бірақ dig google.com (UDP) жұмыс істемейді
  • Айдап кетіп tcpdump ол әлі жұмыс істейді dig, біз UDP пакеттерінің қайтарылып жатқанын анықтаймыз
  • Біз айдаймыз strace dig google.com және біз қазудың қалай дұрыс шақырылғанын көреміз sendmsg() и recvms(), бірақ екіншісі күту уақытымен үзіледі

Өкінішке орай, ауысымның соңы келді және біз мәселені келесі уақыт белдеуіне көшіруге мәжбүрміз. Сұраныс, алайда, біздің команданың қызығушылығын тудырды және әріптесіміз Scrapy Python модулін пайдаланып бастапқы DNS пакетін жасауды ұсынады.

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())

Бұл фрагмент DNS пакетін жасайды және сұрауды метадеректер серверіне жібереді.

Пайдаланушы кодты іске қосады, DNS жауабы қайтарылады және желі деңгейінде проблема жоқ екенін растайтын қолданба оны алады.

Кезекті «әлемді шарлаудан» кейін сұрау біздің командаға оралады, мен сұрау бір жерден екінші жерге айналуды тоқтатса, пайдаланушыға ыңғайлырақ болады деп ойлап, оны толығымен өзіме аударамын.

Осы уақытта пайдаланушы жүйелік кескіннің суретін беруге келіседі. Бұл өте жақсы жаңалық: жүйені өзім сынау мүмкіндігі ақаулықтарды жоюды әлдеқайда жылдам етеді, өйткені мен енді пайдаланушыдан пәрмендерді орындауды, нәтижелерді жіберуді және оларды талдауды сұраудың қажеті жоқ, мен бәрін өзім жасай аламын!

Әріптестерім маған аздап қызғанышпен қарай бастады. Түскі ас үстінде біз конверсияны талқылаймыз, бірақ не болып жатқанын ешкім білмейді. Бақытымызға орай, пайдаланушының өзі салдарын жеңілдету үшін шаралар қабылдады және асығыс емес, сондықтан бізде мәселені шешуге уақыт бар. Бізде сурет болғандықтан, бізді қызықтыратын кез келген сынақтарды орындай аламыз. Тамаша!

Артқа қадам жасау

Жүйе инженері лауазымдарына арналған ең танымал сұхбат сұрақтарының бірі: «Пинг жасағанда не болады www.google.com? Сұрақ өте жақсы, өйткені үміткер қабықтан пайдаланушы кеңістігіне, жүйелік ядроға, содан кейін желіге дейін барлығын сипаттауы керек. Мен күлемін: кейде сұхбат сұрақтары өмірде пайдалы болып шығады...

Мен осы HR сұрағын ағымдағы мәселеге қолдануды шештім. Шамамен айтқанда, DNS атауын анықтауға тырысқанда, келесілер орын алады:

  1. Қолданба libdns сияқты жүйелік кітапхананы шақырады
  2. libdns қай DNS серверімен байланысуы керек жүйе конфигурациясын тексереді (диаграммада бұл 169.254.169.254, метадеректер сервері)
  3. libdns UDP ұяшығын (SOKET_DGRAM) жасау және екі бағытта DNS сұрауы бар UDP пакеттерін жіберу үшін жүйелік қоңырауларды пайдаланады.
  4. Sysctl интерфейсі арқылы ядро ​​деңгейінде UDP стекін конфигурациялауға болады
  5. Ядро желі интерфейсі арқылы желі арқылы пакеттерді жіберу үшін аппараттық құралмен өзара әрекеттеседі
  6. Гипервизор пакетті ұстайды және онымен байланысқан кезде метадеректер серверіне жібереді
  7. Метадеректер сервері өзінің сиқыры арқылы DNS атауын анықтайды және сол әдіс арқылы жауапты қайтарады

Google Cloud техникалық қолдауынан DNS пакеттерінің жоқтығы туралы әңгіме
Біз қандай гипотезаларды қарастырғанымызды еске салайын:

Гипотеза: Бұзылған кітапханалар

  • Тест 1: жүйеде strace іске қосыңыз, dig дұрыс жүйелік қоңырауларды шақыратынын тексеріңіз
  • Нәтиже: дұрыс жүйелік қоңыраулар шақырылады
  • 2-тест: жүйе кітапханаларын айналып өтетін атауларды анықтай алатынымызды тексеру үшін srapy көмегімен
  • Нәтиже: біз аламыз
  • Тест 3: libdns бумасы мен md5sum кітапхана файлдарында rpm –V іске қосыңыз
  • Нәтиже: кітапхана коды жұмыс істейтін операциялық жүйедегі кодқа толығымен сәйкес келеді
  • Тест 4: пайдаланушының түбірлік жүйесінің кескінін мұндай әрекетсіз VM-ге орнатыңыз, chroot іске қосыңыз, DNS жұмыс істейтінін көріңіз
  • Нәтиже: DNS дұрыс жұмыс істейді

Тесттерге негізделген қорытынды: мәселе кітапханаларда емес

Гипотеза: DNS параметрлерінде қате бар

  • 1-сынақ: tcpdump файлын тексеріңіз және DNS пакеттерінің дұрыс жіберілгенін және dig іске қосылғаннан кейін қайтарылғанын тексеріңіз.
  • Нәтиже: пакеттер дұрыс жіберілді
  • Тест 2: серверді екі рет тексеріңіз /etc/nsswitch.conf и /etc/resolv.conf
  • Нәтиже: бәрі дұрыс

Тесттерге негізделген қорытынды: мәселе DNS конфигурациясында емес

Гипотеза: өзегі зақымдалған

  • Тест: жаңа ядроны орнату, қолтаңбаны тексеру, қайта іске қосу
  • Нәтиже: ұқсас мінез-құлық

Тесттерге негізделген қорытынды: ядро зақымдалмаған

Гипотеза: пайдаланушы желісінің дұрыс емес әрекеті (немесе гипервизордың желілік интерфейсі)

  • Тест 1: брандмауэр параметрлерін тексеріңіз
  • Нәтиже: брандмауэр DNS пакеттерін хостта да, GCP-де де өткізеді
  • Тест 2: трафикті тоқтату және DNS сұрауларын жіберу және қайтару дұрыстығын бақылау
  • Нәтиже: tcpdump хост қайтару пакеттерін алғанын растайды

Тесттерге негізделген қорытынды: мәселе желіде емес

Гипотеза: метадеректер сервері жұмыс істемейді

  • Тест 1: метадеректер серверінің журналдарында ауытқуларды тексеріңіз
  • Нәтиже: журналдарда ауытқулар жоқ
  • Тест 2: арқылы метадеректер серверін айналып өтіңіз dig @8.8.8.8
  • Нәтиже: метадеректер серверін пайдаланбай да ажыратымдылық бұзылады

Тесттерге негізделген қорытынды: мәселе метадеректер серверінде емес

Астыңғы сызық: қоспағанда, біз барлық ішкі жүйелерді сынадық орындау уақыты параметрлері!

Ядроның орындалу уақыты параметрлеріне ену

Ядроның орындалу ортасын конфигурациялау үшін пәрмен жолы опцияларын (grub) немесе sysctl интерфейсін пайдалануға болады. Мен ішке қарадым /etc/sysctl.conf және ойланыңыз, мен бірнеше реттелетін параметрлерді таптым. Мен бірдеңені ұстап алғандай сезініп, тау параметрлерінде қалған барлық желілік емес немесе tcp емес параметрлерді алып тастадым. net.core. Содан кейін мен VM-де хост рұқсаттары бар жерге бардым және кінәліні тапқанша, бұзылған VM арқылы параметрлерді бірінен соң бірін қолдана бастадым:

net.core.rmem_default = 2147483647

Міне, DNS-бұзатын конфигурация! Мен өлтіру қаруын таптым. Бірақ бұл неге болып жатыр? Маған әлі де мотив керек болды.

Негізгі DNS буферінің өлшемі арқылы конфигурацияланады net.core.rmem_default. Әдеттегі мән 200КБ шамасында болады, бірақ сіздің серверіңіз көптеген DNS пакеттерін қабылдаса, буфер өлшемін ұлғайтқыңыз келуі мүмкін. Жаңа пакет келгенде буфер толып қалса, мысалы, қолданба оны жеткілікті жылдам өңдемейтіндіктен, пакеттерді жоғалта бастайсыз. Біздің клиент буфер өлшемін дұрыс ұлғайтты, себебі ол деректерді жоғалтудан қорықты, өйткені ол DNS пакеттері арқылы метрика жинауға арналған қолданбаны пайдаланды. Ол орнатқан мән максималды мүмкін болды: 231-1 (егер 231 мәніне орнатылса, ядро ​​«Жарамсыз АРГУМЕНТ» қайтарады).

Кенеттен мен nmap және scapy неге дұрыс жұмыс істейтінін түсіндім: олар шикі розеткаларды пайдаланды! Шикі розеткалардың кәдімгі розеткалардан айырмашылығы: олар iptables айналып өтеді және олар буферленбейді!

Бірақ неге «буфер тым үлкен» проблемаларды тудырады? Ол жоспарланғандай жұмыс істемейтіні анық.

Осы сәтте мен мәселені бірнеше ядролар мен бірнеше дистрибутивтерде қайта шығара аламын. Мәселе 3.x ядросында пайда болды, енді ол 5.x ядросында да пайда болды.

Шынында да, іске қосу кезінде

sysctl -w net.core.rmem_default=$((2**31-1))

DNS жұмысын тоқтатты.

Мен қарапайым екілік іздеу алгоритмі арқылы жұмыс мәндерін іздей бастадым және жүйе 2147481343 нөмірімен жұмыс істейтінін білдім, бірақ бұл сан мен үшін мағынасыз сандар жиынтығы болды. Мен клиентке осы нөмірді қолданып көруді ұсындым, ол жүйе google.com сайтымен жұмыс істейтінін, бірақ басқа домендерде қате жібергенін айтты, сондықтан мен тергеуімді жалғастырдым.

Мен орнаттым тамшы сағат, бұрын пайдаланылуы керек құрал: ол пакет ядроның қай жерде аяқталатынын көрсетеді. Кінәлі функция болды udp_queue_rcv_skb. Мен ядро ​​көздерін жүктеп алып, бірнешеуін қостым функциялары printk пакеттің қай жерде аяқталатынын бақылау үшін. Мен дұрыс жағдайды тез таптым if, және оған біраз уақыт қарап тұрды, өйткені дәл содан кейін бәрі біртұтас суретке жиналды: 231-1, мағынасыз сан, жұмыс істемейтін домен ... Бұл кодтың бір бөлігі болды. __udp_enqueue_schedule_skb:

if (rmem > (size + sk->sk_rcvbuf))
		goto uncharge_drop;

Назар аударыңыз:

  • rmem int түріне жатады
  • size u16 (белгісіз он алты биттік int) түріне жатады және пакет өлшемін сақтайды
  • sk->sk_rcybuf int түріне жатады және анықтамасы бойынша in мәніне тең болатын буфер өлшемін сақтайды net.core.rmem_default

Қашан sk_rcvbuf 231-ге жақындайды, пакет өлшемін жинақтау нәтижеге әкелуі мүмкін бүтін санның асып кетуі. Бұл int болғандықтан, оның мәні теріс болады, сондықтан ол жалған болуы керек болғанда шарт ақиқатқа айналады (бұл туралы толығырақ мына жерден оқи аласыз. байланыс).

Қатені тривиальды жолмен түзетуге болады: кастинг арқылы unsigned int. Мен түзетуді қолдандым және жүйені қайта іске қостым және DNS қайтадан жұмыс істеді.

Жеңіс дәмі

Мен өз нәтижелерімді клиентке жібердім және жібердім LKML ядро патч. Мен ризамын: басқатырғыштың әрбір бөлігі бір-біріне сәйкес келеді, мен байқағанымызды не үшін байқағанымызды нақты түсіндіре аламын, ең бастысы, біз топтық жұмыстың арқасында мәселенің шешімін таба алдық!

Бұл жағдай сирек болғанын мойындау керек және бақытымызға орай, пайдаланушылардан мұндай күрделі сұрауларды сирек аламыз.

Google Cloud техникалық қолдауынан DNS пакеттерінің жоқтығы туралы әңгіме


Ақпарат көзі: www.habr.com

пікір қалдыру