Was dabei herauskommt
Zwei Terabyte Dateien und eine laufende Postgres-Datenbank werden von einem Standort zum anderen verschoben, während die Anwendung durchgehend Anfragen beantwortet. Die Methode ist ein Bulk-Vorkopieren, während die Quelle weiter bedient, ein Streaming-Replikat, das in Schritt bleibt, und ein Wechsel, der in Sekunden gemessen wird, wobei der alte Host bis zum DNS-Umstieg auf den neuen proxyt.
Die Entfernung ist der interessante Teil. Zwischen AMS-01 und FRA-01 beträgt die Roundtrip-Zeit sieben Millisekunden, und ein einzelner Stream füllt einen Port. Führt man dieselbe Kopie nach GRU-01 aus, wo die Roundtrip-Zeit nahe zweihundert beträgt, kriecht eine unangepasste Übertragung mit einem kleinen Bruchteil dessen dahin, was man bezahlt, während beide Maschinen fast im Leerlauf sind. Diese Lücke liegt vollständig daran, wie viele Daten eine Verbindung in der Luft haben darf.
Bevor Sie beginnen
- Quell- und Zielinstanzen, ein Tunnel zwischen ihnen und Root auf beiden.
- DNS, das Sie kontrollieren, mit der TTL des Datensatzes mindestens einen Tag vorher auf sechzig Sekunden gesenkt. Das ist der Schritt, den man überspringt und dann sechs Stunden wartet.
- Genug Speicher auf dem Ziel für den gesamten Datensatz plus das Replikat.
1. Ermitteln, was die Leitung kann
Das Bandbreite-Verzögerungs-Produkt entscheidet über alles. Multiplizieren Sie die Roundtrip-Zeit mit der gewünschten Rate, und Sie erhalten die Datenmenge, die zu jedem Zeitpunkt unbestätigt in der Luft sein muss:
ping -c20 target.example.com | tail -1| Pfad | RTT | In Flight für 1 Gbit/s | Standard-Kernel-Fenster |
|---|---|---|---|
| AMS-01 nach FRA-01 | 7 ms | 0.9 MB | Ausreichend |
| AMS-01 nach NYC-01 | 76 ms | 9.5 MB | Nicht ausreichend |
| AMS-01 nach SIN-01 | 168 ms | 21 MB | Bei weitem nicht |
| AMS-01 nach GRU-01 | 196 ms | 24.5 MB | Bei weitem nicht |
Auf beiden Maschinen:
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 statt der Standard-Staukontrolle macht auf langen Pfaden mit jeglichem Verlust einen Unterschied, weil verlustbasierte Algorithmen ein einzelnes verworfenes Paket als Stau interpretieren und ihr Fenster halbieren. Über zweihundert Millisekunden dauert die Erholung davon Sekunden, und das passiert wiederholt.
Messen Sie, bevor Sie zwei Terabyte auf eine Annahme festlegen:
# target
apt install -y iperf3 && iperf3 -s
# source
iperf3 -c target.example.com -P 8 -t 30Acht parallele Streams sollten sich der Portgeschwindigkeit nähern. Wenn ein Stream hundert Megabit schafft und acht schaffen achthundert, haben die Fenstereinstellungen nicht gegriffen; ein einzelner Stream sollte nach deren Aktivierung den größten Teil des Weges alleine schaffen.
2. Bulk-Vorkopieren
Führen Sie dies gegen eine Live-Quelle aus. Es dauert Stunden, und nichts wird dabei unterbrochen:
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/Die Wahl der Chiffre ist kein Aberglaube. Auf diesen Prozessoren bewegt die hardwarebeschleunigte GCM-Mode mehrere Gigabyte pro Sekunde pro Kern, während die standardmäßig ausgehandelte Chiffre bei einigen Client-Versionen deutlich langsamer ist und Ihre Übertragung in einen Single-Core-Benchmark verwandelt. Die Komprimierung ist aus, weil die Daten bereits komprimiert sind, und wenn nicht, verbringt die CPU ihre Zeit damit, statt Bytes zu bewegen.
Für Millionen kleiner Dateien ist ein Stream die falsche Form. Teilen Sie nach Top-Level-Verzeichnissen auf und führen Sie mehrere aus:
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/{}/Acht parallele Kopien auf acht dedizierten Kernen sind hier die richtige Zahl; sechzehn sind nicht doppelt so schnell und machen die Quellmaschine für das, was sie noch bedient, unangenehm.
3. Die Datenbank, repliziert statt kopiert
Das Dumpen und Wiederherstellen von zweihundert Gigabyte Postgres bedeutet ein langes Fenster, in dem Schreibvorgänge verloren gehen. Streamen Sie stattdessen. Auf der Quelle:
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 postgresqlAuf dem Ziel:
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 postgresqlDas -R-Flag schreibt die Verbindungseinstellungen und die Standby-Signaldatendatei, sodass das Ziel als Replikat hochkommt und zu folgen beginnt. Von hier an bleibt es dauerhaft innerhalb von einer oder zwei Sekunden um die Quelle, was bedeutet, dass der Wechsel keine Datenbankbewegung mehr beinhaltet.
4. Wechsel
Starten Sie eine Sonde von einer dritten Maschine und lassen Sie sie laufen. Sie ist sowohl Ihre Verifizierung als auch Ihr Protokoll dessen, was der Wechsel kostet:
while true; do curl -s -o /dev/null -w "%{http_code} %{time_total}\n" https://app.example.com/health; sleep 1; done | tee cutover.logDann, in dieser Reihenfolge und ohne Pausen:
# 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"Die Schritte zwei bis fünf dauern einige Sekunden. Stoppen Sie nun den alten Host, während DNS propagiert, damit er keine veralteten Inhalte ausliefert, indem Sie ihn in einen Proxy für den neuen verwandeln:
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;
}
}Das ist das Stück, das das Ganze nicht störend macht. Jeder, der noch die alte Adresse auflöst, bekommt eine korrekte Antwort über den Tunnel statt eines Fehlers oder, schlimmer, einer Kopie der Daten, die zum Zeitpunkt des Wechsels aufgehört hat, aktualisiert zu werden. Ändern Sie jetzt den DNS-Eintrag.
Verifizieren
Beginnen Sie mit dem Sondenprotokoll, das Sie gesammelt haben:
sort cutover.log | uniq -c | sort -rn | headJede Zeile sollte 200 lauten. Einige langsamere Antworten während des Wechsels sind zu erwarten; jeder Nicht-200 bedeutet, dass Schritt fünf nach Schritt zwei mit zu großem Abstand begonnen hat, und der Proxy im vorherigen Abschnitt schrumpft diese Lücke auf nichts.
Dann beweisen Sie, dass die Daten identisch sind, nicht nur vorhanden:
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"Ein Probelauf, der nichts auflistet, bedeutet, dass die beiden Bäume bei Inhalt, Berechtigungen, Eigentümer und erweiterten Attributen übereinstimmen. Bytessummen sollten exakt übereinstimmen.
Datenbank als Nächstes:
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;"Die Wiederherstellung sollte auf dem Ziel nun false sein, und die Zeilenzahlen sollten übereinstimmen. Bestätigen Sie schließlich, dass der Verkehr wirklich gewechselt ist, statt stillschweigend für immer proxied zu werden:
dig +short app.example.com
tail -f /var/log/nginx/access.log | wc -l # on the old host, an hour laterWenn der alte Host für eine volle TTL plus einer komfortablen Marge inaktiv war, nehmen Sie den Proxy herunter und zerstören Sie die Instanz. Zerstören Sie sie nicht am selben Nachmittag; die billigste Versicherung in diesem gesamten Verfahren ist, die Quellmaschine intakt und ausgeschaltet für eine Woche zu lassen.
Danach
Zwei Terabyte über einen gut abgestimmten Langstreckenpfad sind ungefähr eine Stunde bei zehn Gigabit und in der Praxis eher länger, da die Quelle auch bedient. Zwischen benachbarten europäischen Standorten planen Sie einen Nachmittag; zwischen Kontinenten starten Sie abends und machen den Wechsel am nächsten Tag. Die Standorteseite listet die Roundtrip-Zeiten, die wir messen, und das sind die Zahlen, die Sie in die Tabelle in Schritt eins eintragen.