我最近在专门为托管一些虚拟机而构建的新服务器机箱上安装了 Ubuntu Utopic 14.04 LTS。此机箱的网络配置包含两个 NIC,仅通过虚拟桥接器公开这两个 NIC - 一个连接到专用网络,一个连接到面向公众的 Internet。一个来宾 VM 将通过分路器访问两个桥接器,用作主机的防火墙和网关,以及专用网络的一般防火墙和网关。另一个 VM 将只是专用网络上的单独来宾服务器。主机将仅通过相应的专用桥接器直接参与专用网络。
因此,除了其相应虚拟网桥的上下文之外,eth0 和 eth1 都不会处于“启动”状态。然而,当 Ubuntu 启动时,我认为 upstart 的故障保护错误地假设(坚持?)至少 eth0 独立启动,然后它才会允许系统通过故障保护所施加的 20/40/60 秒延迟。然而,在启动完成并允许客户虚拟机不受约束地启动之前,延迟几乎没有希望得到解决!看到悖论了吗?说实话,我不确定 eth0 和 eth1 是否会曾经达到故障安全状态是件很难的事。
从最原始、最反动的层面来说,我内心沮丧、非 Ubuntu 的一面想要取消故障保护,因为每次重启配置更改都迫使我等待长达两分钟的状态更改,而我 99.9% 确定这种状态更改永远不会发生通过设计底线——没有故障安全依赖。我只是想让那些我意识到故障安全强制执行的额外障碍消失。
出于同样的原因,我试图至少在某种程度上对 Upstart 尝试使用故障保护做什么持开放态度,因为这是我第一次接触它。我看到一些(非常模糊的)信息,其中一种方法是改变 /etc/network/interfaces 的设置方式,将我的桥接设置移到它们自己的 Upstart 任务中,但我真的更愿意让我的接口定义保持原样,让它正常运行。
那么,我有什么选择呢?我是否可以只消除故障保护任务,或对其进行修改以改变其条件?如果可以,该怎么做?我必须破解我的接口文件吗?
答案1
首先,我为回答我自己的问题而道歉。
其次,事实上,我已经解决了 failsafe.conf 启动延迟问题。虽然我知道这个问题没有太多讨论,但我在其他各种帖子中看到了很多关于类似故障安全/启动延迟问题的活动,所以我将我的研究和解决方案发布出来,供其他遇到类似问题的人参考。
概述
正如在最初的帖子中提到的,我发现的问题是故障安全启动作业对我的系统启动施加了不必要的限制。然后我进一步研究了这个问题,发现了故障安全行为如此的原因。
分析
默认情况下,failsafe.conf 定义了一个启动条件,该条件在启动时有效地触发它(只要文件系统和环回接口可用),并定义了两个可能的停止条件之一:
start on filesystem and net-device-up IFACE=lo
stop on static-network-up or starting rc-sysinit
Failsafe 坚持延迟是因为没有触发“停止”事件。第二个条件 rc-sysinit 是 upstart 运行的最后一个系统初始化任务之一,它有自己的启动条件
start on (filesystem and static-network-up) or failsafe-boot
不具备故障保护功能停止,显然 rc-sysinit 不是开始。一旦超时到期,Failsafe 将发出 failsafe-boot 事件。鉴于 failsafe 已启动,因此隐含“文件系统”,因此两个事件唯一共同的条件是“static-network-up”。Failsafe 正在运行,因为它认为没有任何网络接口处于“up”状态。
原因
通过 /etc/network/if-up.d 反向操作,定义了一个 upstart 脚本,该脚本迭代 /etc/network/interfaces 中定义的所有网络接口,这些接口使用“auto”限定符定义,这意味着该接口将在启动时启动。如何将接口视为“启动”的定义成为一个重要的语义问题,我将在后面进行描述。
当且仅当所有“自动”配置的接口都处于“启动”状态时,upstart 脚本才会发出著名的“static-network-up”事件。这反过来又会允许 rc-sysinit 触发并终止故障保护 - 这就是我的问题的根本原因。我的网络接口在启动时都没有 IP 地址 - 这是设计使然。但“static-network-up”并不遵循接口处于“启动”状态的想法没有一个 IP 地址,因此故障安全会挂起,直到超时为止。
就我的情况而言,我将盒子中的两个物理网卡从属于网桥,并通过分接头将它们暴露给两个不同的虚拟机。一个虚拟机通过一个分接头提供 DHCP,另一个只是同一网络上的服务器。为了使网桥在虚拟机的分接头下正常工作,网卡必须至少处于“UP”状态,被动允许数据包通过。因此,在 /etc/network/interfaces 中使用“auto”似乎是合适的。不是然而,在故障安全看来,这是不合适的,因此唯一的解决方案必须是遵守故障安全语义的解决方案。
那么,解决我的问题的方法有两个:
- 从我定义的每个网络接口(环回除外)中删除“自动”声明。
- 创建 upstart 作业以“手动”启动以前的“自动”界面。
我模仿提供的解决方案,为四台设备(两个分接头和两个虚拟桥)分别定义了一项工作这里。
在此配置中,没有“自动”接口,网络脚本现在应该立即发出“static-network-up”,从而强制终止故障保护。最后的修改要求我在每个分接头的接口定义中添加一个“post-up”子句,以调用“brctl”并创建相应的虚拟网桥,这之前是作为“自动”配置的一部分完成的。
因此,我的 /etc/network/interfaces(部分)现在看起来像:
#auto tpRED (commented out)
iface tpRED inet manual
pre-up /usr/sbin/tunctl -t tpRED
post-up /sbin/brctl addbr brRED
#auto brRED
iface brRED inet manual
bridge_ports eth1 tpRED
bridge_hw xx:yy:aa:bb:cc:dd
严峻考验
酸性测试?重启服务器。当我重启服务器时,故障保护超时已消失,我的网络在功能上完全相同的配置下运行。它成功了!!我只是希望我们能更好地处理“UP”网络接口的语义!!