Keepalived & VRRP: Xây dựng Floating IP cho High Availability trên Linux

Networking tutorial - IT technology blog
Networking tutorial - IT technology blog

Tại Sao Dịch Vụ Của Bạn Cần Một IP Dự Phòng

Hãy tưởng tượng: bạn có một load balancer hoặc server gateway quan trọng đang chạy trên production. Lúc 2 giờ sáng, máy đột ngột sập. Toàn bộ dịch vụ phía sau nó tê liệt. Người dùng bắt đầu nhận lỗi. Điện thoại bạn réo không ngừng.

Giải pháp nghe có vẻ đơn giản — giữ sẵn một server dự phòng để tiếp quản. Cái khó hơn là làm sao để địa chỉ IP tự động chuyển theo khi failover xảy ra. Đó chính xác là bài toán mà KeepalivedVRRP giải quyết.

VRRP (Virtual Router Redundancy Protocol) cho phép hai hoặc nhiều server dùng chung một địa chỉ IP ảo — còn gọi là floating IP hay VIP. Một server đóng vai MASTER và sở hữu VIP đó. Nếu nó sập, server BACKUP phát hiện sự im lặng và giành lấy VIP trong vòng 2–3 giây. Không cần can thiệp thủ công. Không cần thay đổi DNS. Không cần cấu hình lại phía client.

Keepalived là implementation VRRP mã nguồn mở được dùng rộng rãi nhất trên Linux. Tôi đã chạy nó trên production để bảo vệ các HAProxy load balancer, Nginx reverse proxy, và các TCP service tùy chỉnh — đây là loại công cụ bạn cài một lần rồi quên đi, cho đến ngày nó lặng lẽ cứu bạn lúc 2 giờ sáng.

Hướng dẫn này dùng hai server Ubuntu/Debian, nhưng các bước tương tự áp dụng được cho CentOS/RHEL với một vài tên package khác nhau.

Cài Đặt

Môi Trường Lab

Bạn cần hai server Linux trên cùng một network segment. Đây là cấu hình chúng ta sẽ dùng:

  • node1 — 192.168.1.10 (MASTER ban đầu)
  • node2 — 192.168.1.11 (BACKUP)
  • Virtual IP (VIP) — 192.168.1.100 (địa chỉ nổi mà các dịch vụ của bạn trỏ tới)

Client luôn kết nối tới 192.168.1.100. Họ không cần biết node vật lý nào đang đứng sau nó. Keepalived xử lý điều đó một cách trong suốt.

Cài Keepalived Trên Cả Hai Node

Chạy lệnh này trên cả node1 lẫn node2:

# Ubuntu / Debian
sudo apt update
sudo apt install -y keepalived

# CentOS / RHEL / AlmaLinux
sudo dnf install -y keepalived

Keepalived cần bind vào một IP chưa tồn tại trên interface. Bật cài đặt kernel này trên cả hai node:

# Cho phép bind vào IP không thuộc local (bắt buộc cho VIP)
echo 'net.ipv4.ip_nonlocal_bind = 1' | sudo tee /etc/sysctl.d/99-keepalived.conf
sudo sysctl --system

Cấu Hình

Cấu Hình Node MASTER (node1)

Mở file cấu hình Keepalived trên node1:

sudo nano /etc/keepalived/keepalived.conf

Dán cấu hình sau vào:

global_defs {
  router_id node1
}

vrrp_instance VI_1 {
  state MASTER
  interface eth0          # thay bằng tên NIC thực tế của bạn
  virtual_router_id 51   # phải giống nhau trên cả hai node
  priority 100           # giá trị cao hơn = ưu tiên làm master
  advert_int 1           # gửi VRRP advertisement mỗi 1 giây

  authentication {
    auth_type PASS
    auth_pass SecretKey123   # phải giống nhau trên cả hai node
  }

  virtual_ipaddress {
    192.168.1.100/24       # địa chỉ VIP nổi
  }
}

Bốn điều cần lưu ý trước khi tiếp tục:

  • interface eth0 — kiểm tra tên NIC bằng ip link show. VM trên cloud thường dùng ens3 hoặc enp0s3.
  • virtual_router_id 51 — ID nhóm, từ 1–255. Cả hai node phải dùng cùng giá trị. Chọn một giá trị chưa được dùng trên network segment của bạn.
  • priority 100 — node có priority cao nhất giành vai trò MASTER. node2 sẽ được đặt là 90, nên node1 luôn được ưu tiên.
  • auth_pass — mật khẩu dùng chung để chặn các gói VRRP giả mạo. Phải giống nhau ở cả hai phía, không có ngoại lệ.

Cấu Hình Node BACKUP (node2)

Trên node2, cấu hình gần như giống hệt. Chỉ thay đổi hai giá trị: statepriority.

global_defs {
  router_id node2
}

vrrp_instance VI_1 {
  state BACKUP
  interface eth0
  virtual_router_id 51
  priority 90            # thấp hơn node1
  advert_int 1

  authentication {
    auth_type PASS
    auth_pass SecretKey123
  }

  virtual_ipaddress {
    192.168.1.100/24
  }
}

Khởi Động và Bật Keepalived

Trên cả hai node:

sudo systemctl enable keepalived
sudo systemctl start keepalived

Tùy Chọn: Script Kiểm Tra Sức Khỏe

