Vấn đề: Trả tiền cho băng thông mà bạn không thể sử dụng
Quản lý một node server có lưu lượng truy cập cao với hai ISP thường mang lại cảm giác giống như sở hữu động cơ V8 nhưng chỉ sử dụng bốn xi-lanh. Theo mặc định, Linux dựa vào một default gateway duy nhất. Tất cả lưu lượng đi ra của bạn bị dồn nén qua một đường ống trong khi liên kết thứ hai—thứ mà bạn đang trả tiền—lại ở trạng thái nhàn rỗi. Nếu liên kết chính đó gặp sự cố, kết nối của bạn sẽ bị ngắt hoàn toàn cho đến khi bạn can thiệp thủ công.
Các script failover tiêu chuẩn giải quyết được vấn đề dự phòng, nhưng chúng không giải quyết được vấn đề chưa tận dụng hết tài nguyên. Định tuyến Equal-Cost Multi-Path (ECMP) thay đổi điều này. ECMP cho phép kernel Linux phân bổ lưu lượng đi ra qua nhiều đường cùng một lúc. Đây là một cách mạnh mẽ để gộp đường truyền cáp quang 1Gbps với một đường dự phòng 500Mbps nhằm tối đa hóa tổng băng thông khả dụng.
Tôi đã triển khai thiết lập này trên các router biên và VPN concentrator, nơi mà mỗi megabit đều quý giá. Nó lấp đầy khoảng cách giữa quản trị cơ bản và kỹ thuật mạng chuyên nghiệp mà không cần đến các bộ cân bằng tải phần cứng đắt tiền.
ECMP hoạt động như thế nào trong Kernel Linux
ECMP hoạt động bằng cách thêm nhiều “next hop” vào một đích đến duy nhất trong bảng định tuyến, thường là route 0.0.0.0/0. Khi một gói tin cần rời khỏi hệ thống, kernel sẽ chọn một đường đi dựa trên thuật toán băm (hashing algorithm).
Hashing dựa trên luồng (Flow-Based) so với dựa trên gói tin (Packet-Based)
Một nỗi lo phổ biến là ECMP sẽ chia nhỏ các gói tin theo kiểu round-robin. Nếu Linux gửi mỗi gói tin qua một ISP khác nhau, hiệu suất TCP sẽ sụp đổ do việc phân phát không đúng thứ tự (out-of-order delivery). Thay vào đó, các kernel hiện đại sử dụng flow-based hashing. Bằng cách phân tích IP nguồn, IP đích và các cổng (port), kernel đảm bảo rằng tất cả các gói tin của một “luồng” (flow) cụ thể luôn đi trên cùng một con đường. Điều này giúp bảo toàn thứ tự gói tin trong khi vẫn phân phối các phiên người dùng khác nhau trên tất cả các gateway hiện có.
Mẹo chuyên nghiệp: Theo mặc định, Linux thường chỉ băm dựa trên Layer 3 (IP). Để đạt được sự phân phối tốt hơn bằng Layer 4 (port), hãy bật cài đặt sysctl sau:
sudo sysctl -w net.ipv4.fib_multipath_hash_policy=1
Thực hành: Triển khai ECMP với iproute2
Hãy xem xét một kịch bản thực tế. Giả sử máy chủ của bạn có hai giao diện mạng:
- eth1: ISP A (Gateway: 192.168.1.1)
- eth2: ISP B (Gateway: 192.168.2.1)
Bước 1: Xóa đường cũ
Các route mặc định tĩnh hiện có sẽ xung đột với thiết lập multipath mới của bạn. Hãy kiểm tra bảng hiện tại của bạn trước:
ip route show
Nếu tồn tại một route mặc định, hãy xóa sạch nó:
sudo ip route del default
Bước 2: Thêm Route Multipath
Từ khóa nexthop chính là “bí quyết” ở đây. Sử dụng lệnh sau để chia lưu lượng 50/50 giữa hai nhà cung cấp của bạn:
sudo ip route add default \
nexthop via 192.168.1.1 dev eth1 weight 1 \
nexthop via 192.168.2.1 dev eth2 weight 1
Tham số weight rất linh hoạt. Nếu ISP A là đường truyền riêng 1Gbps và ISP B là Starlink 500Mbps, hãy đặt ISP A là weight 2 và ISP B là weight 1. Điều này chỉ dẫn kernel gửi khoảng 66% các luồng mới qua đường truyền nhanh hơn.
Bước 3: Xác minh việc phân chia lưu lượng
Chạy lại lệnh ip route show. Bạn sẽ thấy một mục multipath được liệt kê dưới route mặc định. Để thấy việc cân bằng đang hoạt động, hãy chạy traceroute tới hai IP công cộng khác nhau:
traceroute 8.8.8.8
traceroute 1.1.1.1
Nếu việc băm hoạt động, bạn sẽ thấy hop đầu tiên thay đổi giữa hai địa chỉ IP gateway của mình.
Bẫy “Gateway chết”
Các lệnh iproute2 tiêu chuẩn là tĩnh. Kernel biết nếu cáp bị rút (link DOWN), nhưng nó không biết liệu mạng thượng nguồn của ISP có bị lỗi hay không trong khi liên kết cục bộ vẫn UP. Nếu ISP A mất kết nối nhưng giao diện vẫn hoạt động, kernel sẽ tiếp tục đẩy 50% lưu lượng của bạn vào “hố đen”.
Môi trường production cần một cơ chế kiểm tra sức khỏe (health-check). Bạn có hai lựa chọn chính:
- Script giám sát: Một script Bash đơn giản có thể ping một mục tiêu bên ngoài (như 1.1.1.1) qua một giao diện cụ thể. Nếu thất bại, script sẽ kích hoạt cập nhật route.
- Định tuyến động: Đối với các thiết lập quan trọng, hãy sử dụng
FRR(Free Range Routing). Nó xử lý BFD (Bidirectional Forwarding Detection), có thể phát hiện liên kết chết trong vài mili giây và tự động cập nhật bảng định tuyến. Bạn cũng có thể tham khảo cách cấu hình Định tuyến động với BIRD để có thêm lựa chọn linh hoạt.
Thiết lập vĩnh viễn
Các lệnh ip route thủ công sẽ biến mất sau khi khởi động lại. Đối với các hệ thống Ubuntu hoặc Debian sử dụng Netplan, bạn có thể xác định các route này trong file /etc/netplan/*.yaml của mình. Tuy nhiên, cú pháp multipath của Netplan thường khá rắc rối. Nhiều quản trị viên thích sử dụng script post-up hoặc một service systemd đơn giản để áp dụng lại lệnh nexthop sau khi stack mạng được khởi tạo.
Các lưu ý quan trọng để thành công
- Lựa chọn IP nguồn: Nếu chính máy chủ khởi tạo một kết nối, nó cần biết sử dụng IP nguồn nào. Đảm bảo các quy tắc NAT (Masquerade) trong iptables hoặc nftables được cấu hình để xử lý cả hai giao diện đi ra.
- Khớp MTU: Giữ cho MTU đồng nhất. Nếu đường truyền cáp quang sử dụng 1500 bytes nhưng đường dự phòng dựa trên VPN sử dụng 1400, bạn sẽ gặp tình trạng tải trang bị lỗi và các phiên SSH bị treo.
- Conntrack: Đảm bảo module kernel nf_conntrack đang hoạt động. Điều này cho phép firewall ghi nhớ đường dẫn mà một kết nối đã bắt đầu để có thể xử lý lưu lượng phản hồi một cách chính xác.
Kết luận
ECMP là cách tiết kiệm chi phí nhất để tận dụng tối đa hiệu suất từ một máy chủ Linux đa kết nối (multi-homed). Nó biến một liên kết dự phòng thụ động thành một tài sản hoạt động, tăng tổng băng thông của bạn ngay lập tức. Mặc dù bạn sẽ cần thêm một lớp giám sát để đạt được tính sẵn sàng cao thực sự, nhưng logic định tuyến cốt lõi đã được tích hợp sẵn trong kernel, sẵn sàng để bạn sử dụng.

