Cái này tạo ra cái gì
Hai terabyte tệp và một cơ sở dữ liệu Postgres trực tiếp được chuyển từ trang này sang trang khác, trong khi ứng dụng vẫn trả lời các yêu cầu trong suốt quá trình. Phương pháp là sao chép trước hàng loạt trong khi nguồn vẫn phục vụ, một bản sao luồng duy trì đồng bộ và chuyển đổi được đo bằng giây với máy chủ cũ làm proxy tới máy chủ mới cho đến khi DNS bắt kịp.
Khoảng cách là phần thú vị. Giữa AMS-01 và FRA-01, vòng khứ hồi là bảy mili giây và một luồng duy nhất sẽ lấp đầy một cổng. Chạy cùng một bản sao đó tới GRU-01, nơi vòng khứ hồi gần hai trăm mili giây, và một quá trình truyền không được điều chỉnh sẽ chậm chạp chỉ bằng một phần nhỏ so với những gì bạn đang trả trong khi cả hai máy gần như nhàn rỗi. Khoảng cách đó hoàn toàn phụ thuộc vào lượng dữ liệu mà một kết nối được phép xử lý cùng lúc (trên đường truyền).
Trước khi bắt đầu
- Máy chủ nguồn và đích, một đường hầm giữa chúng và quyền root trên cả hai.
- DNS bạn kiểm soát, với TTL của bản ghi được giảm xuống sáu mươi giây ít nhất một ngày trước đó. Đây là bước mọi người bỏ qua và sau đó phải chờ sáu giờ.
- Đủ dung lượng đĩa trên máy chủ đích cho toàn bộ dữ liệu và cả bản sao.
1. Xác định khả năng của liên kết
Tích của băng thông và độ trễ (bandwidth-delay product) quyết định mọi thứ. Nhân thời gian vòng khứ hồi với tốc độ bạn muốn và bạn nhận được lượng dữ liệu phải được gửi đi mà chưa nhận xác nhận (in flight) tại bất kỳ thời điểm nào:
ping -c20 target.example.com | tail -1| Đường đi | RTT | Dữ liệu trong luồng cho 1 Gbit/s | Cửa sổ kernel mặc định |
|---|---|---|---|
| AMS-01 tới FRA-01 | 7 ms | 0.9 MB | Đủ |
| AMS-01 tới NYC-01 | 76 ms | 9.5 MB | Không đủ |
| AMS-01 tới SIN-01 | 168 ms | 21 MB | Không đủ |
| AMS-01 tới GRU-01 | 196 ms | 24.5 MB | Không đủ |
Trên cả hai máy:
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 thay vì kiểm soát tắc nghẽn mặc định quan trọng trên các đường dài có bất kỳ mất gói nào, vì các thuật toán dựa trên mất gói (loss-based) coi một gói bị rơi là tắc nghẽn và giảm cửa sổ của chúng xuống một nửa. Trên hai trăm mili giây, việc phục hồi mất nhiều giây và nó xảy ra liên tục.
Đo trước khi bạn đầu tư hai terabyte cho một giả định:
# target
apt install -y iperf3 && iperf3 -s
# source
iperf3 -c target.example.com -P 8 -t 30Tám luồng song song nên đạt gần tốc độ cổng. Nếu một luồng đạt một trăm megabit và tám luồng đạt tám trăm, cài đặt cửa sổ đã không có hiệu lực; một luồng duy nhất nên tự nó đạt được gần hết tốc độ khi các cài đặt đó có hiệu lực.
2. Sao chép trước hàng loạt
Chạy việc này với nguồn đang hoạt động. Nó sẽ mất hàng giờ và không có gì bị gián đoạn trong khi nó chạy:
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/Việc chọn thuật toán mã hóa không phải là mê tín. Trên các bộ vi xử lý này, chế độ GCM được tăng tốc phần cứng di chuyển vài gigabyte mỗi giây mỗi lõi, trong khi thuật toán mặc định được thương lượng trên một số phiên bản client chậm hơn rõ rệt và biến quá trình truyền của bạn thành một bài kiểm tra đơn lõi. Nén đã tắt vì dữ liệu đã được nén và nếu không, CPU sẽ dành thời gian cho việc đó thay vì di chuyển byte.
Đối với hàng triệu tệp nhỏ, một luồng là hình dạng sai. Chia theo thư mục cấp cao nhất và chạy nhiều luồng:
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/{}/Tám bản sao song song trên tám lõi chuyên dụng là con số đúng ở đây; mười sáu không nhanh gấp đôi và sẽ làm cho máy nguồn khó chịu cho bất cứ điều gì nó vẫn đang phục vụ.
3. Cơ sở dữ liệu, nhân bản thay vì sao chép
Việc dump và restore hai trăm gigabyte Postgres có nghĩa là một khoảng thời gian dài mà các ghi dữ liệu bị mất. Thay vào đó hãy truyền luồng (stream) nó. Trên nguồn:
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 postgresqlTrên đích:
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 postgresqlCờ -R ghi các cài đặt kết nối và tệp tín hiệu standby, do đó máy đích khởi động như một bản sao và bắt đầu theo dõi. Từ đây nó duy trì trong vòng một hoặc hai giây so với nguồn vô thời hạn, điều này có nghĩa là việc chuyển đổi không còn liên quan đến việc di chuyển cơ sở dữ liệu chút nào.
4. Chuyển đổi
Bắt đầu một chương trình thăm dò (probe) từ một máy thứ ba và để nó chạy. Nó vừa là kiểm tra xác minh của bạn vừa là bản ghi về chi phí của quá trình chuyển đổi:
while true; do curl -s -o /dev/null -w "%{http_code} %{time_total}\n" https://app.example.com/health; sleep 1; done | tee cutover.logSau đó, theo thứ tự này và không dừng lại:
# 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"Các bước từ hai đến năm mất vài giây. Bây giờ ngăn máy chủ cũ phục vụ nội dung cũ trong khi DNS lan truyền, bằng cách biến nó thành proxy cho máy chủ mới:
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;
}
}Đây là phần làm cho toàn bộ quá trình không gián đoạn. Bất kỳ ai vẫn phân giải địa chỉ cũ sẽ nhận được câu trả lời chính xác qua đường hầm thay vì lỗi hoặc tệ hơn, một bản sao dữ liệu đã ngừng cập nhật tại thời điểm chuyển đổi. Bây giờ thay đổi bản ghi DNS.
Kiểm tra xác minh
Bắt đầu với nhật ký chương trình thăm dò bạn đã thu thập:
sort cutover.log | uniq -c | sort -rn | headMỗi dòng phải đọc là 200. Một vài phản hồi chậm hơn trong quá trình chuyển đổi là dự kiến; bất kỳ mã khác 200 có nghĩa là bước năm bắt đầu sau bước hai với biên độ quá rộng, và proxy trong phần trước là thứ thu hẹp khoảng cách đó xuống còn không.
Sau đó chứng minh dữ liệu là giống hệt nhau chứ không chỉ là có mặt:
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"Chạy thử khô (dry run) không liệt kê gì có nghĩa là hai cây thư mục khớp nhau về nội dung, quyền hạn, quyền sở hữu và các thuộc tính mở rộng. Tổng số byte phải khớp chính xác.
Cơ sở dữ liệu tiếp theo:
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;"Trạng thái phục hồi bây giờ phải là false trên máy đích và số hàng phải khớp. Cuối cùng, xác nhận rằng lưu lượng đã thực sự chuyển sang máy mới chứ không phải bị proxy vĩnh viễn:
dig +short app.example.com
tail -f /var/log/nginx/access.log | wc -l # on the old host, an hour laterKhi máy chủ cũ đã chạy rảnh trong một TTL đầy đủ cộng với một khoảng thời gian thoải mái, hãy gỡ proxy xuống và hủy thể hiện (instance). Đừng hủy nó vào cùng buổi chiều; bảo hiểm rẻ nhất trong toàn bộ quy trình này là để máy nguồn nguyên vẹn và tắt nguồn trong một tuần.
Sau đó
Hai terabyte trên một đường dài được điều chỉnh tốt là khoảng một giờ ở mười gigabit và thực tế lâu hơn một chút, vì nguồn cũng đang phục vụ. Giữa các trang châu Âu lân cận, hãy dự kiến một buổi chiều; giữa các lục địa, hãy bắt đầu vào buổi tối và thực hiện chuyển đổi vào ngày hôm sau. Trang vị trí liệt kê thời gian vòng khứ hồi mà chúng tôi đo được và đó là những con số để đưa vào bảng ở bước một.