VMware FT: Practical System for Fault-Tolerant Virtual Machines
本文将介绍2010年由VMware公司提出的商业级的容错虚拟机系统,该系统基于VMware vSphere 4.0设计。该系统通过在另一台服务器上复制主虚拟机的执行来提供容错支持,同时可以在故障发生后自动恢复冗余。
论文参考:《The Design of a Practical System for Fault-Tolerant Virtual Machines》
虚拟机容错技术
在现代服务器架构中,容错技术对于保证服务的持续性和可靠性至关重要。其中,主备模式作为一种经典的容错解决方案,一直受到广泛关注。这种模式的核心在于维持一个随时可以接管的备用服务器,确保在主服务器发生故障时能够无缝切换。
传统的容错实现方式主要依赖于状态复制,即直接复制主服务器上的所有状态变化,包括CPU状态、内存内容和I/O设备状态等。这种方法虽然直观,但需要消耗大量网络带宽,在实际应用中往往面临效率瓶颈。
相比之下,状态机方法提供了一种更为高效的解决方案。这种方法将服务器视为确定性的状态机,通过确保主备服务器从相同的初始状态启动,并按相同顺序接收输入请求来维持同步。这种方法大大减少了需要传输的数据量,提高了系统效率。
VMware vSphere 4.0平台在这一领域取得了重要突破。通过虚拟机技术,它成功实现了高效的容错系统。该系统基于确定性重放技术,不仅完整支持x86架构,还能在故障发生后自动在集群中启动新的备份虚拟机。
虚拟机平台为实现状态机方法提供了理想环境,因为虚拟机本身就是一个定义明确的状态机,而Hypervisor可以完全控制虚拟机的执行过程。这种实现方式不仅可以在普通商用硬件上直接部署,而且由于带宽需求较低,主备服务器可以部署在物理距离较远的位置,进一步提高了系统的可靠性。
这种创新的容错技术为企业级应用提供了强有力的保障,不仅确保了服务的连续性,还实现了故障后的自动恢复,代表了服务器容错技术的重要发展方向。
FT(Fault-Tolerant)设计
VMware FT的基本配置如下图:
在VMware的容错系统中,主备虚拟机采用了一种优雅的同步机制。主虚拟机在一台物理服务器上运行,而备份虚拟机则在另一台物理服务器上运行,两者保持虚拟锁同步,只是备份虚拟机会有轻微的时间延迟。系统的存储架构采用共享存储方案,主备虚拟机都可以访问存储在光纤通道或iSCSI磁盘阵列上的虚拟磁盘。在网络通信方面,只有主虚拟机会在网络上公开自己的存在,因此所有的网络输入、键盘输入和鼠标操作都只会直接发送给主虚拟机。
为了保持同步,系统设计了一个称为日志通道的网络连接(channel)。主虚拟机接收到的所有输入都会通过这个通道转发给备份虚拟机。系统还会传输必要的额外信息,确保备份虚拟机能以完全相同的方式执行非确定性操作。虽然备份虚拟机会执行相同的操作,但其输出会被hypervisor拦截,只有主虚拟机的输出才会返回给客户端。
为了确保系统的可靠性,主备虚拟机之间遵循特定的协议,包括备份虚拟机的显式确认机制,这样可以保证在主虚拟机发生故障时不会丢失数据。系统通过心跳检测和日志通道流量监控来及时发现虚拟机故障,并且即使在发生脑裂情况时,也能确保只有一个虚拟机接管执行。
确定性重放的实现
在VMware的容错系统中,虚拟机的执行可以被视为确定性状态机的复制。为了确保备份虚拟机的执行与主虚拟机完全一致,必须在相同的初始状态下启动两台虚拟机,并提供相同顺序的输入。然而,虚拟机的输入来源广泛,包括网络数据包、磁盘读取以及键盘和鼠标输入。此外,非确定性事件(如虚拟中断)和操作(如读取处理器时钟周期计数器)也会影响虚拟机的状态,这给复制执行带来了挑战。具体而言,复制虚拟机执行面临三个主要挑战:首先,需要准确捕获所有输入和非确定性因素,以确保备份虚拟机能够进行确定性执行;其次,需要正确地将这些输入和非确定性因素应用于备份虚拟机;最后,所有这些操作必须在不影响性能的情况下完成。此外,许多复杂的x86微处理器操作会产生未定义的非确定性副作用,这进一步增加了实现难度。
VMware的确定性重放技术正是为了解决这些问题而设计。它通过记录虚拟机的输入及其相关的所有非确定性因素,将信息以日志条目的形式写入日志文件,从而在后续可以精确重放虚拟机执行。在重放过程中,系统会在相应的指令流中准确地交付事件,例如定时器或I/O完成中断等非确定性事件。VMware确定性重放实现了一种高效的事件记录和交付机制,采用了与AMD和Intel合作开发的硬件性能计数器等多种技术。与其他方法不同,VMware不需要将虚拟机执行划分为时间片(epoch),而是能够在每次中断发生时立即记录并在重放时高效地交付。通过这种方式,VMware确保了主备虚拟机之间的一致性,同时保持了良好的性能。
FT协议
在VMware的容错系统中,确定性重放技术用于生成必要的日志条目,以记录主虚拟机的执行。这些日志条目通过日志管道实时发送给备份虚拟机,而不是写入磁盘。备份虚拟机在接收到这些条目后,能够实时重放,从而确保其执行与主虚拟机完全一致。为了实现故障容错,必须在日志管道上增强日志条目的传输协议。
- 输出要求(Output Requirement):如果备份虚拟机在主虚拟机发生故障后接管执行,它必须以一种与主虚拟机之前发送给外部世界的所有输出完全一致的方式继续执行。
虽然在主虚拟机故障,备份虚拟机接管后,备份虚拟机的执行可能会与主虚拟机有所不同,但只要满足输出要求,就不会丢失任何可见状态或数据,客户也不会感受到服务中断或不一致。为确保输出要求,系统会延迟任何外部输出(如网络数据包),直到备份虚拟机接收到所有必要的信息,以便能够重放到该输出操作的时刻。这意味着备份虚拟机必须先接收到所有在输出操作之前生成的日志条目。如果在主虚拟机执行输出操作后立即发生故障,备份虚拟机需要知道必须继续重放,直到达到输出操作的时刻,然后再“上线”成为新的主虚拟机。为此,系统引入了一个特定规则:
- 输出规则(Output Rule)主虚拟机不能向外界发送输出,直到备份虚拟机收到并确认与该输出操作相关的日志条目。
这一规则确保备份虚拟机能够准确重现主虚拟机在输出时的状态,从而保证在发生故障时的一致性。需要注意的是,这一规则并不要求停止主虚拟机的执行,只需延迟发送输出即可。由于操作系统通常采用非阻塞方式进行网络和磁盘输出,因此主虚拟机可以继续执行,不会因为输出延迟而受到影响。此外,在发生接管的情况下,无法保证所有输出都被精确地产生一次,但网络基础设施(如TCP)能够处理丢失和重复的数据包,从而减轻这一问题带来的影响。
下图是一个FT协议要求的流程展示:
图中由两条时间线组成,分别为主服务器和备份服务器,由主服务器到备份服务器的箭头表示一条日志条目被传输,由备份服务器到主服务器的箭头表示备份服务器对主服务器的回应。这里可以看到,在备份服务器接管后它可以从输出点继续主服务器的任务。
故障检测与响应
在VMware的容错系统中,主虚拟机和备份虚拟机必须快速响应彼此可能发生的故障。如果备份虚拟机出现故障,主虚拟机会“上线”,即停止记录模式并正常执行。如果主虚拟机发生故障,备份虚拟机也需“上线”,但这一过程更为复杂。由于备份虚拟机的执行存在延迟,它可能会有一些已接收并确认但尚未消耗的日志条目。备份虚拟机需要继续重放这些日志条目,直到消耗完最后一条日志条目,然后才会转为正常执行模式,成为新的主虚拟机。在这个过程中,新的主虚拟机会开始向外界输出数据。为了确保网络正常工作,VMware FT会自动在网络上广播新主虚拟机的MAC地址。此外,新主虚拟机可能还需要重新发出一些磁盘I/O请求。
为了检测主备虚拟机的故障,VMware FT使用UDP心跳机制监控运行容错虚拟机的服务器,并监控从主虚拟机到备份虚拟机的日志流量及其确认信息。正常情况下,日志流量应该是规律且持续的,因此如果日志条目或确认信息的流动停止超过特定超时时间(通常为几秒钟),则可能表明发生了故障。然而,这种故障检测方法可能会导致“脑裂”问题:如果备份服务器没有接收到来自主服务器的心跳信号,这可能意味着主服务器已故障,也可能只是网络连接丢失。如果备份虚拟机在主虚拟机仍在运行时错误地上线,可能会导致数据损坏。因此,必须确保只有一个虚拟机在检测到故障时上线。为避免脑裂问题,系统利用存储在共享存储上的虚拟磁盘。当任一虚拟机想要上线时,它会在共享存储上执行原子设置操作。如果操作成功,该虚拟机被允许上线;如果失败,则表明另一台虚拟机已经上线,此时当前虚拟机会自我终止。如果无法访问共享存储,则该虚拟机会等待直到可以访问。值得注意的是,如果由于存储网络故障导致无法访问共享存储,那么该虚拟机也无法进行有效工作。
最后,一旦发生故障并且某个虚拟机已上线,VMware FT会自动在另一台主机上启动新的备份虚拟机,以恢复冗余。这一过程对于实现有效的容错至关重要,并需要精心设计。
FT的其他组件
为了创建一个可用的、健壮的和自动化的系统,还必须设计和实现许多其他的组件。
启动和重启容错虚拟机
在VMware的容错系统中,设计一个机制以在与主虚拟机相同的状态下启动备份虚拟机是至关重要的。这一机制同样适用于在发生故障后重启备份虚拟机。该机制需要能够处理处于任意状态的正在运行的主虚拟机,并且应尽量减少对主虚拟机执行的干扰,以免影响当前客户。为此,VMware FT采用了现有的VMotion功能。VMware VMotion允许在几乎没有中断的情况下将运行中的虚拟机从一台服务器迁移到另一台服务器,通常暂停时间少于一秒。VMware创建了一种修改版的VMotion,能够在远程服务器上创建主虚拟机的精确运行副本,而不销毁本地服务器上的虚拟机。这种FT VMotion会设置日志通道,使源虚拟机进入记录模式作为主虚拟机,而目标虚拟机则进入重放模式作为新的备份虚拟机。
启动备份虚拟机的另一个方面是选择运行它的服务器。容错虚拟机在访问共享存储的服务器集群中运行,因此所有虚拟机通常可以在集群中的任何服务器上运行。这种灵活性使得VMware vSphere能够在一个或多个服务器发生故障时恢复容错冗余。当发生故障并且主虚拟机需要新的备份虚拟机以重新建立冗余时,主虚拟机会通知集群服务。集群服务根据资源使用情况和其他约束条件确定最佳服务器来运行备份虚拟机,并调用FT VMotion来创建新的备份虚拟机。因此,VMware FT通常能够在几分钟内重新建立虚拟机冗余,而不会对容错虚拟机的执行造成明显干扰。
管理日志通道
日志通道和buffer关系如下图所示:
在VMware的容错系统中,管理进程会为主虚拟机和备份虚拟机维护一个大型日志缓冲区。主虚拟机生成的日志条目会尽快刷新到日志通道,而备份虚拟机会及时读取这些条目并发送确认信息。这些确认信息帮助VMware FT确定何时可以发送因输出规则而延迟的输出。如果备份虚拟机遇到空的日志缓冲区,它会暂停执行,直到有新条目可用;这不会影响客户,因为在主虚拟机正常时,它不同外界交互。相反,如果主虚拟机的日志缓冲区满了,它必须暂停执行,可能会影响客户(无法处理请求)。因此,需设计机制以避免主日志缓冲区填满。同时,执行延迟过大可能导致问题。如果主虚拟机故障,备份虚拟机需要重放所有已确认的日志条目,因此希望保持执行延迟时间较小(不超过一秒)。为此,系统通过监测主备虚拟机之间的实时执行延迟来调整主虚拟机的CPU分配。如果备份虚拟机滞后超过一秒,主虚拟机会被减速(减少它的CPU分配数量);反之则增加其CPU限制。这种减速通常很少发生,主要在系统压力较大时才会出现。
FT虚拟机的操作
在VMware的容错系统中,处理主虚拟机的各种控制操作是一个实际问题。例如,当主虚拟机被显式关闭时,备份虚拟机也应停止,避免尝试上线。此外,主虚拟机上的资源管理变更(如增加CPU共享)也应应用于备份虚拟机。为此,主虚拟机会通过日志通道向备份发送特殊控制条目,以执行相应操作。
一般来说,大多数操作应仅在主虚拟机上发起,而VMware FT会将必要的控制条目发送到备份虚拟机。唯一可以独立进行的操作是VMotion,即主备虚拟机可以分别迁移到其他主机,但VMware FT确保两者不会迁移到同一服务器,以保持容错能力。主虚拟机的VMotion比普通VMotion复杂,因为备份虚拟机必须在适当时刻与新的主虚拟机重新连接。备份虚拟机的VMotion也面临类似的问题,但更为复杂。在普通VMotion中,所有未完成的磁盘I/O必须在最终切换时完成。对于主虚拟机,这一过程相对简单;而对于备份虚拟机,由于其需重放主虚拟机的执行,因此难以在特定时刻完成所有I/O。为了解决这一问题,当备份虚拟机达到VMotion的最终切换点时,它会通过日志通道请求主虚拟机暂时暂停所有I/O操作。这样,在重放主虚拟机的暂停操作时,备份虚拟机的I/O也能自然地在同一执行点上被暂停。
磁盘IO的实现问题
在VMware的容错系统中,磁盘I/O的实现涉及多个细微问题。首先,由于磁盘操作是非阻塞的,多个同时访问同一磁盘位置的操作可能导致非确定性。此外,VM直接使用DMA进行虚拟机内存与磁盘之间的数据传输,这也可能引发非确定性。为了解决这一问题,VM会检测到任何I/O竞争(虽然这种情况较少),并强制这些竞争的磁盘操作在主备虚拟机上顺序执行。
其次,磁盘操作可能与虚拟机内应用程序或操作系统的内存访问发生竞争。例如,当应用程序正在读取某个内存块时,如果同时进行对该块的磁盘读取,可能会导致非确定性结果。虽然这种情况不常见,但VM必须检测并处理。解决方案之一是暂时对目标内存页设置保护,以防止在磁盘操作进行时发生访问。由于更改内存管理单元(MMU)保护是一项昂贵的操作,VM选择使用“跳跃缓冲区”(bounce buffer)。跳跃缓冲区是一个临时缓冲区,其大小与正在访问的内存相同。磁盘读取操作会先将数据读入跳跃缓冲区,然后在I/O完成时将数据复制到客户内存中;而写入操作则先将数据复制到跳跃缓冲区,再从该缓冲区写入磁盘。
第三,当主虚拟机发生故障并且备份虚拟机接管时,未完成的磁盘I/O会引发问题。新晋升的主虚拟机无法确认这些I/O是否已成功发出或完成。此外,由于备份虚拟机未发出这些I/O,因此在继续运行时不会收到明确的I/O完成信号,这可能导致客户操作系统启动中止或重置程序。VM可以发送错误完成信号来指示某个I/O失败,但这可能会导致客户操作系统对本地磁盘错误反应不佳。因此,在备份虚拟机上线过程中,VM会重新发出待处理的I/O请求。由于VM已经消除了所有竞争,并且所有I/O都明确指定了访问的内存和磁盘块,这些磁盘操作即使已成功完成也可以重新发出(即它们是幂等的)。
网络IO的实现问题
在VMware vSphere中,网络性能优化主要依赖于管理进程异步更新虚拟机网络设备的状态。然而,这种异步更新会引入非确定性,可能导致备份虚拟机的执行与主虚拟机不一致。因此,在容错模式下,禁用了异步网络优化,所有网络数据包的处理都需要通过管理进程进行。
在VMware的容错模式下,为了提高网络性能,采取了两项优化措施。首先,通过集群优化减少虚拟机的陷阱和中断。当虚拟机以足够的速度传输数据时,管理进程可以将多个数据包合并为一次传输操作,从而减少陷阱的数量。其次,为了降低数据传输的延迟,管理进程确保在发送和接收日志条目及确认信息时不会发生线程上下文切换。这是通过在TCP栈中注册特定函数来实现的,使得可以快速处理日志消息和确认信息。这些优化措施旨在确保在容错模式下仍能保持良好的网络性能。此外,当主虚拟机排队传输数据包时,系统会立即刷新相关的输出日志条目,以减少延迟。这些措施旨在确保在容错模式下仍能保持良好的网络性能
一些替代方案
共享磁盘与非共享磁盘
在默认设计中,主虚拟机和备份虚拟机共享相同的虚拟磁盘。这种设计确保在故障切换发生时,磁盘内容是正确且可用的。主虚拟机负责对共享磁盘进行实际写入,并且写入操作需遵循输出规则(Output Rule)的延迟要求。另一种设计是让主虚拟机和备份虚拟机拥有各自独立的虚拟磁盘。在这种情况下,备份虚拟机会对其虚拟磁盘进行所有写入操作,从而保持与主虚拟机磁盘内容的一致性。这种非共享设计在共享存储不可用或成本过高时非常有用,尤其是在主备虚拟机距离较远的情况下。
然而,非共享设计的一个缺点是,在启用容错时,两个虚拟磁盘必须以某种方式显式同步。此外,在发生故障后,磁盘可能会失去同步,因此在备份虚拟机重启后需要重新同步。非共享磁盘配置中可能没有可用于解决脑裂问题的共享存储,此时系统可以使用其他外部仲裁者,例如一个双方均可通信的第三方服务器。如果服务器属于一个包含多个节点的集群,则可以基于集群成员资格使用多数算法来决定哪个虚拟机可以上线。
非共享磁盘的结构如下图所示:
在备份虚拟机上执行磁盘读
在VMware FT的默认设计中,备份虚拟机不直接读取其虚拟磁盘,而是通过日志通道接收磁盘读取结果。虽然这种设计确保了数据一致性,但对于频繁进行磁盘读取的工作负载,日志通道的流量可能较大。另一种替代设计是让备份虚拟机执行磁盘读取,从而消除对磁盘读取数据的日志记录。这可以减少日志通道的流量,但也带来复杂性。备份虚拟机必须等待所有磁盘读取完成,如果主虚拟机的读取成功而备份失败,则备份需重试该操作;反之,若主虚拟机读取失败,则需通过日志通道发送目标内存内容。在共享磁盘配置下,如果主虚拟机对某个位置进行读取后又进行写入,则写入操作必须延迟,直到备份虚拟机完成第一次读取。这种依赖关系增加了实现复杂性。
总结
VMware Fault-Tolerance (VMFT) 是一种关键的技术,旨在确保虚拟机在发生故障时的高可用性和连续性。通过主备虚拟机的架构,VMFT 实现了实时数据同步和无缝故障切换,使得在主虚拟机出现问题时,备份虚拟机能够迅速接管其任务,确保服务的持续运行。该技术通过使用确定性重放、共享或非共享磁盘配置以及优化的网络和磁盘 I/O 操作来减少延迟和带宽消耗,从而提高性能。尽管 VMFT 的实现面临诸多挑战,如处理非确定性操作和确保数据一致性,但其在企业级应用中的重要性不容忽视。随着技术的发展,VMFT 将继续为用户提供更可靠的解决方案,以应对日益复杂的 IT 环境和业务需求。