在服务器主机上使用 ifplugd

默认情况下,Linux(Cumulus Linux 除外,因为本文讨论的是服务器主机)不会删除连接接口上的 IP 地址。此外,当链路断开时(如 NO-CARRIER),静态路由不会关联接口。阅读更多关于确定 Linux 上的管理/物理状态的信息

要理解这意味着什么,首先查看 Ubuntu 14.10 VM 的此持久配置,该配置存储在 /etc/network/interfaces 中(而不是 network-manager 中)

auto eth1 iface eth1
inet static 
    address 5.5.5.5 
    netmask 255.255.255.0 
    broadcast 5.5.5.255 
    up route add -net 3.3.0.0/16 gw 5.5.5.1 dev eth1

在此 VM 上,eth1 处于 UP 状态,因为以下输出指示 LOWER_UP。此外,其状态为 UP

user@ubuntu:~$ ip link show eth1
3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT group default qlen 1000 link/ether 00:0c:29:8e:9e:3a brd ff:ff:ff:ff:ff:ff

查看路由表

user@ubuntu:~$ ip route show
default via 192.168.72.2 dev eth0
3.3.0.0/16 via 5.5.5.1 dev eth1
5.5.5.0/24 dev eth1  proto kernel  scope link  src 5.5.5.5
169.254.0.0/16 dev eth1  scope link  metric 1000
192.168.72.0/24 dev eth0  proto kernel  scope link  src 192.168.72.136

请注意以下事项

  • eth1 上的 5.5.5.0/24 连接路由(因为分配的地址是 5.5.5.5,并且位于 255.255.255.0 子网中)
  • 在此 Ubuntu VM 上配置的 3.3.0.0/16 静态路由

接下来,模拟 eth1 上没有连接(例如,有人拔出了电缆)。您可以通过将 VM 中的以太网设备分配给死接口来执行此操作

user@ubuntu:~$ ip link show eth1
3: eth1: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc pfifo_fast state DOWN mode DEFAULT group default qlen 1000
    link/ether 00:0c:29:8e:9e:3a brd ff:ff:ff:ff:ff:f

NO-CARRIERDOWN 状态表示此链路在管理上已启动,但在物理上已关闭。现在检查路由表

user@ubuntu:~$ ip route show
default via 192.168.72.2 dev eth0
3.3.0.0/16 via 5.5.5.1 dev eth1
5.5.5.0/24 dev eth1  proto kernel  scope link  src 5.5.5.5
169.254.0.0/16 dev eth1  scope link  metric 1000
192.168.72.0/24 dev eth0  proto kernel  scope link  src 192.168.72.136

请注意,配置中没有任何更改。虽然这在某些情况下很有用 — 例如,当您的无线网卡在 AP 之间移动并暂时断开连接时,您的 Web 连接不会重置 — 但在其他情况下则不好,并且可能导致流量被黑洞。对于服务器来说,这通常不是问题,除非您正在做一些花哨的事情,例如拥有双网关(两条或多条等成本路由)。在这种情况下,服务器会尝试在死链路上进行负载均衡,因为该接口的路由未被删除,导致 50% 的连接失败,因为它们尝试使用死链路。

演示 ifplugd

在 Ubuntu VM 上重置链路并将 VMware Fusion(虚拟机监控程序)中的链路设置为 UP 后,您可以启动 ifplugd

user@ubuntu:~$ sudo service ifplugd start
 * Network Interface Plugging Daemon...                                          
 * start eth1...                                                         
 [ OK ] 
user@ubuntu:~$                                               

user@ubuntu:~$ service ifplugd status 
* eth1: ifplugd process for device eth1 running as pid 4512. 
user@ubuntu:~$ ip link show eth1 3: eth1: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc pfifo_fast state DOWN mode DEFAULT group default qlen 1000 link/ether 00:0c:29:8e:9e:3a brd ff:ff:ff:ff:ff:ff

此时,电缆已被“切断”,您可以在路由表中看到这一点

user@ubuntu:~$ ip link show eth1
3: eth1: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc pfifo_fast state DOWN mode DEFAULT group default qlen 1000
    link/ether 00:0c:29:8e:9e:3a brd ff:ff:ff:ff:ff:ff
