Dùng HAProxy Làm Load Balancer Cho Nhiều VPS Web: Health Check Và Failover

Cài HAProxy làm load balancer cho nhiều VPS web, cấu hình health check, round robin, failover và kiểm tra backend trước khi đưa traffic production.

Khi một website hoặc API đã vượt giới hạn của một VPS đơn lẻ, bước mở rộng tự nhiên là chạy nhiều backend và đặt load balancer phía trước. HAProxy là một lựa chọn phổ biến cho HTTP/TCP load balancing nhờ cấu hình rõ ràng, health check tích hợp và khả năng loại backend lỗi khỏi vòng phục vụ. Bài viết này hướng dẫn mô hình 1 HAProxy + 2 web server, cấu hình frontend/backend, health check, thuật toán cân bằng, log và quy trình test failover an toàn.

Điểm quan trọng Hãy lựa chọn dịch vụ dựa trên nhu cầu sử dụng thực tế và theo dõi tài nguyên thường xuyên để có hiệu quả tốt nhất.

Khi website hoặc API chạy trên một VPS duy nhất, toàn bộ traffic, application process và khả năng chịu lỗi đều phụ thuộc vào một máy. Nâng CPU/RAM có thể giúp trong một giai đoạn, nhưng tới một mức nào đó bạn sẽ muốn scale ngang: chạy nhiều web server và phân phối request giữa chúng.

HAProxy là một reverse proxy/load balancer hiệu năng cao cho HTTP và TCP. Với một cấu hình tương đối nhỏ, bạn có thể:

  • nhận traffic ở một đầu vào duy nhất;
  • phân phối request tới nhiều backend;
  • health check backend định kỳ;
  • tự loại backend lỗi khỏi vòng cân bằng;
  • đưa backend trở lại khi khỏe;
  • giới hạn connection hoặc gắn weight khác nhau.

Bài này tập trung vào mô hình đơn giản nhưng thực tế:

Internet
   |
HAProxy VPS
   |------ web01
   |------ web02

Nếu bạn đang dùng Nginx làm reverse proxy cho một backend duy nhất, có thể đọc trước bài Cài Nginx reverse proxy trên VPS Ubuntu. HAProxy trong bài này tập trung vào load balancing nhiều backend và failover.

Khi nào nên dùng HAProxy?

HAProxy phù hợp khi:

  • website/API đã có từ 2 backend trở lên;
  • muốn rollout từng node;
  • cần loại server lỗi tự động;
  • muốn tách load balancer khỏi application;
  • muốn cân bằng TCP như database proxy hoặc service non-HTTP trong một số mô hình;
  • cần kiểm soát weight, connection hoặc health check rõ ràng.

Không nên dựng load balancer chỉ vì “kiến trúc trông chuyên nghiệp hơn”. Nếu một VPS vẫn chạy nhẹ, load balancer tạo thêm một thành phần cần vận hành.

Load balancer có tự làm hệ thống high availability không?

Không hoàn toàn.

Nếu bạn chỉ có một HAProxy VPS, bản thân load balancer vẫn là single point of failure.

Mô hình này giúp backend web chịu lỗi tốt hơn, nhưng nếu HAProxy mất mạng hoặc reboot thì traffic vẫn gián đoạn.

Để tăng HA thực sự, có thể cần:

  • hai load balancer;
  • floating/virtual IP;
  • DNS failover;
  • anycast hoặc managed load balancer;
  • health check bên ngoài.

Bài hiện tại không cố biến kiến trúc nhỏ thành cluster HA phức tạp; mục tiêu là xây nền đúng trước.

Chuẩn bị 3 VPS

Ví dụ:

lb01     10.10.0.10
web01    10.10.0.21
web02    10.10.0.22

Tốt nhất các máy giao tiếp với nhau qua private network hoặc VPN riêng.

Chỉ lb01 cần nhận port 80/443 từ Internet trong mô hình này. web01 và web02 có thể chỉ cho phép HTTP từ IP private của load balancer.

