jeśli mieliście okazję przeczytać post o budowie mojej sieci domowej, wiecie, że szkieletowym przełącznikiem jest Nexus 93180YC-EX. taki… domowy przełącznik.

anycastowe adresy usług

tak czy inaczej, w sieci tej mam różną ilość serwerów DNS (i DHCP), które serwują anycastowy adres 192.168.168.168 oraz 2001:470:xx:a6::168. niezależnie od ilości działających serwerów DNS, zawsze przynajmniej jeden powinien odpowiedzieć.

obecnie w “klastrze” mam dwie VMki oraz dwa fizycznie Raspberry Pi 4B+. wszystkie pracują pod kontrolą FreeBSD 14.0-STABLE, z pakietami nsd, unbound oraz bird jako demonem rozgłaszającym adresy po IPv4 i IPv6.

z perspektywy szkieletowego Nexusa i BGP, rozgłoszenia te wyglądają następująco - dla IPv4:

sw-core# sh bgp ipv4 unicast
BGP routing table information for VRF default, address family IPv4 Unicast
BGP table version is 36, Local Router ID is 192.168.33.1
Status: s-suppressed, x-deleted, S-stale, d-dampened, h-history, *-valid, >-best
Path type: i-internal, e-external, c-confed, l-local, a-aggregate, r-redist, I-injected
Origin codes: i - IGP, e - EGP, ? - incomplete, | - multipath, & - backup, 2 - best2

   Network            Next Hop            Metric     LocPrf     Weight Path
*|i192.168.168.168/32 192.168.66.22                     100          0 i
*|i                   192.168.66.44                     100          0 i
*>i                   192.168.44.180                    100          0 i
*|i                   192.168.66.33                     100          0 i

dla IPv6:

sw-core# sh bgp ipv6 unicast
[...]
   Network            Next Hop            Metric     LocPrf     Weight Path
*|i2001:470:xx:a6::168/128
                      2001:470:xx:66::22
                                                        100          0 i
*|i                   2001:470:xx:66::44
                                                        100          0 i
*>i                   2001:470:xx:444::180
                                                        100          0 i
*|i                   2001:470:xx:66::33
                                                        100          0 i

i w końcu - co ląduje w tablicy routingu?

sw-core# sh ip route 192.168.168.168
IP Route Table for VRF "default"
'*' denotes best ucast next-hop
'**' denotes best mcast next-hop
'[x/y]' denotes [preference/metric]
'%<string>' in via output denotes VRF <string>

192.168.168.168/32, ubest/mbest: 4/0
    *via 192.168.44.180, [200/0], 1w5d, bgp-65055, internal, tag 65055
    *via 192.168.66.22, [200/0], 4d09h, bgp-65055, internal, tag 65055
    *via 192.168.66.33, [200/0], 3w3d, bgp-65055, internal, tag 65055
    *via 192.168.66.44, [200/0], 1w1d, bgp-65055, internal, tag 65055
sw-core# sh ipv6 route 2001:470:xx:a6::168
IPv6 Routing Table for VRF "default"
'*' denotes best ucast next-hop
'**' denotes best mcast next-hop
'[x/y]' denotes [preference/metric]

2001:470:xx:a6::168/128, ubest/mbest: 4/0
    *via 2001:470:xx:66::22/128, [200/0], 4d09h, bgp-65055, internal, tag 65055
    *via 2001:470:xx:66::33/128, [200/0], 3w3d, bgp-65055, internal, tag 65055
    *via 2001:470:xx:66::44/128, [200/0], 1w1d, bgp-65055, internal, tag 65055
    *via 2001:470:xx:444::180/128, [200/0], 1w5d, bgp-65055, internal, tag 65055

efekt (domyślnie), jest jednak taki, że dochodzi do nierównomiernego rozłożenia ruchu na każdy z serwerów. domyślnie, rozkładanie ruchu odbywa się na podstawie źródłowego adresu IP i źródłowego portu TCP/UDP. u mnie (parę /24 z puli 192.168/16 generujących dosyć dużo zróżnicowanych zapytań), kończy się to rozkładem ruchu w stosunku mniej więcej 1/2 do 1/4 do dwóch 1/8.

zajrzałem zatem do konfiguracji ECMP i po wydaniu polecenia:

sw-core(config)# ip load-sharing address source-destination port source-destination rotate 32 universal-id 9239194

…w ciągu jednego dnia sytuacja zmieniła się na prawie idealne rozłożenie po 1/4:

sposób obsługi ruchu w ECMP można oczywiście zweryfikować również na Nexusie:

sw-core# sh ip load-sharing
IPv4/IPv6 ECMP load sharing:
Universal-id (Random Seed): 94812191
Load-share mode : address source-destination port source-destination
Rotate: 32

podsumowanie

oprócz ECMP (Equal-Cost MultiPathing) można również kombinować z bardziej zaawansowanymi mechanizmami - np. UCMP (Uneqal-Cost MultiPathing). ale na początek takie podejście powinno się sprawdzić ;)