Fullmoon System

Linux Bonding: Mode Differences and CentOS 7.9 Active-Backup Configuration

EdwardMoon

Linux bonding combines two or more physical network interfaces into one logical interface. It can switch paths after a failure or distribute traffic across multiple connections, depending on the mode and switch configuration. This article compares the modes, then covers configuring and recovering active-backup bonding with CentOS 7.9 network-scripts.

Scope: This maintenance example applies to static IPv4 networking already managed by network.service. CentOS Linux 7 reached end of support on June 30, 2024; do not use it as the baseline for new servers. Official CentOS end-of-life notice

What Bonding Can and Cannot Provide

active-backup uses one NIC at a time and switches to another after failure. Bonding two 1 Gbps NICs still limits normal throughput to the active NIC's speed. Load-balancing modes such as LACP can distribute multiple flows among NICs, but a single connection does not automatically become as fast as their combined capacity.

Bonding uses the Linux bonding driver. Network teaming based on teamd is a separate implementation with a similar purpose; do not mix their configuration methods. Redundant links cannot preserve connectivity if the shared switch, upstream router, or power system fails.

Bonding Modes and Switch Configuration

This comparison assumes ordinary server-to-switch connections. Direct links and unusual topologies require separate validation.

Mode Behavior Switch requirements Considerations
0: balance-rr Distributes transmitted packets across NICs in sequence Usually requires static port aggregation May reorder packets
1: active-backup One active NIC with failover No LACP or static aggregation required No combined throughput
2: balance-xor Selects a transmit path using a hash policy Usually requires static port aggregation Does not negotiate LACP
3: broadcast Sends the same packet through every NIC Usually requires port aggregation Duplicates traffic rather than adding throughput
4: 802.3ad / LACP Distributes flows within an aggregation group LACP must be configured on the corresponding ports Check speed, duplex, and hash policy within the aggregation group
5: balance-tlb Balances transmission; receives through one NIC No special aggregation configuration required Check driver support
6: balance-alb Adds IPv4 receive balancing to TLB No special aggregation configuration required Depends on ARP negotiation and support for MAC changes

Unlike mode 5, mode 6 can also balance IPv4 receive traffic. Distinguish static aggregation for modes 0, 2, and 3 from LACP in mode 4. See the mode descriptions and Switch Configuration section in the Linux kernel bonding documentation for detailed requirements.

Environment and Pre-Change Checks

The example attaches eth0 and eth1 to bond0, using 192.168.1.100/24 and gateway 192.168.1.1. Replace names and addresses with actual values, check for duplicate IPs, and ensure the gateway is in the same subnet. Connect both ports to the same VLAN/network; do not place active-backup ports in an LACP group.

Applying the configuration interrupts connectivity on the target NICs. Secure an independent management path such as IPMI, iDRAC, or a hypervisor console and schedule maintenance instead of relying solely on SSH. VLANs, bridges, virtual IPs, multiple default routes, policy routing, and IPv6 require separate migration plans. The generator below does not convert all such configurations.

cat /etc/centos-release
uname -r
ip -br link
ip -br address
ip route show table all
ip rule show
systemctl is-active network
systemctl is-active NetworkManager
modinfo bonding
ethtool eth0
ethtool eth1

Verify that network already manages the interfaces and NetworkManager is inactive. If NetworkManager manages the server, do not stop it for this example; use the appropriate nmcli bonding procedure. Prevent both tools from managing the same NIC.

modinfo bonding queries module information. Normal distribution kernels include the bonding driver; its absence from lsmod does not justify installing a separate kmod-bonding package. If modinfo fails, first check that installed module packages match the running kernel.

Complete ifcfg File Layout

Put the IP, gateway, and bonding options in /etc/sysconfig/network-scripts/ifcfg-bond0. miimon=100 checks link state every 100 milliseconds; it does not verify end-to-end upstream connectivity.

DEVICE=bond0
NAME=bond0
TYPE=Bond
BONDING_MASTER=yes
BOOTPROTO=none
ONBOOT=yes
NM_CONTROLLED=no
IPADDR=192.168.1.100
PREFIX=24
GATEWAY=192.168.1.1
DEFROUTE=yes
PEERDNS=no
IPV6INIT=no
BONDING_OPTS="mode=active-backup miimon=100"

