Cơn ác mộng Single Point of Failure (SPOF) lúc nửa đêm
Đúng 23h đêm Black Friday 2023, server reverse proxy Nginx của bên mình nổ bộ nguồn. Phía sau là cụm 4 node backend và database cluster chạy mượt mà, tải CPU chưa tới 30%. Dù vậy, khách hàng lập tức bị chặn đứng bằng lỗi Connection timed out. Lý do rất đơn giản: domain trỏ thẳng vào IP public duy nhất của con proxy đó. Cổng vào sập, cả hệ thống tê liệt.
Mình vội mở dashboard Cloudflare đổi bản ghi A sang IP server dự phòng. Dù Cloudflare cập nhật bản ghi chỉ mất vài giây, khách truy cập qua mạng nhà mạng trong nước vẫn dính cache gần 10 phút. Khoảng 350 đơn hàng bốc hơi. Doanh thu rơi mất hơn 120 triệu đồng. Đó là cái giá phải trả cho một kiến trúc còn tồn tại điểm chết đơn độc (SPOF).
Tại sao DNS Failover không thể cứu nguy kịp thời?
Nhiều bạn nghĩ đơn giản: “Cần gì phức tạp, cứ dùng DNS Round-robin hoặc viết cron job tự đổi bản ghi qua API Cloudflare/Route53 là xong!”. Nhưng thực tế vận hành luôn phơi bày 3 lỗ hổng chí mạng:
- Client và ISP cố chấp cache DNS: Các nhà mạng như VNPT, Viettel, FPT và trình duyệt client thường bỏ qua thông số TTL ngắn (60s). Rất nhiều phiên truy cập bị kẹt lại IP chết suốt 15-30 phút.
- Mù trạng thái dịch vụ (Service Health): DNS chỉ phân giải IP. Nó không thể nhận biết Nginx trên server còn sống hay vừa crash vì cạn RAM (OOM Killer).
- Độ trễ phát hiện quá lớn: Healthcheck script cần 3-5 lần ping/curl thất bại mới kích hoạt đổi IP. Cộng thêm thời gian gọi API, thời gian downtime thực tế thường vượt quá 3-5 phút.
Bản chất vấn đề nằm ở tầng mạng. Chúng ta không thể giao phó tính sẵn sàng cao cho DNS ở tầng ứng dụng bên ngoài. Thay vào đó, hãy dùng Virtual IP (VIP) ngay trong mạng nội bộ. Ở tầng này, các server tự thương thảo và hoán đổi quyền điều khiển chỉ trong vài mili-giây.
3 giải pháp High Availability cho Gateway và bài toán lựa chọn
Trên môi trường Linux, kỹ sư hệ thống thường cân nhắc giữa 3 phương án:
- Cloud Load Balancer (AWS ALB, GCP LB): Cực kỳ nhàn, nhà cung cấp cam kết SLA tới 99.99%. Điểm trừ là chi phí tăng vọt khi throughput lớn (vài trăm Mbps trở lên). Hơn nữa, bạn không thể áp dụng cách này trên cụm On-Premises, server thuê riêng (Dedicated) ở Viettel IDC, CMC hay cụm ảo hóa Proxmox/KVM tự dựng.
- Pacemaker + Corosync: Giải pháp clustering chuẩn doanh nghiệp, mạnh về split-brain fencing và quản lý tài nguyên phức tạp. Đổi lại, cấu hình tương đối rối rắm. Với cụm chỉ có 2 node, bạn rất dễ dính lỗi mất quorum nếu không cấu hình qdevice chuẩn xác.
- Keepalived (giao thức VRRP): Gọn nhẹ, chiếm chưa tới 20MB RAM, cấu hình gói gọn trong một file duy nhất. Keepalived liên tục bắn heartbeat qua mạng nội bộ. Khi máy chính gặp sự cố, máy phụ kéo Virtual IP về card mạng của mình chỉ sau 1-2 giây.
Cách triển khai Keepalived + VIP chuẩn trên Ubuntu Server
Với hầu hết hệ thống web vừa và lớn dùng Nginx hoặc HAProxy, Keepalived là lựa chọn tối ưu giữa độ ổn định và chi phí vận hành. Dưới đây là mô hình Master – Backup chuẩn bạn có thể áp dụng ngay.
Thông số mạng giả định
- Node 01 (Master): IP
192.168.1.11, card mạngeth0 - Node 02 (Backup): IP
192.168.1.12, card mạngeth0 - Virtual IP (VIP dùng chung): IP
192.168.1.100(đây là địa chỉ IP công khai cho client hoặc trỏ DNS về)
Bước 1: Cài đặt Keepalived
Cài đặt gói dịch vụ trực tiếp từ kho apt trên cả hai node:
sudo apt update
sudo apt install -y keepalived psmisc
Lưu ý: Gói psmisc cung cấp lệnh killall, công cụ cần thiết cho script kiểm tra tiến trình Nginx ở bước sau.
Bước 2: Bật tính năng Non-local IP binding
Mặc định, Linux chặn tiến trình bind vào địa chỉ IP chưa gán lên card mạng. Nếu Node 02 chưa giữ VIP, Nginx trên máy đó sẽ không khởi động được. Bật cờ ip_nonlocal_bind để xử lý vấn đề này:
echo "net.ipv4.ip_nonlocal_bind=1" | sudo tee -a /etc/sysctl.conf
sudo sysctl -p
Bước 3: Cấu hình Node Master (192.168.1.11)
Tạo mới file cấu hình chính tại /etc/keepalived/keepalived.conf:
sudo nano /etc/keepalived/keepalived.conf
Nội dung cấu hình:
global_defs {
router_id lb01
enable_script_security
script_user root
}
vrrp_script check_nginx {
script "/usr/bin/killall -0 nginx"
interval 2
weight -20
fall 2
rise 2
}
vrrp_instance VI_WEB {
state MASTER
interface eth0
virtual_router_id 51
priority 101
advert_int 1
authentication {
auth_type PASS
auth_pass M@tKhauB@oMat123
}
virtual_ipaddress {
192.168.1.100/24 dev eth0 label eth0:vip
}
track_script {
check_nginx
}
}
Điểm cốt lõi cần lưu ý:
virtual_router_id 51: ID định danh của nhóm VRRP. Giá trị này phải đồng nhất giữa Master và Backup (dải từ 1 đến 255).priority 101: Mức ưu tiên. Node nào có priority cao hơn sẽ giữ VIP.vrrp_script check_nginx: Kiểm tra Nginx mỗi 2 giây. Nếu Nginx dừng, priority giảm 20 điểm (xuống 81). Mức 81 thấp hơn 100 của Backup, kích hoạt quá trình bàn giao VIP ngay lập tức.
Bước 4: Cấu hình Node Backup (192.168.1.12)
Tạo file tương tự trên Node 02:
sudo nano /etc/keepalived/keepalived.conf
Nội dung file:
global_defs {
router_id lb02
enable_script_security
script_user root
}
vrrp_script check_nginx {
script "/usr/bin/killall -0 nginx"
interval 2
weight -20
fall 2
rise 2
}
vrrp_instance VI_WEB {
state BACKUP
interface eth0
virtual_router_id 51
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass M@tKhauB@oMat123
}
virtual_ipaddress {
192.168.1.100/24 dev eth0 label eth0:vip
}
track_script {
check_nginx
}
}
Khác biệt duy nhất: state đổi thành BACKUP và priority giảm xuống 100.
Bước 5: Khởi động dịch vụ và kiểm tra trạng thái
Bật service Keepalived trên cả 2 máy:
sudo systemctl enable --now keepalived
Kiểm tra card mạng của Node 01 (Master):
ip addr show eth0
Dòng IP phụ 192.168.1.100/24 sẽ xuất hiện kèm nhãn eth0:vip. Chạy lệnh tương tự trên Node Backup, bạn sẽ thấy card mạng chỉ có IP tĩnh gốc.
Kiểm thử kịch bản rớt mạng (Failover test)
Mở terminal trên máy client và gõ lệnh ping liên tục tới VIP:
ping 192.168.1.100
Trên Node 01, chủ động tắt Nginx để kích hoạt kịch bản lỗi:
sudo systemctl stop nginx
Hãy nhìn terminal ping. Quá trình truyền gói chỉ mất đúng 1 nhịp (timeout tầm 1 giây). Kiểm tra lại bằng ip addr show eth0 trên Node 02: VIP 192.168.1.100 đã được gán sang máy phụ. Client gửi request HTTP vẫn nhận phản hồi 200 OK bình thường.
Sau khi bạn bật lại Nginx trên Node 01 (sudo systemctl start nginx), priority của Master phục hồi về 101. VIP lập tức được thu hồi về Node 01 nhờ cơ chế preempt. Hệ thống của bạn giờ đây đã sẵn sàng tự phục hồi trước mọi sự cố phần cứng gateway.