Nếu bạn chưa có private network giữa các máy, có thể tham khảo Tailscale trên VPS Ubuntu hoặc mô hình mạng riêng của nhà cung cấp nếu có.

Chuẩn hóa hai web backend trước

Load balancer chỉ hoạt động tốt nếu các backend phục vụ cùng ứng dụng.

Bạn cần thống nhất:

  • source code;
  • environment variable;
  • runtime version;
  • static asset;
  • session strategy;
  • database endpoint;
  • health endpoint.

Nếu user login vào web01 nhưng request sau đi sang web02, session lưu local file có thể mất.

Với application nhiều node, thường nên đưa session ra storage dùng chung như Redis/database hoặc thiết kế stateless.

Cài HAProxy trên Ubuntu

Trên load balancer:

sudo apt update
sudo apt install -y haproxy

Kiểm tra:

haproxy -v
sudo systemctl status haproxy

File cấu hình mặc định thường là:

/etc/haproxy/haproxy.cfg

Backup trước khi sửa:

sudo cp /etc/haproxy/haproxy.cfg /etc/haproxy/haproxy.cfg.bak

Cấu hình HTTP load balancing cơ bản

Ví dụ:

global
    log /dev/log local0
    log /dev/log local1 notice
    daemon

    stats socket /run/haproxy/admin.sock mode 660 level admin


defaults
    log global
    mode http
    option httplog
    timeout connect 5s
    timeout client  30s
    timeout server  30s

frontend http_front
    bind *:80
    default_backend web_back

backend web_back
    balance roundrobin
    option httpchk GET /health
    http-check expect status 200

    server web01 10.10.0.21:80 check
    server web02 10.10.0.22:80 check

Điểm chính:

  • frontend nhận traffic từ client;
  • backend chứa pool server;
  • balance roundrobin chia request lần lượt;
  • check bật health check;
  • /health là endpoint để xác nhận app khỏe.

HAProxy documentation khuyến nghị thêm check ở các server line để backend lỗi được loại khỏi vòng phục vụ.

Health endpoint nên trả gì?

Một endpoint tốt nên:

  • phản hồi nhanh;
  • trả 200 khi app sẵn sàng;
  • không chạy query rất nặng;
  • không phụ thuộc quá nhiều dịch vụ bên ngoài;
  • phản ánh đủ để load balancer biết node có phục vụ được không.

Ví dụ Nginx đơn giản:

location = /health {
    access_log off;
    return 200 "ok\n";
}

Nếu cần kiểm tra application thật, endpoint có thể do app cung cấp.

Đừng để health check gọi một API ngoài Internet. Nếu API đó lỗi, cả backend có thể bị đánh dấu down dù website vẫn phục vụ được.

Round robin, leastconn hay weight?

roundrobin

Phù hợp khi các backend tương đương và request có thời gian gần giống nhau.

balance roundrobin

leastconn

Ưu tiên server đang có ít connection hơn.

balance leastconn

Hữu ích với connection dài hoặc request không đồng đều.

Weight

Nếu web01 mạnh hơn web02:

server web01 10.10.0.21:80 check weight 2
server web02 10.10.0.22:80 check weight 1

Đừng dùng weight như cách chữa backend chậm vì lỗi code; hãy sửa nguyên nhân trước.

Health check TCP và HTTP khác nhau thế nào?

Chỉ dùng:

server web01 10.10.0.21:80 check

thì HAProxy có thể kiểm tra TCP connection.

Điều đó chỉ chứng minh port 80 nhận connection, không chắc ứng dụng trả HTTP bình thường.

HTTP health check sâu hơn:

option httpchk GET /health
http-check expect status 200

Với website production, HTTP check thường hữu ích hơn TCP check đơn thuần.

rise và fall

Bạn có thể kiểm soát số lần thành công/thất bại liên tiếp trước khi đổi trạng thái.

Ví dụ:

server web01 10.10.0.21:80 check fall 3 rise 2

Ý nghĩa:

  • fail 3 lần liên tiếp → server down;
  • pass 2 lần liên tiếp → server up lại.