user@ubuntu:~$ ip route show
default via 192.168.72.2 dev eth0
169.254.0.0/16 dev eth0  scope link  metric 1000
192.168.72.0/24 dev eth0  proto kernel  scope link  src 192.168.72.136

请注意,以上输出中不再显示这两条路由。接下来,电缆已重新插入,因此链路恢复为管理上已启动且物理上已启动

user@ubuntu:~$ ip link show eth1
3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT group default qlen 1000
    link/ether 00:0c:29:8e:9e:3a brd ff:ff:ff:ff:ff:ff
user@ubuntu:~$ ip route show
default via 192.168.72.2 dev eth0
3.3.0.0/16 via 5.5.5.1 dev eth1
5.5.5.0/24 dev eth1  proto kernel  scope link  src 5.5.5.5
169.254.0.0/16 dev eth0  scope link  metric 1000
192.168.72.0/24 dev eth0  proto kernel  scope link  src 192.168.72.136

请注意,一切看起来都和以前一样。ifplugd 帮助服务器更像路由器(或第 3 层交换机),并使连接路由和静态路由消失。

在 Ubuntu 14.10 上配置 ifplugd

以下示例使用 ifupdown(而不是 NVIDIA 中的 ifupdown2,也不是 network-manager)。

  1. 运行 apt-get update 以获取最新的软件包信息

    user@ubuntu:~$ sudo apt-get update
    
  2. 安装 ifplugd

    user@ubuntu:~$ sudo apt-get install ifplugd
    Reading package lists... Done
    Building dependency tree       
    Reading state information... Done
    Suggested packages:
      waproamd
    The following NEW packages will be installed:
      ifplugd
    0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded.
    Need to get 0 B/65.1 kB of archives.
    After this operation, 276 kB of additional disk space will be used.
    Preconfiguring packages ...
    Selecting previously unselected package ifplugd.
    (Reading database ... 193504 files and directories currently installed.)
    Preparing to unpack .../ifplugd_0.28-19ubuntu1_amd64.deb ...
    Unpacking ifplugd (0.28-19ubuntu1) ...
    Processing triggers for man-db (2.7.0.2-2) ...
    Processing triggers for ureadahead (0.100.0-16) ...
    user@ubuntu:~$
    
  3. 修改 ifplugd 的默认配置。使用 vinano 或您首选的文本编辑器。如果您仅为 eth1 运行 ifplugd,您应该看到以下输出(通常您用空格分隔两个或多个接口,例如,eth1 eth2 eth3

    cat /etc/default/ifplugd
    #(REMOVE GIANT COMMENT BLOCK FOR BREVITY)
    INTERFACES=""
    HOTPLUG_INTERFACES="eth1"
    ARGS="-q -f -u0 -d0 -w -I"
    SUSPEND_ACTION="none"
    

    标志说明

    标志描述
    -q当守护程序退出时,不要调用脚本进行网络关闭。
    -f忽略检测失败,而是重试。此选项将失败视为“无链路”。
    -u0指定配置接口的延迟。
    -d0指定取消配置接口的延迟。
    -w当守护进程化(创建后台进程)时,请等待后台进程完成初始链路节拍检测。当您启用此选项时,父进程会在退出时返回链路状态。2 表示它检测到链路节拍,3 表示它未检测到链路节拍;其他一切都是错误。
    -I不要在链路更改时执行的程序的非零返回值时退出。
    -M当网络接口不可用时,不要失败。而是使用 netlink 监视设备可用性。这对于 PCMCIA 设备和类似设备很有用。

    要启动 ifplugd,请使用 service ifplugd start 命令

    user@ubuntu:~$ sudo service ifplugd start
     * Network Interface Plugging Daemon...                                          
     * start eth1...                                                         
     [ OK ] 
    

    要检查 ifplugd 是否正在运行,请使用 service ifplugd status 命令

    user@ubuntu:~$ sudo service ifplugd status
     * eth1:                                                                        
     ifplugd process for device eth1 running as pid 16327.
     * eth1:                                                                        
     ifplugd process for device eth1 running as pid 16327.