Bond aktywno-zapasowy Linuksa na all-active EVPN: co się psuje
Segment all-active EVPN wysyła unicast do dowolnego liścia, podczas gdy bond aktywno-zapasowy Linuksa nasłuchuje tylko na jednym porcie. Zanim zaczniesz testować, dopasuj oba modele.
Umieść bond aktywno-zapasowy na serwerze, a segment all-active Ethernet na fabricu, i połowa ruchu powrotnego może zniknąć, nie ruszając ani jednego licznika błędów. Żadna z tych konfiguracji nie jest sama w sobie błędna. Problem tkwi w przekazaniu między nimi: jedna strona wybiera jeden port, a druga zakłada, że każdy podłączony liść potrafi dostarczyć. Prześledź jedną ramkę w każdym kierunku, a niezgodność stanie się oczywista.
Co aktywno-zapasowy robi z ramką przychodzącą
Tryb bondingu 1 utrzymuje dokładnie jeden slave w ścieżce nadawania i zamienia go tylko wtedy, gdy bieżący zawiedzie. Ta część jest dobrze znana. Tutaj liczy się strona odbioru: jądro przekazuje ramkę do stosu tylko wtedy, gdy trafi ona na aktywny slave, a ramki pojawiające się na innym slave odrzuca. To all_slaves_active ustawienie istnieje właśnie po to, by złagodzić tę regułę, i domyślnie jest wyłączone. ip -d link show bond0 wypisuje bieżącą wartość obok trybu.
/proc/net/bonding/bond0 nazywa aktywny slave i raportuje stan łącza każdego slave. Ten plik jest jedynym uczciwym źródłem informacji, który port aktualnie niesie ruch.
Host w tym trybie ma naraz jedną użyteczną ścieżkę odbioru, wybieraną lokalnie bez wiedzy o fabricu. Jeśli ramka dla tego hosta przyjdzie drugim kablem, port przełącznika policzy ją jako odebraną, stos hosta nigdy jej nie zobaczy, a wszystkie liczniki poza własnym licznikiem odrzuceń hosta wyglądają całkiem zdrowo.
Co all-active multihoming robi z odległym następnym skokiem
EVPN multihoming opisuje zbiór liści współdzielących jeden segment Ethernet, identyfikowany przez ESI, i rozgłasza ten segment reszcie fabricu. W modelu all-active zdalne peery instalują więcej niż jeden następny skok dla adresów segmentu. Unicast w stronę serwera może więc trafić na dowolny liść, a fabric może swobodnie wybierać per przepływ. To cały sens projektu i zarazem założenie, które bond serwera musi spełniać.
Ruch zalewany podlega innej regule. Liście wybierają wyznaczonego forwardera per segment, więc broadcast, nieznany unicast i multicast wchodzą zwykle przez jeden z nich. Unicast i zalewanie podejmują więc dwie odrębne decyzje, a tylko jedna z nich jest widoczna w stanie bondu hosta.
Gdzie oba wybory się rozchodzą
Jądro wybiera swój aktywny slave na podstawie stanu łącza i własnej polityki. Fabric wybiera następne skoki na podstawie tras EVPN, a wyznaczonego forwardera na podstawie wyboru między liśćmi. Żaden proces nie konsultuje się z drugim. Gdy wybiorą różne liście, awaria zależy od kierunku: to, co serwer wysyła, wychodzi normalnie, a odpowiedzi znikają.
Istnieją dwa obsługiwane wyjścia i nie są wymienne. Daj hostowi bond, który fabric może traktować jako jedno logiczne przyłączenie, co w praktyce oznacza bond LACP wynegocjowany z liśćmi, i oba łącza są naprawdę aktywne razem. Albo zaakceptuj także dostarczanie single-active z fabricu, aby segment szedł tym samym modelem jednego portu naraz co bond. Nie działa natomiast segment all-active przed bondem nasłuchującym tylko na jednym porcie, chyba że celowo włączysz odbiór na nieaktywnych slave'ach i zaakceptujesz wynikające z tego podwójne dostarczanie.
Dlaczego kabel zapasowy wciąż wygląda zdrowo
Kabel, który nie niesie ruchu, nadal zgłasza łącze w górę, a slave w gotowości w bondzie jest zaprojektowany tak, by wyglądać na gotowy. Operatorzy czytają to jako nadmiarowość i przestają pytać.
Zapytaj zamiast tego, którego fizycznego portu użyła ramka powrotna. Na hoście licz pakiety odebrane per slave, a nie per bond, bo licznik bondu ukrywa asymetrię. Na liściu spójrz na wpisy przekazywania mostu dla adresu MAC serwera oraz na zbiór następnych skoków, który niesie trasa EVPN. Jeśli wpis wskazuje liść, którego łącze hosta jest zapasowe, projekt dostarcza do portu, który host ignoruje. To niezgodność konfiguracji, a nie usterka sprzętu, i żadne monitorowanie stanu łącza jej nie ujawni.
Testuj dostarczanie w obu kierunkach, nie stan łącza
Zbuduj macierz z jednym wierszem na awarię i jedną kolumną na kierunek, a potem wypełniaj ją dostarczonym ruchem, a nie stanem interfejsu. Wiersz jeden to normalna praca i właśnie tam ukrywa się niezgodność, bo objaw wygląda jak problem aplikacji.
Następnie usuń aktywne łącze hosta, usuń jeden liść, usuń uplinki tego liścia i przywróć każdy po kolei. Po każdym kroku zapisz aktywny slave, stan segmentu EVPN, zdalny wpis przekazywania i zaobserwowaną przepustowość w obu kierunkach. Liść, który traci ścieżkę do fabricu, gdy jego łącze hosta pozostaje w górze, jest ciekawym przypadkiem, bo przyłączenie pozostaje rozgłoszone i może po cichu stać się ślepą uliczką. Testuj świeżymi przepływami unicast i ruchem zalewanym, od którego zależy aplikacja, bo oba używają różnych decyzji przekazywania.
Zaakceptuj projekt tylko wtedy, gdy macierz pokazuje dwukierunkowe dostarczanie zamierzoną ścieżką. Dwa kable ze łączem w górze to nie ten wynik.