Bối cảnh — Tại sao cần Network Bonding
Câu chuyện bắt đầu lúc 2 giờ sáng thứ Sáu. Database server đột nhiên mất kết nối mạng. Alert đổ về đầy màn hình, hơn 50 nhân viên văn phòng sáng hôm sau không thể làm việc nếu database không lên được. Khi chạy vào server room kiểm tra, mình phát hiện một card mạng bị lỗi — cái card duy nhất kết nối server vào switch.
Đó là lần đầu tiên mình thực sự hiểu tại sao network bonding lại tồn tại.
Network bonding (còn gọi là NIC teaming hay link aggregation) là kỹ thuật gộp nhiều card mạng vật lý thành một interface logic duy nhất. Lợi ích rõ ràng nhất:
- Failover tự động: Một card chết, card kia tiếp quản ngay — không downtime
- Load balancing: Phân tải traffic qua nhiều đường dây song song
- Tăng bandwidth: 2 card 1Gbps → có thể đạt 2Gbps aggregated tùy mode
Linux hỗ trợ 7 bonding mode, nhưng thực tế mình dùng chủ yếu 2 mode sau:
- mode 1 (active-backup): Chỉ 1 card active, card còn lại standby. Đơn giản, không cần switch đặc biệt — đây là lựa chọn mặc định cho production
- mode 4 (802.3ad/LACP): Cần switch hỗ trợ LACP, nhưng đổi lại tăng được bandwidth thật sự — dùng cho database/storage server cần throughput cao
Cài đặt
Ubuntu 20.04+ đã bundle sẵn bonding driver trong kernel. Kiểm tra có load chưa:
modprobe bonding
lsmod | grep bonding
Nếu output trống, load module thủ công và đặt auto-load lúc boot:
echo "bonding" >> /etc/modules
modinfo bonding
Với Ubuntu 18.04 trở xuống, cài thêm ifenslave:
apt-get install ifenslave -y
CentOS/RHEL 8+ không cần làm gì thêm — driver có sẵn trong kernel, chỉ cần dùng nmcli để cấu hình.
Cấu hình chi tiết
Cách 1: Dùng netplan (Ubuntu 20.04+)
Đây là cách mình hay dùng nhất cho Ubuntu server hiện tại. Trước tiên xem file config hiện có:
ls /etc/netplan/
# Thường là: 00-installer-config.yaml hoặc 01-netcfg.yaml
Backup file cũ trước khi chỉnh:
cp /etc/netplan/00-installer-config.yaml /etc/netplan/00-installer-config.yaml.bak
File config đầy đủ cho active-backup bonding:
# /etc/netplan/00-installer-config.yaml
network:
version: 2
renderer: networkd
ethernets:
eth0:
dhcp4: false
dhcp6: false
eth1:
dhcp4: false
dhcp6: false
bonds:
bond0:
interfaces: [eth0, eth1]
addresses: [192.168.1.100/24]
gateway4: 192.168.1.1
nameservers:
addresses: [8.8.8.8, 1.1.1.1]
parameters:
mode: active-backup
primary: eth0
mii-monitor-interval: 100
Một chi tiết đáng chú ý: mii-monitor-interval: 100 là khoảng thời gian (ms) kernel check trạng thái card. Mình từng để 200ms và thấy failover hơi chậm rõ rệt — 100ms là ngưỡng tốt cho production.
Apply config — luôn dùng netplan try trước khi làm trên remote server:
netplan try # Test 120 giây, nếu mất kết nối sẽ rollback tự động
netplan apply # Xác nhận apply vĩnh viễn
Mình đã suýt tự khóa mình khỏi server production một lần vì bỏ qua bước netplan try. Đừng bao giờ bỏ qua nó.
Cấu hình mode 802.3ad (LACP) — tăng bandwidth thật sự
Phía switch cần tạo port-channel/LAG với LACP enabled trước. Sau đó chỉnh phần parameters trong file netplan:
bonds:
bond0:
interfaces: [eth0, eth1]
addresses: [192.168.1.100/24]
gateway4: 192.168.1.1
parameters:
mode: 802.3ad
lacp-rate: fast
transmit-hash-policy: layer3+4
mii-monitor-interval: 100
transmit-hash-policy: layer3+4 dùng cả IP lẫn port để hash traffic — phân tải đều hơn so với layer2 mặc định chỉ hash theo MAC.
Cách 2: Dùng nmcli (CentOS/RHEL/Rocky Linux)
# Tạo bond interface
nmcli connection add type bond \
con-name bond0 \
ifname bond0 \
bond.options "mode=active-backup,miimon=100"
# Gắn eth0 và eth1 làm slave
nmcli connection add type ethernet \
con-name bond0-slave-eth0 \
ifname eth0 \
master bond0
nmcli connection add type ethernet \
con-name bond0-slave-eth1 \
ifname eth1 \
master bond0
# Gán IP tĩnh cho bond0
nmcli connection modify bond0 \
ipv4.addresses "192.168.1.100/24" \
ipv4.gateway "192.168.1.1" \
ipv4.dns "8.8.8.8,1.1.1.1" \
ipv4.method manual
# Kích hoạt
nmcli connection up bond0
Xác nhận kết nối đã lên sau khi apply:
nmcli connection show
nmcli device status
Kiểm tra & Monitoring
Đọc trạng thái bonding từ kernel
Kernel expose toàn bộ trạng thái bonding qua /proc/net/bonding/bond0 — đây là nơi đầu tiên cần nhìn vào khi debug:
cat /proc/net/bonding/bond0
Output khi cả 2 card đang healthy:
Bonding Mode: fault-tolerance (active-backup)
Primary Slave: eth0 (primary_reselect failure)
Currently Active Slave: eth0
MII Status: up
MII Polling Interval (ms): 100
Slave Interface: eth0
MII Status: up
Speed: 1000 Mbps
Duplex: full
Link Failure Count: 0
Slave Interface: eth1
MII Status: up
Speed: 1000 Mbps
Duplex: full
Link Failure Count: 0
MII Status: up trên cả 2 slave và Currently Active Slave đúng card primary là dấu hiệu mọi thứ đang ổn. Theo dõi Link Failure Count để phát hiện card chập chờn — số này tăng dần là dấu hiệu card sắp hỏng, dù chưa down hẳn.
Test failover thực tế — bước không được bỏ qua
Cấu hình xong mà không test failover thì chẳng khác gì không có bonding. Mở 2 terminal:
# Terminal 1: Ping liên tục đến gateway
ping -i 0.2 192.168.1.1
# Terminal 2: Tắt card active để simulate lỗi phần cứng
ip link set eth0 down
# Quan sát Terminal 1 — lý tưởng là không có packet lost
# Nếu thấy 1-2 packet drop là bình thường, hơn 5 packet drop là cần xem lại mii-monitor-interval
# Bật lại sau khi test
ip link set eth0 up
Với mii-monitor-interval: 100ms, failover thường xảy ra trong vòng 200–300ms — đủ nhanh để TCP connection không bị reset.
Monitor real-time và các lệnh hữu ích
# Theo dõi trạng thái liên tục
watch -n 1 'cat /proc/net/bonding/bond0 | grep -E "Currently Active|MII Status|Link Failure"'
# Kiểm tra tốc độ và trạng thái vật lý từng card
ethtool eth0 | grep -E "Speed|Duplex|Link detected"
ethtool eth1 | grep -E "Speed|Duplex|Link detected"
# Thống kê bytes TX/RX per interface (xem phân tải traffic)
ip -s link show eth0
ip -s link show eth1
# Xem log kernel khi có failover event
journalctl -k | grep -i "bond\|enslaved\|link failure"
Đang dùng Prometheus + node_exporter? Metric node_network_up{device="bond0"} và node_network_up{device="eth0"} tự track trạng thái bond và từng slave — không cần cấu hình thêm gì.
Những vấn đề thực tế đã gặp
Mình quản lý network cho office 50 người và datacenter nhỏ, đã gặp đủ mọi kiểu vấn đề với bonding — ghi lại đây để bạn khỏi mất cả đêm như mình:
- MAC address conflict với LACP: Switch cần thấy MAC của bond0, không phải MAC của từng slave riêng. Switch cũ không support LACP properly sẽ gây loop hoặc block port. Khi không chắc về switch, dùng mode 1 (active-backup) luôn an toàn hơn.
- Interface rename sau reboot: Từng gặp bonding hoạt động tốt, nhưng sau reboot thì
eth0/eth1tự đổi thànheth2/eth3— do udev thay đổi thứ tự detect card. Cấu hình hỏng sạch, không có lỗi rõ ràng để debug. Luôn dùng tên predictable kiểuenp3s0, đừng tin vàoeth0. - VLAN trên bonding: Hoàn toàn được hỗ trợ. Tạo VLAN interface trên bond0 bình thường — không cần tạo VLAN trên từng slave riêng lẻ.
- Bonding trong VM: Server hypervisor thì bond ở host level rồi expose virtual NIC cho VM. Không bond bên trong guest VM — hypervisor layer đã handle failover rồi, bond thêm bên trong chỉ thêm phức tạp không cần thiết.
Sau cái đêm 2 giờ sáng đó, toàn bộ production server của mình đều chạy active-backup bonding. Một năm trở lại đây đã có 3 lần card mạng lỗi, cả 3 lần failover đều diễn ra trong im lặng hoàn toàn — không ai hay biết, không ticket support nào được mở. Đó là cách infrastructure tốt nên vận hành.
