igozhang

——

    业务物理机换网卡操作

    背景

    业务物理机(igo101igo105)业务网使用 NetworkManager 管理的 bond0active-backup),成员口为两张业务物理网卡对应的 slave 连接:

    连接名 作用
    bond0 业务网 bond,承载主机 IP
    bond-slave-ens1f0 bond 成员 1
    bond-slave-ens2f0 bond 成员 2

    更换物理网卡后,内核网卡名通常会变化(例如 ens1f0ens1f0np0ens2f0ens2f0np0)。若 NM 配置里仍写旧名,bond 无法正确绑定成员口,业务网中断,SSH 也可能失败。此时需通过带外控制台(BMC/iLO 等)登录修复。

    适用范围: 适合 CentOS 7 / Rocky 9 操作系统(NetworkManager + bond0 场景)。

    范围说明:

    • 目标主机:igo102igo105igo101 已完成)
    • 只更换进入 bond0 的两张业务网卡;ens17f* 等其它口不在本次范围
    • SSH 端口:5008
    • 操作用户:igo(改系统网络配置需 sudo

    换卡前现状示例(igo102):

    • 实际成员:ens1f0ens2f0
    • bond0primary:各机可能不同(如 102/103/104 为 ens2f0,105 为 ens1f0),修改时按本机原值映射,不要照搬其它机器

    换卡后目标示例(igo101):

    • 实际成员:ens1f0np0ens2f0np0
    • slave 连接的 interface-namebond0primary 均已改为新名

    配置文件目录:

    /etc/NetworkManager/system-connections/
      bond0.nmconnection
      bond-slave-ens1f0.nmconnection
      bond-slave-ens2f0.nmconnection
      ens1f0.nmconnection          # 独立网卡配置,勿与 bond-slave 混淆
      ens2f0.nmconnection
    

    1. 手动修改配置文件

    适用于未预置脚本、或需要逐步核对配置落盘内容的场景。

    1.1 换卡前准备(可选但建议)

    在仍可通过 SSH 登录时,记录本机当前配置:

    hostname
    cat /sys/class/net/bond0/bonding/slaves
    cat /sys/class/net/bond0/bonding/primary
    nmcli -g connection.interface-name,connection.master connection show bond-slave-ens1f0
    nmcli -g connection.interface-name,connection.master connection show bond-slave-ens2f0
    nmcli -g bond.options,ipv4.addresses,ipv4.gateway connection show bond0
    sudo sed -n '1,80p' /etc/NetworkManager/system-connections/bond-slave-ens1f0.nmconnection
    sudo sed -n '1,80p' /etc/NetworkManager/system-connections/bond-slave-ens2f0.nmconnection
    sudo sed -n '1,80p' /etc/NetworkManager/system-connections/bond0.nmconnection
    

    重点记录:

    1. 两个 slave 当前的 interface-name
    2. bond0primary
    3. bond0 的 IPv4 地址(例如 10.10.10.102/24

    1.2 换卡后确认新网卡名

    带外登录目标机后执行:

    ip -o link show | awk -F': ' '{print $2}' | grep -E '^ens'
    ls -1 /sys/class/net | grep -E '^ens'
    

    对照旧名,确认新名。常见对应关系:

    旧名 新名(示例)
    ens1f0 ens1f0np0
    ens2f0 ens2f0np0

    若实际新名与上表不一致,以本机 ip link / sysfs 看到的为准。

    1.3 备份配置文件

    ts=$(date +%Y%m%d%H%M%S)
    sudo cp -a /etc/NetworkManager/system-connections/bond-slave-ens1f0.nmconnection \
      /etc/NetworkManager/system-connections/bond-slave-ens1f0.nmconnection.bak.${ts}
    sudo cp -a /etc/NetworkManager/system-connections/bond-slave-ens2f0.nmconnection \
      /etc/NetworkManager/system-connections/bond-slave-ens2f0.nmconnection.bak.${ts}
    sudo cp -a /etc/NetworkManager/system-connections/bond0.nmconnection \
      /etc/NetworkManager/system-connections/bond0.nmconnection.bak.${ts}
    

    1.4 修改配置文件

    只改下列字段,其它内容(UUID、IP、DNS 等)保持不动。

    (1)编辑 bond-slave-ens1f0.nmconnection

    将:

    interface-name=ens1f0
    

    改为实际新名,例如:

    interface-name=ens1f0np0
    

    (2)编辑 bond-slave-ens2f0.nmconnection

    将:

    interface-name=ens2f0
    

    改为实际新名,例如:

    interface-name=ens2f0np0
    

    (3)编辑 bond0.nmconnection

    [bond] 段中的 primary 从旧成员名改为对应新名。例如本机原 primary=ens2f0,则改为:

    [bond]
    mode=active-backup
    primary=ens2f0np0
    

    可用编辑器修改,例如:

    sudo vi /etc/NetworkManager/system-connections/bond-slave-ens1f0.nmconnection
    sudo vi /etc/NetworkManager/system-connections/bond-slave-ens2f0.nmconnection
    sudo vi /etc/NetworkManager/system-connections/bond0.nmconnection
    

    修改后快速核对:

    sudo grep -nE '^(interface-name|primary)=' \
      /etc/NetworkManager/system-connections/bond-slave-ens1f0.nmconnection \
      /etc/NetworkManager/system-connections/bond-slave-ens2f0.nmconnection \
      /etc/NetworkManager/system-connections/bond0.nmconnection
    

    1.5 重新加载并激活

    以下命令会变更网络状态,可能导致短暂闪断:

    sudo nmcli connection reload
    sudo nmcli connection up bond-slave-ens1f0
    sudo nmcli connection up bond-slave-ens2f0
    sudo nmcli connection up bond0
    

    1.6 验证

    cat /sys/class/net/bond0/bonding/slaves
    cat /sys/class/net/bond0/bonding/primary
    cat /sys/class/net/bond0/bonding/active_slave
    ip -4 -o addr show dev bond0
    nmcli -t -f NAME,DEVICE,STATE connection show --active | grep -E 'bond'
    ping -c 3 -W 2 10.10.10.254
    

    预期:

    • slaves 为新网卡名(如 ens1f0np0 ens2f0np0
    • primary 为映射后的新名
    • bond0 上 IPv4 地址仍为本机原地址
    • 可 SSH(端口 5008)登录

    1.7 注意

    • 不要改错成同目录下的 ens1f0.nmconnection / ens2f0.nmconnection(非 bond slave)
    • 不要改 uuid、不要随意改 bond0 的 IP
    • primary 必须按本机原 primary 做旧名→新名映射,不要统一抄成某一台的值
    • 建议一次只换一台,验证业务网恢复后再换下一台

    2. 通过脚本切换

    在对应服务器上以 igo 用户操作。建议换卡前生成并验证脚本;换卡后若 SSH 不通,通过带外控制台执行。

    脚本路径:/home/igo/shell/fix-bond-nic-rename.sh

    逻辑概要:

    1. 从 NM 读取当前配置中的成员名(bond-slave-ens1f0 / bond-slave-ens2f0interface-name)以及 bond0primary
    2. 在系统中解析实际网卡名:若配置名已存在则沿用;若不存在,则查找以该配置名为前缀的唯一网卡(例如配置为 ens1f0、实际为 ens1f0np0
    3. 默认 dry-run,只打印计划变更
    4. --apply 后:用 nmcli 修改连接并 connection up 生效

    2.1 在对应服务器上生成脚本

    每一台待换机(如 igo102igo105)上执行下面整段命令,生成脚本(仅写文件,不改网络):

    bash -s << 'END'
    mkdir -p "$HOME/shell"
    cat > "$HOME/shell/fix-bond-nic-rename.sh" << 'EOF'
    #!/usr/bin/env bash
    # After NIC replace: read bond configured names, resolve to real ifaces, update NM and activate.
    # Usage:
    #   bash ~/shell/fix-bond-nic-rename.sh
    #   bash ~/shell/fix-bond-nic-rename.sh --apply
    set -euo pipefail
    
    APPLY=0
    if [[ "${1:-}" == "--apply" ]]; then
      APPLY=1
    fi
    
    CONN1="bond-slave-ens1f0"
    CONN2="bond-slave-ens2f0"
    BOND_CONN="bond0"
    
    resolve_iface() {
      local configured="$1"
      if [[ -z "${configured}" ]]; then
        echo "ERROR: empty configured iface" >&2
        return 1
      fi
      if [[ -d "/sys/class/net/${configured}" ]]; then
        printf "%s\n" "${configured}"
        return 0
      fi
      local matches
      matches="$(ls -1 /sys/class/net | grep -E "^${configured}" || true)"
      if [[ -z "${matches}" ]]; then
        echo "ERROR: configured ${configured} missing, and no iface starts with ${configured}" >&2
        ls -1 /sys/class/net | grep -E "^ens" >&2 || true
        return 1
      fi
      local count
      count="$(printf "%s\n" "${matches}" | awk "NF{c++} END{print c+0}")"
      if [[ "${count}" -ne 1 ]]; then
        echo "ERROR: configured ${configured} missing; ambiguous candidates:" >&2
        printf "%s\n" "${matches}" >&2
        return 1
      fi
      printf "%s\n" "${matches}"
    }
    
    echo "Host: $(hostname -s 2>/dev/null || hostname)"
    if [[ "${APPLY}" -eq 1 ]]; then
      echo "Mode: APPLY"
    else
      echo "Mode: DRY-RUN"
    fi
    
    echo "=== present ens interfaces ==="
    ls -1 /sys/class/net | grep -E "^ens" || true
    
    CUR_IF1="$(nmcli -g connection.interface-name connection show "${CONN1}")"
    CUR_IF2="$(nmcli -g connection.interface-name connection show "${CONN2}")"
    BOND_OPTS="$(nmcli -g bond.options connection show "${BOND_CONN}")"
    CUR_PRIMARY="$(printf "%s\n" "${BOND_OPTS}" | tr "," "\n" | awk -F= "/^primary=/{print \$2; exit}")"
    IPADDR="$(nmcli -g ipv4.addresses connection show "${BOND_CONN}")"
    
    NEW_IF1="$(resolve_iface "${CUR_IF1}")"
    NEW_IF2="$(resolve_iface "${CUR_IF2}")"
    if [[ -n "${CUR_PRIMARY}" ]]; then
      NEW_PRIMARY="$(resolve_iface "${CUR_PRIMARY}")"
    else
      NEW_PRIMARY=""
    fi
    
    echo "=== resolve ==="
    echo "${CONN1}: ${CUR_IF1} -> ${NEW_IF1}"
    echo "${CONN2}: ${CUR_IF2} -> ${NEW_IF2}"
    if [[ -n "${CUR_PRIMARY}" ]]; then
      echo "${BOND_CONN} primary: ${CUR_PRIMARY} -> ${NEW_PRIMARY}"
    else
      echo "${BOND_CONN} primary: (empty)"
    fi
    echo "${BOND_CONN} ipv4.addresses: ${IPADDR}"
    echo "bond.options now: ${BOND_OPTS}"
    
    NEED_CHANGE=0
    if [[ "${CUR_IF1}" != "${NEW_IF1}" || "${CUR_IF2}" != "${NEW_IF2}" ]]; then
      NEED_CHANGE=1
    fi
    if [[ -n "${CUR_PRIMARY}" && "${CUR_PRIMARY}" != "${NEW_PRIMARY}" ]]; then
      NEED_CHANGE=1
    fi
    
    if [[ "${NEED_CHANGE}" -eq 0 ]]; then
      echo "No rename needed; bond names already match present ifaces."
      echo -n "slaves: "; cat /sys/class/net/bond0/bonding/slaves 2>/dev/null || true
      exit 0
    fi
    
    if [[ "${APPLY}" -eq 0 ]]; then
      echo "Dry-run only. Re-run with --apply to apply changes."
      exit 0
    fi
    
    echo "=== applying ==="
    sudo nmcli connection modify "${CONN1}" connection.interface-name "${NEW_IF1}"
    sudo nmcli connection modify "${CONN2}" connection.interface-name "${NEW_IF2}"
    if [[ -n "${NEW_PRIMARY}" ]]; then
      sudo nmcli connection modify "${BOND_CONN}" bond.options "mode=active-backup,primary=${NEW_PRIMARY}"
    fi
    sudo nmcli connection up "${CONN1}"
    sudo nmcli connection up "${CONN2}"
    sudo nmcli connection up "${BOND_CONN}"
    
    echo "=== verify ==="
    echo -n "slaves: "; cat /sys/class/net/bond0/bonding/slaves
    echo -n "primary: "; cat /sys/class/net/bond0/bonding/primary
    echo -n "active: "; cat /sys/class/net/bond0/bonding/active_slave
    ip -4 -o addr show dev bond0
    nmcli -g connection.interface-name,connection.master connection show "${CONN1}"
    nmcli -g connection.interface-name,connection.master connection show "${CONN2}"
    nmcli -g bond.options,ipv4.addresses connection show "${BOND_CONN}"
    echo "DONE"
    EOF
    chmod 755 "$HOME/shell/fix-bond-nic-rename.sh"
    ls -la "$HOME/shell/fix-bond-nic-rename.sh"
    END
    

    生成成功后应看到类似:

    -rwxr-xr-x 1 igo igo .... /home/igo/shell/fix-bond-nic-rename.sh
    

    2.2 换卡前确认脚本可用

    在每台待换机上执行:

    ls -la ~/shell/fix-bond-nic-rename.sh
    sha256sum ~/shell/fix-bond-nic-rename.sh
    bash ~/shell/fix-bond-nic-rename.sh
    

    换卡前预期输出类似:

    bond-slave-ens1f0: ens1f0 -> ens1f0
    bond-slave-ens2f0: ens2f0 -> ens2f0
    ...
    No rename needed; bond names already match present ifaces.
    

    2.3 换卡后修复步骤

    带外或 SSH(若仍可达)登录已换卡的那一台,先 dry-run:

    bash ~/shell/fix-bond-nic-rename.sh
    

    确认解析结果正确,例如:

    bond-slave-ens1f0: ens1f0 -> ens1f0np0
    bond-slave-ens2f0: ens2f0 -> ens2f0np0
    bond0 primary: ens2f0 -> ens2f0np0
    

    再执行生效(会变更网络配置):

    bash ~/shell/fix-bond-nic-rename.sh --apply
    

    2.4 验证

    脚本末尾会打印 slaves / primary / bond0 地址等。也可再执行:

    cat /sys/class/net/bond0/bonding/slaves
    cat /sys/class/net/bond0/bonding/primary
    ip -4 -o addr show dev bond0
    ping -c 3 -W 2 10.10.10.254
    

    然后从其它机器测试 SSH:

    ssh -p 5008 igo@igo10X
    

    2.5 脚本无法自动解析时

    若 dry-run 报错(例如旧名消失后找不到唯一前缀匹配、或匹配到多个候选),不要直接 --apply,改用本文第 1 章手动改配置文件,或先根据 ip link 明确新名后再处理。


    回滚建议

    若修改后异常,可用换卡前备份的 .nmconnection.bak.* 恢复,然后:

    sudo nmcli connection reload
    sudo nmcli connection up bond-slave-ens1f0
    sudo nmcli connection up bond-slave-ens2f0
    sudo nmcli connection up bond0
    

    注意:物理网卡已换成新硬件、内核只暴露新网卡名时,恢复成旧名配置无法工作,只能继续按新名修正。


    操作检查清单

    • 确认本次只换 bond 使用的两张业务网卡
    • 换卡前记录本机 interface-nameprimary、IP
    • 换卡后确认新网卡名
    • 脚本方式:各机先执行 2.1 生成脚本,再 dry-run → --apply;或按第 1 章手动改文件
    • 确认 bond0 slaves/primary/IP 正常
    • 确认网关可达、SSH(5008)恢复
    • 单台验证完成后再处理下一台

    MP3