Notatki z terenu
Prawdziwe incydenty i śledztwa z pracy przy chmurze, AI i bezpieczeństwie, opisane jako krótkie historie detektywistyczne. Każda jest zanonimizowana: nazwy, systemy i szczegóły pozwalające na identyfikację zostały uogólnione.
Terraform apply dostał 409 na zasobie, którego jego state nigdy nie widział. Zwrot akcji: poprawka już istniała, w historii gita innego środowiska.
Potok w modelu „zbuduj raz, promuj wszędzie” kryje dwie zagadki: krok CI, który umiera bez żadnego wyjścia, i rolę wdrożeniową na produkcję, której nie da się przyjąć.
Ingress ArgoCD bez adresu prowadzi do certyfikatu self-signed bez IP w SAN, a potem do współdzielonego obiektu IngressClass usuniętego przez niezwiązany prune GitOps, w trakcie migracji kontrolera ingress na żywo.
Autoskaler Kubernetesa co 1–2 minuty rozbierał i odbudowywał węzły dla groszowych oszczędności. Detektywistyczna relacja z diagnozy i naprawy.
Zmiana źródła zależności Pythona skierowała wewnętrzne pakiety do proxy kurującego artefakty, które zawsze odzwierciedlało tylko publiczny PyPI. Po drodze: o włos uniknięty force-push i pomylenie 404 z 403.
Audyt disaster recovery platformy tradingowej pokazuje, że cele czasu odtworzenia były już spełnione natywnie. Prawdziwe luki to głębokość retencji, zapisy odporne na manipulację, niejasności między kontami i nieodwracalne ustawienie, którego nikt nie powinien jeszcze przełączać.
Commit twierdzący, że produkcyjna baza platformy finansowej została już zniszczona w AWS, okazuje się w pełni prawdziwy i w pełni niegroźny. Potwierdziło to dopiero sprawdzenie żywej infrastruktury, a nie ponowne czytanie tego samego niepokojącego zdania.
Wykres prawie bezczynnego CPU niemal uzasadnia zmniejszenie węzłów walidatorów platformy blockchain, dopóki profil pamięci samego obciążenia nie budzi wątpliwości. Zdobycie prawdziwych liczb oznacza obejście zablokowanego klastra i konektora monitoringu, który po cichu startuje w złym trybie.
Celowany Terraform apply po cichu pominął NAT gateway i odciął nowy klaster Kubernetesa, aż jego węzły po piętnastu minutach przekroczyły limit czasu. Potem okazało się, że zapisany plik planu niesie poświadczenia złej tożsamości.
Pod przez sześć godzin wisiał w Pending, bo time-slicing GPU sprawiał, że jedna karta graficzna liczyła się jak cztery wobec limitu puli węzłów równego jeden. A pod spodem sąsiednie obciążenie deklarowało jedną trzecią CPU, którego faktycznie używało.
Klaster wyszukiwania przeznaczony do usunięcia miał większy dzienny ruch niż jego działający następca. Te same dane w ujęciu godzinowym pokazały, że w godzinie przełączenia oba zamieniły się kształtami dnia i nocy, a pozostała płaska linia to usługa rozmawiająca sama ze sobą.
Monitor zbudowany do wyłapywania kopii zapasowych, które po cichu przestają się wykonywać, był czerwony rano po wdrożeniu. Kopie były w porządku, etykieta metryki znaczyła coś odwrotnego niż oczywiste przypuszczenie, a jej poprawienie zlikwidowało ograniczenie, które już zapisano i zaakceptowano.
Drugie szybkie łącze wyglądało na oczywistą konieczność dla LLM rozłożonego na parę NVIDIA DGX Spark. Dopóki pierwszy pomiar nie pokazał zera, drugi niemożliwie wysokiej wartości, a uczciwe liczby 13% szczytowego wykorzystania.
Narzędzia kontenerowe obiecywały 180 GB miejsca do odzyskania, a dały około jednego, bo warstwowy storage raportuje rozmiary logiczne. Prawdziwego konsumenta znalazły dwa polecenia systemu plików, a o włos uniknięte usunięcie zatrzymała twarda blokada na nazwie.
Zwolnienie jednej z dwóch maszyn wyglądało na koszt 4,4× prędkości, dopóki uruchomienie tego samego modelu na obu liczbach węzłów nie rozbiło tego na 1,65× sprzętu i 2,7× modelu. Płaska linia przepustowości przy pięciu bardzo różnych promptach pokazała dlaczego.
Prośba o upublicznienie bucketu S3 okazała się wymagać brzegu CDN (Origin Access Control) przy prywatnym buckecie. Potem 403 z domyślnej wartości modułu, certyfikat wildcard w złym regionie i „DNS się nie rozwiązuje”, które okazało się tylko nieaktualnym cache VPN.
LLM nie działał przez piętnaście godzin, a jego kontenery radośnie raportowały „Up 46 hours”. Polityka OOM dostawcy wskazała go jako preferowaną ofiarę, a każdy restart potem padał przez ustawienie dotyczące wylogowania.
W migracji z CI do chmury rola „tylko do odczytu” do planu nie potrafiła zrobić planu: nie mogła czytać wartości sekretów, jeden zaszyfrowany sekret nie dawał się odszyfrować, klaster nie rozpoznawał roli, a nieaktualne ponowne uruchomienie udawało zielony build.
Znacznik „nie przerywać” chronił działającego poda multimedialnego 5585 razy, a potem przestał, bo 48-godzinny okres karencji dodany właśnie z myślą o tym obciążeniu pozwolił, żeby drift węzła go zignorował. Klaster zapowiedział egzekucję dwa dni wcześniej i nikogo nie zaalarmował.
Analityczna baza danych wpadła w pętlę restartów z błędem parsowania XML podczas czytania pliku YAML. Winowajcą był niedrukowalny bajt dzwonka terminala ukryty w haśle, które każde narzędzie w łańcuchu wyświetlało jako idealnie poprawne.
Jedna aplikacja z dwudziestu przestała się synchronizować, bo w klastrze pojawiło się pole statusu, o którym narzędzie wdrożeniowe nigdy nie słyszało. Potem „zachowawczy” wybór wersji okazał się tym niewspieranym, a aktualizacja ujawniła CRD nieprawidłowy od 2021 roku i partię jobów, które nie uruchomiły się od dziesięciu miesięcy.
Portfel operatora walidatora nie zgadzał się z adresem, który skrypt instalacyjny kazał mu zarejestrować. „Adres” był pierwszymi 40 znakami klucza publicznego, wyciętymi z linii logu przez niezakotwiczony grep, a klient, który już skutecznie postawił stake, po cichu to obszedł.
Wszystkie testy przeszły, a potem przekazanie do repozytorium GitOps padło z „401 Bad credentials”. Osobisty token dostępu wygasł w czasie jedenastomiesięcznej ciszy, a od niego zależały też workflowy stagingu i produkcji.