Điều này tránh một packet loss ngắn làm node bị loại ngay.

Validate cấu hình trước reload

Luôn chạy:

sudo haproxy -c -f /etc/haproxy/haproxy.cfg

Nếu config valid, reload:

sudo systemctl reload haproxy

Không restart mù quáng sau mỗi thay đổi. Reload giúp giảm gián đoạn connection hiện tại.

Test phân phối request

Trên web01, tạo response khác để kiểm tra tạm:

echo web01 | sudo tee /var/www/html/index.html

Trên web02:

echo web02 | sudo tee /var/www/html/index.html

Từ client:

for i in $(seq 1 6); do curl -s http://IP_LOAD_BALANCER; done

Với round robin, bạn thường thấy hai backend được luân phiên.

Sau test, trả nội dung app thật về bình thường.

Test failover an toàn

Trong staging hoặc maintenance window, dừng web server trên web02:

sudo systemctl stop nginx

Theo dõi log HAProxy:

sudo journalctl -u haproxy -f

Request mới nên chỉ đi web01 sau khi health check đánh dấu web02 down.

Khởi động lại:

sudo systemctl start nginx

Sau số lần rise thành công, node sẽ trở lại pool.

Firewall backend

Giả sử load balancer có IP private 10.10.0.10.

Trên web01/web02:

sudo ufw allow from 10.10.0.10 to any port 80 proto tcp

Nếu backend không cần nhận HTTP public trực tiếp, xóa rule mở 80 từ Internet chỉ sau khi test load balancer thành công.

Giữ console/recovery access trước khi chỉnh firewall.

Nếu chưa quen UFW, xem bài Cài UFW Firewall trên VPS Ubuntu.

HTTPS nên terminate ở đâu?

Hai mô hình phổ biến:

TLS termination tại HAProxy

Client HTTPS → HAProxy TLS → HTTP/HTTPS backend

Ưu điểm:

  • quản lý certificate tập trung;
  • backend đơn giản hơn.

TLS passthrough

Client TLS → HAProxy TCP → backend TLS

Phù hợp khi backend tự quản lý TLS hoặc cần end-to-end TLS đặc thù.

Với website thông thường, terminate TLS tại HAProxy là mô hình dễ quản lý.

Ví dụ bind HTTPS

Sau khi đã có certificate PEM phù hợp:

frontend https_front
    bind *:443 ssl crt /etc/haproxy/certs/example.pem
    default_backend web_back

File PEM thường phải chứa certificate và private key theo format HAProxy yêu cầu.

Giới hạn permission file cẩn thận:

sudo chmod 600 /etc/haproxy/certs/example.pem

Không đưa private key vào Git.

Forward client IP

Backend cần biết IP client thật.

Trong HTTP mode:

option forwardfor

HAProxy sẽ thêm X-Forwarded-For.

Backend chỉ nên trust header này từ load balancer đáng tin cậy, không từ Internet trực tiếp.

Nếu Nginx backend cần real IP, cấu hình trusted proxy đúng IP HAProxy.

Sticky session có nên dùng không?

Có thể cấu hình cookie/stick table để user quay lại cùng backend, nhưng sticky session thường che thiết kế stateful.

Nếu có thể, tốt hơn là:

  • session nằm ở Redis/database;
  • upload nằm object storage/shared filesystem;
  • app stateless.

Sticky session chỉ nên dùng khi ứng dụng legacy thực sự cần.

HAProxy stats

HAProxy có stats socket và có thể bật stats page nếu cần.

Ví dụ stats page:

listen stats
    bind 127.0.0.1:8404
    stats enable
    stats uri /stats

Bind localhost giúp tránh public dashboard.

Truy cập qua SSH tunnel:

ssh -L 8404:127.0.0.1:8404 admin@lb01

Sau đó mở http://127.0.0.1:8404/stats.

Monitoring load balancer

Theo dõi:

  • request rate;
  • backend status;
  • connection queue;
  • 4xx/5xx;
  • response time;
  • CPU/RAM trên load balancer;
  • network throughput.

