2 giờ sáng. Điện thoại rung. Node 1 của cụm Proxmox vừa chết — ổ cứng hỏng. 12 VM đang chạy trên đó, không có shared storage, không có SAN, không có gì hết.
Mình đã ở trong tình huống đó. Không phải production thật sự, may mắn là homelab — nhưng cảm giác nhìn toàn bộ VM offline cùng lúc thì không khác gì. Mình chạy homelab với Proxmox VE quản lý 12 VM và container — đây là playground để test mọi thứ trước khi đưa lên production. Và đêm đó là lúc mình bắt đầu nghiêm túc với Proxmox VE Replication.
Tại sao không cần SAN vẫn làm được HA?
Shared Storage (SAN/NFS) là giải pháp HA truyền thống: tất cả node đọc/ghi vào một storage chung. VM chết ở node này, node khác restart lên ngay — zero downtime. Nhưng SAN thì đắt, phức tạp, và với homelab hay SME không có ngân sách thì gần như không khả thi.
Proxmox VE Replication dùng ZFS send/receive để đồng bộ VM disk giữa các node theo chu kỳ cấu hình được (mặc định 15 phút). Cơ chế hoạt động như sau:
- Proxmox tạo ZFS snapshot trên node nguồn
- Gửi incremental snapshot sang node đích qua SSH tunnel được mã hóa
- Node đích luôn có bản sao gần nhất của VM disk (tối đa bằng interval đã set)
- Khi node nguồn chết → start VM trên node đích ngay, mất tối đa bằng khoảng thời gian của 1 sync cycle
Đây không phải live migration và không phải zero-downtime HA. Nhưng với RPO 15 phút và RTO tính bằng phút thay vì giờ, cộng với chi phí bằng 0, đây là lựa chọn thực tế cho hầu hết use case mà SAN không phải là option.
Yêu cầu trước khi bắt đầu
Cần đảm bảo đủ các điều kiện sau, thiếu một trong số này thì Replication sẽ không hoạt động:
- Proxmox Cluster đã được tạo — ít nhất 2 node đã join cluster
- ZFS Pool trên mỗi node — VM disk phải nằm trên ZFS storage, không phải LVM hay directory storage
- SSH key-based auth giữa các node — Proxmox tự cấu hình khi tạo cluster, thường không cần làm thủ công
- Đủ băng thông nội bộ — lần sync đầu sẽ copy toàn bộ disk, cần tính toán trước
Kiểm tra ZFS pool và cluster status trước khi làm:
# Xem ZFS pools đang có
zpool list
zpool status rpool
# Xem cluster nodes
pvecm status
pvecm nodes
Kiểm tra VM disk có đang dùng ZFS không (ví dụ VM ID 100):
qm config 100 | grep -E "scsi|virtio|ide|sata"
# Kết quả đúng sẽ thấy "local-zfs:" ở đầu:
# scsi0: local-zfs:vm-100-disk-0,size=32G
# Nếu thấy "local-lvm:" hay "local:" thì phải migrate disk sang ZFS trước
Cấu hình Replication từng bước
Tạo Replication Job qua Web UI
Cách nhanh nhất để bắt đầu:
- Vào Datacenter → Replication → Add
- Chọn VM cần replicate (chọn theo VM ID)
- Chọn Target — node đích trong cluster
- Chọn Schedule — mặc định
*/15tức mỗi 15 phút, có thể điều chỉnh - Click Create
Proxmox sẽ chạy sync ngay lập tức sau khi tạo. Lần đầu mất khá lâu vì phải gửi toàn bộ disk — sau đó chỉ gửi incremental changes nên nhanh hơn rất nhiều.
Cấu hình qua CLI cho nhiều VM cùng lúc
Khi cần setup hàng loạt hoặc scripted, dùng công cụ pvesr:
# Thêm replication job: VM 100, target pve-node2, mỗi 15 phút
pvesr create 100-0 --vmid 100 --target pve-node2 --schedule "*/15"
# Replication đến node thứ 3 (job thứ 2 cho cùng VM)
pvesr create 100-1 --vmid 100 --target pve-node3 --schedule "*/30"
# Xem toàn bộ jobs đang có
pvesr list
# Chạy sync ngay, không chờ schedule
pvesr run 100-0
Format job ID là <vmid>-<number>. Một VM có thể có nhiều replication job đến nhiều node khác nhau — hữu ích khi muốn replicate đến cả node 2 và node 3.
Giới hạn bandwidth cho replication
Bước này quan trọng mà hay bị bỏ qua. Nếu không giới hạn, lần sync đầu tiên (full copy) có thể ăn hết băng thông internal network, ảnh hưởng trực tiếp VM đang chạy production.
# Giới hạn bandwidth của storage (trong web UI: Datacenter → Storage → local-zfs → Edit)
# Hoặc chỉnh trực tiếp /etc/pve/storage.cfg:
# bwlimit: 102400 # KB/s, tức 100 MB/s
# Cách khác: giới hạn ở mức network interface với tc
tc qdisc add dev eth0 root tbf rate 200mbit burst 32kbit latency 400ms
Kiểm tra và Monitoring replication
Xem trạng thái real-time
# Status tất cả jobs trên node hiện tại
pvesr status
# Output mẫu:
# VMID STATE SOURCE TARGET DURATION FAIL
# 100 ok pve-node1 pve-node2 0:00:23 0
# 101 ok pve-node1 pve-node2 0:01:45 0
# 102 syncing pve-node1 pve-node2 - 0
# Xem log chi tiết của 1 job
journalctl -u pvesr@100-0 --since "2 hours ago" -f
Kiểm tra ZFS snapshots trên node đích
Đây là cách verify data thật sự đã đến node đích chưa — đừng chỉ tin vào UI:
# SSH vào node đích
ssh root@pve-node2
# Xem snapshots của VM được replicate
zfs list -t snapshot | grep vm-100
# Output mong muốn — thấy nhiều snapshot incremental:
# rpool/data/vm-100-disk-0@__replicate_100-0__1700000000 1.2G
# rpool/data/vm-100-disk-0@__replicate_100-0__1700000900 45M
# rpool/data/vm-100-disk-0@__replicate_100-0__1700001800 38M
Test failover thực tế — bước quan trọng nhất
Replication chưa test failover thì coi như không có. Đây là bài học đau nhất mình học được từ câu chuyện 2 giờ sáng đó — mình setup backup đầy đủ nhưng chưa bao giờ thử restore, và lúc cần thì mới phát hiện config sai.
Giả lập failover: migrate VM sang node đích, dùng ZFS dataset đã replicate sẵn:
# Cách 1: Qua web UI
# Chọn VM → More → Migrate → chọn node → tick "Allow Replication Overwrite"
# Cách 2: CLI — migrate VM 100 sang pve-node2, dùng local disk đã có
qm migrate 100 pve-node2 --with-local-disks 1
# VM sẽ dùng ZFS snapshot mới nhất trên node đích,
# không cần copy lại từ đầu — migration xong trong vài giây
Sau khi VM start thành công trên node 2, migrate ngược lại để trả VM về node gốc:
qm migrate 100 pve-node1 --with-local-disks 1
Script monitoring tự động
Tạo script kiểm tra định kỳ và alert khi có job fail:
#!/bin/bash
# /usr/local/bin/check-replication.sh
FAILED=$(pvesr status 2>/dev/null | awk 'NR>1 && $5 > 0 {print $1, "fail_count:", $5}')
if [ -n "$FAILED" ]; then
MSG="[REPLICATION ALERT] $(hostname): $FAILED"
# Gửi Telegram alert — thay YOUR_BOT_TOKEN và CHAT_ID
curl -s -X POST "https://api.telegram.org/bot${BOT_TOKEN}/sendMessage" \
-d "chat_id=${CHAT_ID}&text=${MSG}" > /dev/null
exit 1
fi
echo "$(date): All replication jobs OK"
exit 0
chmod +x /usr/local/bin/check-replication.sh
# Chạy mỗi 30 phút
echo "*/30 * * * * root /usr/local/bin/check-replication.sh >> /var/log/pve-replication.log 2>&1" \
> /etc/cron.d/proxmox-replication
Xử lý lỗi thường gặp
Lỗi: “Could not connect to host”
# Kiểm tra SSH từ node nguồn sang đích
ssh root@pve-node2 "echo OK"
# Nếu fail, refresh cluster certificates và SSH keys
pvecm updatecerts
# Xem authorized keys của cluster
cat /etc/pve/priv/authorized_keys
Lỗi: “target storage does not exist”
Thường xảy ra khi tên ZFS pool hoặc storage ID khác nhau giữa các node. Kiểm tra storage trên node đích:
pvesh get /nodes/pve-node2/storage
# Đảm bảo storage name khớp với cấu hình replication job
Job bị stuck ở trạng thái “syncing”
# Kill lock và chạy lại
pvesr finalize 100-0 --lock-timeout 1
pvesr run 100-0
# Nếu vẫn lỗi, xem log chi tiết
journalctl -u pvesr@100-0 -n 50
Với setup replication này, mình tự tin hơn nhiều khi chạy production workload trên bare-metal Proxmox không có shared storage. Không phải HA hoàn hảo như vSphere HA hay Proxmox HA với shared storage, nhưng với chi phí bằng 0 cho licensing và hardware, 15 phút RPO/RTO là đánh đổi hoàn toàn chấp nhận được — đặc biệt khi bạn đã test failover và biết chắc nó hoạt động trước lúc cần dùng thật.

