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żka | RTT | W locie dla 1 Gbit/s | Domyślne okno jądra |
|---|---|---|---|
| AMS-01 do FRA-01 | 7 ms | 0.9 MB | Wystarczające |
| AMS-01 do NYC-01 | 76 ms | 9.5 MB | Niewystarczające |
| AMS-01 do SIN-01 | 168 ms | 21 MB | Daleko do tego |
| AMS-01 do GRU-01 | 196 ms | 24.5 MB | Daleko 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 --systemBBR 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 30Osiem 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 postgresqlNa 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 postgresqlFlaga -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.logNastę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 | headKaż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 laterGdy 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.