Sự cố ở cấp server đã được xử lý. Nhưng nếu Nginx crash trong khi OS vẫn chạy bình thường thì sao? Track scripts của Keepalived xử lý đúng trường hợp này — chúng giám sát một tiến trình và tự động giảm priority của node nếu dịch vụ chết.

Thêm block này trên cả hai node, đặt trước block vrrp_instance:

vrrp_script check_nginx {
  script "/usr/bin/pgrep nginx"
  interval 2      # kiểm tra mỗi 2 giây
  weight -20      # trừ 20 khỏi priority nếu kiểm tra thất bại
  fall 2          # cần 2 lần thất bại liên tiếp mới kích hoạt
  rise 2          # cần 2 lần thành công liên tiếp mới phục hồi
}

Tham chiếu nó bên trong block vrrp_instance:

vrrp_instance VI_1 {
  ...
  track_script {
    check_nginx
  }
}

Phép tính như sau: nếu Nginx dừng trên node1, priority hiệu dụng của nó giảm từ 100 xuống 80 (100 − 20). Thấp hơn mức 90 của node2. Keepalived kích hoạt failover và chuyển VIP — dù OS của node1 vẫn đang chạy tốt.

Reload sau mỗi lần thay đổi cấu hình:

sudo systemctl reload keepalived

Kiểm Tra và Giám Sát

Xem Node Nào Đang Giữ VIP

Trên node1, chạy:

ip addr show eth0

Bạn sẽ thấy VIP xuất hiện bên cạnh IP chính:

2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP>
    inet 192.168.1.10/24 brd 192.168.1.255 scope global eth0
    inet 192.168.1.100/24 scope global secondary eth0

Trên node2, VIP sẽ không xuất hiện — nó đang ở trạng thái BACKUP, chờ đợi.

Kiểm Tra Failover

Dừng Keepalived trên node1 để giả lập sự cố:

# Trên node1
sudo systemctl stop keepalived

Chuyển sang node2 và kiểm tra:

# Trên node2
ip addr show eth0

Trong vòng 2–3 giây, 192.168.1.100 sẽ xuất hiện trên node2. Khởi động lại node1 và VIP sẽ quay về — priority 100 của nó vượt qua mức 90 của node2:

# Trên node1
sudo systemctl start keepalived

Giám Sát Qua Log Keepalived

Các chuyển đổi trạng thái được ghi vào syslog. Theo dõi trực tiếp:

sudo journalctl -u keepalived -f

Trong quá trình failover bạn sẽ thấy nội dung tương tự:

keepalived[1234]: VRRP_Instance(VI_1) Transition to MASTER STATE
keepalived[1234]: VRRP_Instance(VI_1) Entering MASTER STATE
keepalived[1234]: VRRP_Instance(VI_1) Sending gratuitous ARP

Dòng cuối — gratuitous ARP — chính là thứ làm cho failover trở nên trong suốt. Keepalived broadcast một bản cập nhật ARP thông báo cho toàn bộ thiết bị trên mạng rằng 192.168.1.100 giờ nằm ở một địa chỉ MAC mới. Switch cập nhật bảng ARP. Client kết nối lại. Không ai phải đụng tay vào file cấu hình.

Kiểm Tra Trạng Thái VRRP Trực Tiếp

Để xem nhanh trạng thái mà không cần đọc log:

sudo kill -USR1 $(cat /var/run/keepalived.pid)
sudo cat /tmp/keepalived.data | grep State

Các phiên bản mới hơn cung cấp stats socket:

sudo keepalived --dump-conf

Các Vấn Đề Thường Gặp Cần Lưu Ý

  • Cả hai node đều trở thành MASTER (split-brain) — hầu như luôn là vấn đề firewall. VRRP dùng IP protocol 112 và địa chỉ multicast 224.0.0.18. Nếu bị chặn, mỗi node nghĩ node kia đã chết. Cách khắc phục: sudo iptables -A INPUT -p 112 -j ACCEPT
  • VIP không phản hồi sau failover — kiểm tra xem net.ipv4.ip_nonlocal_bind = 1 đã được kích hoạt trên node vừa trở thành MASTER chưa.
  • virtual_router_id không khớp — node1 và node2 phải dùng cùng giá trị. Khác ID đồng nghĩa chúng không bao giờ tạo thành một nhóm, và cả hai đều cố giành VIP một cách độc lập.

Bước Tiếp Theo

Với VIP đã hoạt động, bước tiếp theo hiển nhiên là đặt một dịch vụ thực sự phía sau nó. Triển khai HAProxy hoặc Nginx trên cả hai node, cho chúng lắng nghe trên cùng các port, và trỏ upstream client của bạn tới 192.168.1.100. Traffic tự động đi theo VIP — không cần cấu hình lại phía client khi failover xảy ra.

Muốn khai thác tối đa hơn? Chạy nhiều VRRP instance với các giá trị virtual_router_id khác nhau và phân chia traffic ra cả hai node trong điều kiện bình thường. node1 là MASTER cho VIP-A, node2 là MASTER cho VIP-B — mỗi node đóng vai backup cho node kia. Đây là mô hình active-active với failover, một pattern đã được kiểm chứng tốt cho các cặp load balancer cần cả khả năng dự phòng lẫn thông lượng cao.

Share: