Aktualizacja software’u central AT&T sprawiła, że jeden powrót z awarii mógł wywołać awarię sąsiadów
15 stycznia 1990 r. amerykańska sieć dalekobieżna AT&T doświadczyła wielogodzinnej kaskadowej awarii. Nowe oprogramowanie było zainstalowane w wielu centralach 4ESS. Gdy jedna centrala wykonywała reset i wracała do pracy, wysyłała określone komunikaty do sąsiadów. W specyficznym timingu odbiorca mógł wejść w wadliwą ścieżkę kodu i sam się zrestartować. Jego powrót generował kolejne komunikaty, które mogły resetować następne centrale. Lokalny mechanizm odzyskiwania stał się więc mechanizmem rozprzestrzeniania awarii.
Awaria zaczęła się od zwykłego zdarzenia utrzymaniowego
Sieci telekomunikacyjne zakładają, że pojedyncza centrala od czasu do czasu się restartuje. Sąsiednie węzły muszą wtedy zaktualizować informacje o trasach i ponownie zsynchronizować stan. To normalna ścieżka recovery i właśnie dlatego była tak niebezpieczna: bug ukrywał się w kodzie, który miał pomagać w powrocie do zdrowia.
Specyficzna kolejność komunikatów ujawniała defekt
Opis incydentu wskazuje na bardzo wąskie okno czasowe, w którym określone komunikaty przychodziły niemal jednocześnie. Tego typu błędy są trudne do testowania, bo zwykły zestaw scenariuszy może nigdy nie trafić w dokładną sekwencję. W systemie rozproszonym kolejność wiadomości jest częścią przestrzeni stanów.
Identyczny software zamienił redundancję w wspólną podatność
Sieć składała się z wielu central, więc powinna tolerować utratę pojedynczego węzła. Problem polegał na tym, że te węzły uruchamiały tę samą wersję oprogramowania. Wspólny bug recovery mógł działać jak wirus logiczny, choć nie był złośliwym kodem.
Kaskada sama się podtrzymywała
Każda centrala, która się restartowała, po powrocie wysyłała komunikaty mogące wywołać problem u innych. System próbujący się naprawić produkował więc kolejne warunki awarii. To przeciwieństwo izolacji błędów: failure domain rozszerzał się automatycznie.
Rollback był skuteczniejszy niż dalsze debugowanie w produkcji
Po rozpoznaniu związku z nową wersją software’u AT&T mogło wycofać zmianę. W dużych systemach krytycznych zdolność szybkiego rollbacku jest funkcją bezpieczeństwa. Nie trzeba od razu rozumieć każdego bitu przyczyny, aby przywrócić znaną dobrą wersję.
Recovery code wymaga osobnych testów chaosowych
Programiści zwykle testują ścieżkę normalną częściej niż kod uruchamiany po awarii. Tymczasem recovery działa właśnie wtedy, gdy system jest najbardziej niestabilny. Testy restartów, opóźnień, zduplikowanych wiadomości i nietypowej kolejności zdarzeń powinny być równie ważne jak test funkcji podstawowej. Co więcej, kaskada może wystąpić nawet bez wysokiego obciążenia użytkowników. Wystarczy, że same mechanizmy sterujące wygenerują lawinę zmian stanu. Dlatego control plane bywa izolowany od data plane, a jego komunikaty mają osobne limity i reguły stabilizacji.
System rozproszony powinien zakładać, że recovery messages też mogą być groźne
Projektant protokołu zwykle koncentruje się na danych produkcyjnych: połączeniach, transakcjach czy pakietach użytkownika. Komunikaty kontrolne — „wróciłem do sieci”, „moja tabela tras jest aktualna”, „zrestartowałem się” — mogą jednak zmieniać stan wielu węzłów naraz. Dlatego trzeba traktować je jak pełnoprawne wejścia o potencjalnie dużym wpływie. Stosuje się rate limiting, idempotency, wersjonowanie protokołu, backoff oraz mechanizmy zapobiegające jednoczesnemu restartowi wielu węzłów. Chaos engineering celowo symuluje dziś właśnie takie scenariusze: restart grupy maszyn, utratę łączności, opóźnienie wiadomości czy nagły powrót dużej liczby instancji. Awaria AT&T była wczesną ilustracją problemu, który nadal dotyczy chmur i mikroserwisów: recovery path to też ścieżka produkcyjna i może mieć większy blast radius niż normalna obsługa ruchu. Po incydencie wartość miała także izolacja wersji. Gdy cała sieć otrzymuje identyczny release jednocześnie, pojedynczy defekt ma maksymalny zasięg. Stopniowe wdrożenie z małą częścią węzłów pełni rolę bezpiecznika również w telekomunikacji.