Nếu bạn đã dùng Prometheus/Grafana, có thể bổ sung HAProxy exporter hoặc metric endpoint phù hợp. Xem bài Giám sát VPS bằng Prometheus và Grafana.

Deployment không downtime với HAProxy

Load balancer giúp triển khai từng node:

  1. disable web02 khỏi pool;
  2. deploy code web02;
  3. health check;
  4. đưa web02 vào lại;
  5. lặp với web01.

Cách này giảm rủi ro hơn restart toàn bộ web tier cùng lúc.

Nếu bạn đã tự động deploy bằng GitHub Actions, xem bài Deploy VPS bằng GitHub Actions.

Database có cần load balance giống web server không?

Không nên áp cùng tư duy một cách máy móc.

Database có read/write consistency, replication lag, transaction và failover phức tạp hơn.

Đừng chỉ đặt hai PostgreSQL/MySQL vào backend round robin rồi nghĩ đó là HA database.

Sai lầm thường gặp

Hai backend không đồng bộ code

User nhận behavior khác nhau tùy node.

Health check chỉ kiểm tra port

Port mở nhưng app đã lỗi vẫn được nhận traffic.

Session lưu local

Login hoặc cart biến mất khi request sang node khác.

Chỉ có một HAProxy nhưng gọi hệ thống “HA hoàn toàn”

Load balancer vẫn là SPOF.

Backend vẫn public toàn bộ port

Attacker có thể bypass load balancer/WAF nếu biết IP backend.

Checklist production

  • Hai backend chạy cùng phiên bản app.
  • Session/state không phụ thuộc local node nếu có thể.
  • HAProxy dùng private IP tới backend.
  • Health endpoint nhẹ và đúng nghĩa.
  • haproxy -c pass trước reload.
  • Test một backend down.
  • Backend firewall chỉ cho nguồn cần thiết.
  • Theo dõi HAProxy metric/log.
  • Có backup config.
  • Có kế hoạch cho SPOF của load balancer.

FAQ

HAProxy và Nginx có giống nhau không?

Cả hai đều có thể reverse proxy và load balance. HAProxy tập trung mạnh vào proxy/load balancing, còn Nginx cũng là web server và static content server. Chọn theo kiến trúc và kỹ năng team.

Round robin có luôn tốt nhất không?

Không. Nếu connection dài hoặc backend khác cấu hình, leastconn hoặc weight có thể phù hợp hơn.

Backend down thì HAProxy có tự bỏ ra không?

Có nếu bạn bật health check bằng check và cấu hình phù hợp.

HAProxy có làm website không downtime tuyệt đối không?

Không. Nó giúp backend failover nhưng chính load balancer, database, network và DNS vẫn có failure mode.

Có thể chạy HAProxy và Nginx trên cùng VPS không?

Có thể, nhưng phải phân biệt port và vai trò. Thường HAProxy ở edge, Nginx ở backend hoặc mỗi thành phần trên máy riêng.

Kết luận

HAProxy là bước mở rộng hợp lý khi một website/API đã có nhiều backend VPS. Health check giúp tự loại node lỗi, còn các thuật toán như round robin và leastconn giúp phân phối traffic theo workload.

Hãy bắt đầu với kiến trúc nhỏ, private network, health endpoint đúng nghĩa và test failover thật trước khi gọi hệ thống là sẵn sàng production.

Nếu bạn đang mở rộng từ một VPS sang nhiều web node, có thể tham khảo các dịch vụ VPS tại HUONG CLOUD và lựa chọn tài nguyên cho từng tầng dựa trên traffic và metric thực tế.

Nguồn tham khảo

Kết luận

Nếu chưa chắc cấu hình hoặc loại dịch vụ nào phù hợp, hãy gửi nhu cầu thực tế để đội ngũ hỗ trợ tư vấn trước khi mua.

Chưa biết nên chọn gói nào?

Xem bảng giá VPS hoặc liên hệ đội ngũ hỗ trợ để chọn cấu hình phù hợp.

Xem bảng giá VPS →