PEERDNS=no prevents this profile from changing DNS configuration. Verify that name resolution still works after applying the change. IPV6INIT=no reflects this example's IPv4-only scope; do not use it unchanged on an IPv6 server.

Set MASTER and SLAVE on physical NICs without duplicating the IP address or default gateway. The following blocks belong to two separate files.

# /etc/sysconfig/network-scripts/ifcfg-eth0
DEVICE=eth0
NAME=eth0
TYPE=Ethernet
BOOTPROTO=none
ONBOOT=yes
NM_CONTROLLED=no
MASTER=bond0
SLAVE=yes
IPV6INIT=no

# /etc/sysconfig/network-scripts/ifcfg-eth1
DEVICE=eth1
NAME=eth1
TYPE=Ethernet
BOOTPROTO=none
ONBOOT=yes
NM_CONTROLLED=no
MASTER=bond0
SLAVE=yes
IPV6INIT=no

Remove conflicting automatically activated ifcfg files or profiles for the same NIC. Set per-bond options through BONDING_OPTS. Correct ifcfg configuration lets network-scripts load the necessary module, so repeatedly appending to /etc/modules-load.d/bonding.conf is unnecessary. Official RHEL 7 ifcfg bonding configuration

Bash Script to Back Up and Generate Candidate Configuration

Save this as prepare-bond.sh and adapt the variables. It backs up current ifcfg files and network state to a root-only directory and generates candidate files separately. The next section handles replacing live files and restarting NICs.

#!/bin/bash
# CentOS 7.9 with network.service only: create backups and candidate configuration only.
set -euo pipefail
umask 077

BOND_DEVICE="bond0"
ETH0_DEVICE="eth0"
ETH1_DEVICE="eth1"
IP_ADDRESS="192.168.1.100"
PREFIX="24"
GATEWAY="192.168.1.1"
CFG_DIR="/etc/sysconfig/network-scripts"

