Dwanaście instalacji

Przenoszenie dwóch terabajtów między dwiema naszymi lokalizacjami bez przestojów

Pre-kopia, replika strumieniowa i proxy przy przełączeniu, z tuningiem TCP, który decyduje, czy transfer na długim dystansie zajmie godzinę, czy dzień.

Co to buduje

Dwa terabajty plików i działająca baza Postgres przeniesiona z jednej lokalizacji do drugiej, z aplikacją odpowiadającą na żądania przez cały czas. Metoda to masowe wstępne kopiowanie, podczas gdy źródło dalej serwuje, streamingowa replika, która pozostaje zsynchronizowana, i przełączenie mierzone w sekundach, ze starym hostem proxującym do nowego, dopóki DNS się nie zaktualizuje.

Odległość jest interesującą częścią. Między AMS-01 a FRA-01 czas round trip to siedem milisekund, a pojedynczy strumień wypełni port. Uruchom tę samą kopię do GRU-01, gdzie czas round trip to blisko dwieście, a nietuningowany transfer wlecze się z ułamkiem prędkości, za którą płacisz, podczas gdy obie maszyny siedzą prawie bezczynnie. Ta różnica wynika w całości z tego, ile danych jedne połączenie może mieć w locie.

Zanim zaczniesz

  • Instancje źródłowa i docelowa, tunel między nimi i root na obu.
  • DNS, którym zarządzasz, z TTL rekordu obniżonym do sześćdziesięciu sekund co najmniej dzień wcześniej. To krok, który ludzie pomijają, a potem czekają sześć godzin.
  • Wystarczająco dużo dysku na celu dla całego zbioru danych plus repliki.

1. Sprawdź, co potrafi łącze

Iloczyn pasma i opóźnienia decyduje o wszystkim. Pomnóż czas round trip przez prędkość, którą chcesz, a otrzymasz ilość danych, która musi być niepotwierdzona w locie w każdej chwili:

ping -c20 target.example.com | tail -1
ŚcieżkaRTTW locie dla 1 Gbit/sDomyślne okno jądra
AMS-01 do FRA-017 ms0.9 MBWystarczające
AMS-01 do NYC-0176 ms9.5 MBNiewystarczające
AMS-01 do SIN-01168 ms21 MBDaleko do tego
AMS-01 do GRU-01196 ms24.5 MBDaleko do tego

Na obu maszynach:

cat > /etc/sysctl.d/75-transfer.conf <<EOF
net.core.rmem_max = 134217728
net.core.wmem_max = 134217728
net.ipv4.tcp_rmem = 4096 262144 134217728
net.ipv4.tcp_wmem = 4096 262144 134217728
net.ipv4.tcp_congestion_control = bbr
net.core.default_qdisc = fq
net.ipv4.tcp_mtu_probing = 1
EOF
sysctl --system

BBR zamiast domyślnego sterowania przeciążeniem ma znaczenie na długich ścieżkach z jakąkolwiek stratą, ponieważ algorytmy oparte na stratach interpretują pojedynczy zgubiony pakiet jako przeciążenie i zmniejszają swoje okno o połowę. Po dwustu milisekundach odzyskanie po tym trwa sekundy i powtarza się to wielokrotnie.

Zmierz, zanim zaangażujesz dwa terabajty w założenie:

# target
apt install -y iperf3 && iperf3 -s
# source
iperf3 -c target.example.com -P 8 -t 30

Osiem równoległych strumieni powinno zbliżyć się do szybkości portu. Jeśli jeden strumień osiągnie sto megabitów, a osiem osiemset, ustawienia okna nie zadziałały; po ich zastosowaniu pojedynczy strumień powinien sam osiągnąć większość drogi.

2. Masowe wstępne kopiowanie

Uruchom to na żywym źródle. Zajmie to godziny i nic nie zostanie przerwane podczas tego:

apt install -y rsync
rsync -aHAX --numeric-ids --partial --inplace --info=progress2 \
  -e "ssh -c [email protected] -o Compression=no" \
  /srv/data/ [email protected]:/srv/data/

Wybór szyfru nie jest przesądem. Na tych procesorach sprzętowo przyspieszony tryb GCM przesuwa kilka gigabajtów na sekundę na rdzeń, podczas gdy domyślnie negocjowany szyfr w niektórych wersjach klientów jest wyraźnie wolniejszy i zamienia twój transfer w test jednordzeniowy. Kompresja jest wyłączona, ponieważ dane są już skompresowane, a jeśli nie są, CPU spędza czas na tym zamiast na przenoszeniu bajtów.

Dla milionów małych plików jeden strumień to zły kształt. Podziel według katalogu najwyższego poziomu i uruchom kilka:

ls /srv/data | xargs -P 8 -I{} rsync -aHAX --numeric-ids \
  -e "ssh -c [email protected] -o Compression=no" \
  /srv/data/{}/ [email protected]:/srv/data/{}/

Osiem równoległych kopii na ośmiu dedykowanych rdzeniach to odpowiednia liczba tutaj; szesnaście nie jest dwa razy szybsze i sprawi, że maszyna źródłowa będzie nieprzyjemna dla tego, co nadal serwuje.

3. Baza danych, replikowana zamiast kopiowana

Zrzucenie i przywrócenie dwustu gigabajtów Postgresa oznacza długie okno, w którym zapisy są tracone. Strumieniuj zamiast tego. Na źródle:

sudo -u postgres psql -c "CREATE USER repl WITH REPLICATION PASSWORD '<a long password>';"
sudo -u postgres psql -c "SELECT pg_create_physical_replication_slot('target_site');"
echo "host replication repl 10.9.0.2/32 scram-sha-256" >> /etc/postgresql/17/main/pg_hba.conf
systemctl reload postgresql

Na celu:

systemctl stop postgresql
rm -rf /var/lib/postgresql/17/main/*
sudo -u postgres pg_basebackup -h 10.9.0.1 -U repl -D /var/lib/postgresql/17/main \
  -S target_site -X stream -R -P -c fast
systemctl start postgresql

Flaga -R zapisuje ustawienia połączenia i plik sygnału stanby, więc cel wstaje jako replika i zaczyna podążać. Od tego momentu pozostaje w ciągu sekundy lub dwóch od źródła w nieskończoność, co oznacza, że przełączenie nie wymaga już przenoszenia bazy danych.

4. Przełączenie

Uruchom sondę z trzeciej maszyny i zostaw ją działającą. To zarówno twoja weryfikacja, jak i zapis tego, ile kosztowało przełączenie:

while true; do curl -s -o /dev/null -w "%{http_code} %{time_total}\n" https://app.example.com/health; sleep 1; done | tee cutover.log

Następnie, w tej kolejności i bez pauz:

# 1. final delta, source still live
rsync -aHAX --numeric-ids --delete -e "ssh -c [email protected]" /srv/data/ [email protected]:/srv/data/

# 2. stop writes on the source
systemctl stop app

# 3. one more delta, now tiny
rsync -aHAX --numeric-ids --delete -e "ssh -c [email protected]" /srv/data/ [email protected]:/srv/data/

# 4. promote the replica
ssh [email protected] "sudo -u postgres pg_ctl promote -D /var/lib/postgresql/17/main"

# 5. start the application on the target
ssh [email protected] "systemctl start app"

Kroki od drugiego do piątego zajmują kilka sekund. Teraz zatrzymaj stary host przed serwowaniem nieaktualnych treści, podczas gdy DNS się propaguje, zamieniając go w proxy dla nowego:

server {
  listen 443 ssl;
  server_name app.example.com;
  ssl_certificate     /etc/letsencrypt/live/app.example.com/fullchain.pem;
  ssl_certificate_key /etc/letsencrypt/live/app.example.com/privkey.pem;
  location / {
    proxy_pass https://10.9.0.2;
    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-For $remote_addr;
  }
}

To element, który czyni całą operację niezakłócającą. Każdy, kto nadal rozwiązuje stary adres, otrzymuje poprawną odpowiedź przez tunel zamiast błędu lub, co gorsza, kopii danych, która przestała się aktualizować w momencie przełączenia. Teraz zmień rekord DNS.

Zweryfikuj to

Zacznij od logu sondy, który zbierałeś:

sort cutover.log | uniq -c | sort -rn | head

Każda linia powinna czytać 200. Kilka wolniejszych odpowiedzi podczas przełączania jest oczekiwane; każdy nie-200 oznacza, że krok piąty zaczął się po kroku drugim zbyt późno, a proxy z poprzedniej sekcji jest tym, co zmniejsza tę lukę do zera.

Następnie udowodnij, że dane są identyczne, a nie tylko obecne:

rsync -aHAXn --delete --itemize-changes /srv/data/ [email protected]:/srv/data/ | head
du -s --bytes /srv/data
ssh [email protected] "du -s --bytes /srv/data"

Uruchomienie testowe, które niczego nie wyszczególnia, oznacza, że oba drzewa zgadzają się co do zawartości, uprawnień, własności i rozszerzonych atrybutów. Sumy bajtów powinny zgadzać się dokładnie.

Baza danych w następnej kolejności:

ssh [email protected] "sudo -u postgres psql -c 'SELECT pg_is_in_recovery();'"
ssh [email protected] "sudo -u postgres psql app -c 'SELECT count(*) FROM orders;'"
sudo -u postgres psql app -c "SELECT count(*) FROM orders;"

Odzyskiwanie powinno być teraz fałszywe na celu, a liczniki wierszy powinny się zgadzać. Na koniec potwierdź, że ruch naprawdę się przeniósł, a nie jest po cichu proxowany na zawsze:

dig +short app.example.com
tail -f /var/log/nginx/access.log | wc -l   # on the old host, an hour later

Gdy stary host był bezczynny przez pełne TTL plus komfortowy margines, zdejmij proxy i zniszcz instancję. Nie niszcz jej tego samego popołudnia; najtańszym ubezpieczeniem w całej tej procedurze jest pozostawienie maszyny źródłowej nietkniętej i wyłączonej na tydzień.

Po wszystkim

Dwa terabajty po dobrze dostrojonej ścieżce długodystansowej to mniej więcej godzina przy dziesięciu gigabitach i raczej dłużej w praktyce, ponieważ źródło również serwuje. Między sąsiednimi europejskimi lokacjami planuj popołudnie; między kontynentami zacznij wieczorem i zrób przełączenie następnego dnia. Strona z lokacjami zawiera czasy round trip, które mierzymy, i to są liczby, które należy wpisać do tabeli w kroku pierwszym.

Gotowi, gdy jesteś

Wybierz miasto. Wybierz rozmiar. Płać kryptowalutą.

Bez formularzy o tym, kim jesteś, bez czekania na akceptację człowieka, bez telefonu w celu weryfikacji. Faktura zostaje uregulowana, a dane logowania trafiają do Twojej skrzynki.