die() { printf '%s\n' "$*" >&2; exit 1; }
valid_ipv4() {
  local value="$1" octet a b c d
  [[ "$value" =~ ^[0-9]{1,3}(\.[0-9]{1,3}){3}$ ]] || return 1
  IFS=. read -r a b c d <<< "$value"
  for octet in "$a" "$b" "$c" "$d"; do
    (( 10#$octet <= 255 )) || return 1
  done
}

[[ "$EUID" -eq 0 ]] || die "root로 실행하세요."
[[ -d "$CFG_DIR" ]] || die "network-scripts 경로가 없습니다."
for nic in "$BOND_DEVICE" "$ETH0_DEVICE" "$ETH1_DEVICE"; do
  [[ "$nic" =~ ^[a-zA-Z0-9_-]{1,15}$ ]] || die "인터페이스 이름을 확인하세요."
done
[[ "$ETH0_DEVICE" != "$ETH1_DEVICE" ]] || die "서로 다른 물리 NIC가 필요합니다."
[[ "$BOND_DEVICE" != "$ETH0_DEVICE" && "$BOND_DEVICE" != "$ETH1_DEVICE" ]] ||
  die "bond 이름이 물리 NIC와 같습니다."
[[ ! -e "/sys/class/net/$BOND_DEVICE" && ! -e "$CFG_DIR/ifcfg-$BOND_DEVICE" ]] ||
  die "기존 bond가 있습니다. 기존 구성 변경은 이 예제 범위 밖입니다."
valid_ipv4 "$IP_ADDRESS" || die "IP 주소 형식이 잘못되었습니다."
valid_ipv4 "$GATEWAY" || die "게이트웨이 주소 형식이 잘못되었습니다."
[[ "$GATEWAY" != "$IP_ADDRESS" ]] || die "게이트웨이는 서버 자신과 달라야 합니다."
[[ "$PREFIX" =~ ^([1-9]|[12][0-9]|3[0-2])$ ]] || die "PREFIX는 1~32여야 합니다."
systemctl is-active --quiet network ||
  die "기존 network.service 환경에서만 사용하세요."
if systemctl is-active --quiet NetworkManager; then
  die "NetworkManager 환경입니다. 해당 환경의 nmcli 본딩 절차를 사용하세요."
fi

modinfo bonding >/dev/null
for nic in "$ETH0_DEVICE" "$ETH1_DEVICE"; do
  [[ -e "/sys/class/net/$nic" ]] || die "NIC가 없습니다: $nic"
  [[ -f "$CFG_DIR/ifcfg-$nic" ]] || die "기존 ifcfg 파일이 없습니다: $nic"
  [[ ! -L "/sys/class/net/$nic/master" ]] || die "이미 다른 장치에 종속된 NIC입니다: $nic"
  [[ ! -e "$CFG_DIR/route-$nic" && ! -e "$CFG_DIR/rule-$nic" &&
     ! -e "$CFG_DIR/route6-$nic" && ! -e "$CFG_DIR/rule6-$nic" ]] ||
    die "별도 경로/정책 설정은 bond에 따로 이전해야 합니다: $nic"
  if ip -6 address show dev "$nic" scope global | grep -q 'inet6 '; then
    die "IPv6 주소가 있는 NIC입니다. IPv6 이전 계획을 먼저 작성하세요: $nic"
  fi
done

PLAN_DIR=$(mktemp -d "/root/bond-plan.XXXXXXXX")
mkdir "$PLAN_DIR/before" "$PLAN_DIR/new"
for nic in "$ETH0_DEVICE" "$ETH1_DEVICE"; do
  cp -a "$CFG_DIR/ifcfg-$nic" "$PLAN_DIR/before/"
done
ip address show > "$PLAN_DIR/address-before.txt"
ip route show table all > "$PLAN_DIR/routes-before.txt"
ip rule show > "$PLAN_DIR/rules-before.txt"
printf 'BOND_DEVICE=%q\nETH0_DEVICE=%q\nETH1_DEVICE=%q\n' \
  "$BOND_DEVICE" "$ETH0_DEVICE" "$ETH1_DEVICE" > "$PLAN_DIR/names.sh"

cat > "$PLAN_DIR/new/ifcfg-$BOND_DEVICE" <<EOF
DEVICE=$BOND_DEVICE
NAME=$BOND_DEVICE
TYPE=Bond
BONDING_MASTER=yes
BOOTPROTO=none
ONBOOT=yes
NM_CONTROLLED=no
IPADDR=$IP_ADDRESS
PREFIX=$PREFIX
GATEWAY=$GATEWAY
DEFROUTE=yes
PEERDNS=no
IPV6INIT=no
BONDING_OPTS="mode=active-backup miimon=100"
EOF

for nic in "$ETH0_DEVICE" "$ETH1_DEVICE"; do
  cat > "$PLAN_DIR/new/ifcfg-$nic" <<EOF
DEVICE=$nic
NAME=$nic
TYPE=Ethernet
BOOTPROTO=none
ONBOOT=yes
NM_CONTROLLED=no
MASTER=$BOND_DEVICE
SLAVE=yes
IPV6INIT=no
EOF
done
printf '백업 및 후보 설정: %s\n' "$PLAN_DIR"
printf '실제 설정과 네트워크 상태는 변경하지 않았습니다.\n'

Check syntax with bash -n prepare-bond.sh, then generate candidate files with sudo bash prepare-bond.sh. Record the output and backup paths. The script cannot verify duplicate IPs, VLAN alignment, switch policy, or every routing dependency, so perform the pre-change checks too.

Apply from the Console

Run these commands one step at a time and stop if a step fails. Exit status 1 from diff means differences were found. Verify they are intended before taking the NICs down. Changing to the example IP can also change the management address.

# Run from a root console. Replace the path below with the actual generator output.
PLAN_DIR=/root/bond-plan.XXXXXXXX
test -f "$PLAN_DIR/names.sh" || exit 1
source "$PLAN_DIR/names.sh"
CFG_DIR=/etc/sysconfig/network-scripts

# Review the candidate configuration; networking has not been changed yet.
cat "$PLAN_DIR/new/ifcfg-$BOND_DEVICE"
diff -u "$PLAN_DIR/before/ifcfg-$ETH0_DEVICE" "$PLAN_DIR/new/ifcfg-$ETH0_DEVICE"
diff -u "$PLAN_DIR/before/ifcfg-$ETH1_DEVICE" "$PLAN_DIR/new/ifcfg-$ETH1_DEVICE"

# Run only after review. Connectivity on the target NICs is interrupted from this point.
# If ifdown fails, investigate the cause and stop.
ifdown "$ETH0_DEVICE"
ifdown "$ETH1_DEVICE"

# Install these three files. If any installation fails, recover instead of activating.
install -o root -g root -m 600 "$PLAN_DIR/new/ifcfg-$BOND_DEVICE" "$CFG_DIR/ifcfg-$BOND_DEVICE"
install -o root -g root -m 600 "$PLAN_DIR/new/ifcfg-$ETH0_DEVICE" "$CFG_DIR/ifcfg-$ETH0_DEVICE"
install -o root -g root -m 600 "$PLAN_DIR/new/ifcfg-$ETH1_DEVICE" "$CFG_DIR/ifcfg-$ETH1_DEVICE"
restorecon "$CFG_DIR/ifcfg-$BOND_DEVICE" "$CFG_DIR/ifcfg-$ETH0_DEVICE" "$CFG_DIR/ifcfg-$ETH1_DEVICE"

ifup "$BOND_DEVICE"
ifup "$ETH0_DEVICE"
ifup "$ETH1_DEVICE"

Validate Addresses, Bonding Mode, and Failover

ip -br address show bond0
ip -d link show bond0
ip link show master bond0
cat /proc/net/bonding/bond0
ip route
ping -c 4 -I bond0 192.168.1.1
ethtool eth0
ethtool eth1

The presence of bond0 is not enough. Verify that the IP is assigned only to the bond, both physical NICs are members, and the default route is correct. Inspect the following fields in /proc/net/bonding/bond0.

# Example output format, not a measurement from a specific server.
Bonding Mode: fault-tolerance (active-backup)
Currently Active Slave: eth0
MII Status: up
MII Polling Interval (ms): 100
...
Slave Interface: eth0
MII Status: up
Speed: 1000 Mbps
...
Slave Interface: eth1
MII Status: up
Speed: 1000 Mbps

Currently Active Slave identifies the NIC carrying traffic. Check that both NICs have healthy MII Status, and inspect each physical NIC's ethtool output for actual link speed. A summed speed shown for the bond is not a throughput measurement.

  1. From another client, send continuous pings and real service requests to the server IP.
  2. Keep the maintenance console open and disable only the active NIC's cable or corresponding switch port.
  3. Confirm that the active NIC changes and connectivity recovers; record packet loss and service impact.
  4. Restore the disabled path and verify both links, then test the other path the same way.
  5. Verify a new management session, DNS queries, and service responses, then use a planned reboot to test persistence.

Cable failure and upstream network failure are different tests. miimon checks link state and may miss an upstream switch/router failure while the local link remains up. Test the actual failure scope and switch topology required by the service separately.

Rollback

Run this procedure from the console. It assumes a new setup with no preexisting bond and restores the original NIC files saved by the preparation script. Check each step's errors and current state, and verify original files before restoring them. Separately reverse any routing, DNS, or firewall changes made during deployment.

# Set the actual backup path recorded during application. Run from a root console.
PLAN_DIR=/root/bond-plan.XXXXXXXX
test -f "$PLAN_DIR/names.sh" || exit 1
source "$PLAN_DIR/names.sh"
CFG_DIR=/etc/sysconfig/network-scripts

# Check each result. If ifdown fails because the bond was never created, inspect state first.
ifdown "$BOND_DEVICE"
ifdown "$ETH0_DEVICE"
ifdown "$ETH1_DEVICE"

# This procedure applies only to a new setup where no bond existed beforehand.
ip link delete "$BOND_DEVICE" type bond
mv "$CFG_DIR/ifcfg-$BOND_DEVICE" "$PLAN_DIR/ifcfg-bond-failed"
cp -a "$PLAN_DIR/before/ifcfg-$ETH0_DEVICE" "$CFG_DIR/ifcfg-$ETH0_DEVICE"
cp -a "$PLAN_DIR/before/ifcfg-$ETH1_DEVICE" "$CFG_DIR/ifcfg-$ETH1_DEVICE"
restorecon "$CFG_DIR/ifcfg-$ETH0_DEVICE" "$CFG_DIR/ifcfg-$ETH1_DEVICE"

ifup "$ETH0_DEVICE"
ifup "$ETH1_DEVICE"
ip -br address
ip route
journalctl -u network --since '-10 minutes' --no-pager

After recovery, compare addresses and routes with address-before.txt and routes-before.txt, and test management and service access from another client. If Link Failure Count increases or the mode is wrong, first inspect cables, switch VLANs, aggregation settings, duplicate profiles, and BONDING_OPTS.

References