[RFC] High availability in KVM

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



We are trying to improve the integration of KVM with the most common
HA stacks, but we would like to share with the community what we are
trying to achieve and how before we take a wrong turn.

This is a pretty long write-up, but please bear with me.
---


 Virtualization has boosted flexibility on the data center, allowing
 for efficient usage of computer resources, increased server
 consolidation, load balancing on a per-virtual machine basis -- you
 name it, However we feel there is an aspect of virtualization that
 has not been fully exploited so far: high availability (HA).

 Traditional HA solutions can be classified in two groups: fault
 tolerant servers, and software clustering.

 Broadly speaking, fault tolerant servers protect us against hardware
 failures and, generally, rely on redundant hardware (often
 proprietary), and hardware failure detection to trigger fail-over.

 On the other hand, software clustering, as its name indicates, takes
 care of software failures and usually requires a standby server
 whose software configuration for the part we are trying to make
 fault tolerant must be identical to that of the active server.

 Existing open source HA stacks such as pacemaker/corosync and Red
 Hat Cluster Suite rely on software clustering techniques to detect
 both hardware failures and software failures, and employ fencing to
 avoid split-brain situations which, in turn, makes it possible to
 perform failover safely. However, when applied to virtualization
 environments these solutions show some limitations:

   - Hardware detection relies on polling mechanisms (for example
     pinging a network interface to check for network connectivity),
     imposing a trade off between failover time and the cost of
     polling. The alternative is having the failing system send an
     alarm to the HA software to trigger failover. The latter
     approach is preferable but it is not always applicable when
     dealing with bare-metal; depending on the failure type the
     hardware may not able to get a message out to notify the HA
     software. However, when it comes to virtualization environments
     we can certainly do better. If a hardware failure, be it real
     hardware or virtual hardware, is fully contained within a
     virtual machine the host or hypervisor can detect that and
     notify the HA software safely using clean resources.

   - In most cases, when a hardware failure is detected the state of
     the failing node is not known which means that some kind of
     fencing is needed to lock resources away from that
     node. Depending on the hardware and the cluster configuration
     fencing can be a pretty expensive operation that contributes to
     system downtime. Virtualization can help here. Upon failure
     detection the host or hypervisor could put the virtual machine
     in a quiesced state and release its hardware resources before
     notifying the HA software, so that it can start failover
     immediately without having to mingle with the failing virtual
     machine (we now know that it is in a known quiesced state). Of
     course this only makes sense in the event-driven failover case
     described above.

   - Fencing operations commonly involve killing the virtual machine,
     thus depriving us of potentially critical debugging information:
     a dump of the virtual machine itself. This issue could be solved
     by providing a virtual machine control that puts the virtual
     machine in a known quiesced state, releases its hardware
     resources, but keeps the guest and device model in memory so
     that forensics can be conducted offline after failover. Polling
     HA resource agents should use this new command if postmortem
     analysis is important.

 We are pursuing a scenario where current polling-based HA resource
 agents are complemented with an event-driven failure notification
 mechanism that allows for faster failover times by eliminating the
 delay introduced by polling and by doing without fencing. This would
 benefit traditional software clustering stacks and bring a feature
 that is essential for fault tolerance solutions such as Kemari.

 Additionally, for those who want or need to stick with a polling
 model we would like to provide a virtual machine control that
 freezes a virtual machine into a failover-safe state without killing
 it, so that postmortem analysis is still possible.

 In the following sections we discuss the RAS-HA integration
 challenges and the changes that need to be made to each component of
 the qemu-KVM stack to realize this vision. While at it we will also
 delve into some of the limitations of the current hardware error
 subsystems of the Linux kernel.


HARDWARE ERRORS AND HIGH AVAILABILITY

 The major open source software stacks for Linux rely on polling
 mechanisms to detect both software errors and hardware failures. For
 example, ping or an equivalent is widely used to check for network
 connectivity interruptions. This is enough to get the job done in
 most cases but one is forced to make a trade off between service
 disruption time and the burden imposed by the polling resource
 agent.

 On the hardware side of things, the situation can be improved if we
 take advantage of CPU and chipset RAS capabilities to trigger
 failover in the event of a non-recoverable error or, even better, do
 it preventively when hardware informs us things might go awry. The
 premise is that RAS features such as hardware failure notification
 can be leveraged to minimize or even eliminate service
 down-times.

 Generally speaking, hardware errors reported to the operating system
 can be classified into two broad categories: corrected errors and
 uncorrected errors. The later are not necessarily critical errors
 that require a system restart; depending on the hardware and the
 software running on the affected system resource such errors may be
 recoverable. The picture looks like this (definitions taken from
 "Advanced Configuration and Power Interface Specification, Revision
 4.0a" and slightly modified to get rid of ACPI jargon):

   - Corrected error: Hardware error condition that has been
     corrected by the hardware or by the firmware by the time the
     kernel is notified about the existence of an error condition.

   - Uncorrected error: Hardware error condition that cannot be
     corrected by the hardware or by the firmware. Uncorrected errors
     are either fatal or non-fatal.

       o A fatal hardware error is an uncorrected or uncontained
	  error condition that is determined to be unrecoverable by
	  the hardware. When a fatal uncorrected error occurs, the
	  system is usually restarted to prevent propagation of the
	  error.

       o A non-fatal hardware error is an uncorrected error condition
	  from which the kernel can attempt recovery by trying to
	  correct the error. These are also referred to as correctable
	  or recoverable errors.

 Corrected errors are inoffensive in principle, but they may be
 harbingers of fatal non-recoverable errors. It is thus reasonable in
 some cases to do preventive failover or live migration when a
 certain threshold is reached. However this is arguably the job
 systems management software, not the HA, so this case will not be
 discussed in detail here.

 Uncorrected errors are the ones HA software cares about.

 When a fatal hardware error occurs the firmware may decide to
 restart the hardware. If the fatal error is relayed to the kernel
 instead the safest thing to do is to panic to avoid further
 damage. Even though it is theoretically possible to send a
 notification from the kernel's error or panic handler, this is a
 extremely hardware-dependent operation and will not be considered
 here. To detect this type of failures one's old reliable
 polling-based resource agent is the way to go.

 Non-fatal or recoverable errors are the most interesting in the
 pack.  Detection should ideally be performed in a non-intrusive way
 and feed the policy engine with enough information about the error
 to make the right call. If the policy engine decides that the error
 might compromise service continuity it should notify the HA stack so
 that failover can be started immediately.


REQUIREMENTS

 * Linux kernel

 One of the main goals is to notify HA software about hardware errors
 as soon as they are detected so that service downtime can be
 minimized. For this a hardware error subsystem that follows an
 event-driven model is preferable because it allows us to eliminate
 the cost associated with polling. A file based API that provides a
 sys_poll interface and process signaling both fit the bill (the
 latter is pretty limited in its semantics an may not be adequate to
 communicate non-memory type errors).

 The hardware error subsystem should provide enough information to be
 able to map error sources (memory, PCI devices, etc) to processes or
 virtual machines, so that errors can be contained. For example, if a
 memory failure occurs but only affects user-space addresses being
 used by a regular process or a KVM guest there is no need to bring
 down the whole machine.

 In some cases, when a failure is detected in a hardware resource in
 use by one or more virtual machines it might be necessary to put
 them in a quiesced state before notifying the associated qemu
 process.

 Unfortunately there is no generic hardware error layer inside the
 kernel, which means that each hardware error subsystem does its own
 thing and there is even some overlap between them. See HARDWARE ERRORS IN LINUX below for a brief description of the current mess.

 * qemu-kvm

 Currently KVM is only notified about memory errors detected by the
 MCE subsystem. When running on newer x86 hardware, if MCE detects an
 error on user-space it signals the corresponding process with
 SIGBUS. Qemu, upon receiving the signal, checks the problematic
 address which the kernel stored in siginfo and decides whether to
 inject the MCE to the virtual machine.

 An obvious limitation is that we would like to be notified about
 other types of error too and, as suggested before, a file-based
interface that can be sys_poll'ed might be needed for that.
 On a different note, in a HA environment the qemu policy described
 above is not adequate; when a notification of a hardware error that
 our policy determines to be serious arrives the first thing we want
 to do is to put the virtual machine in a quiesced state to avoid
 further wreckage. If we injected the error into the guest we would
 risk a guest panic that might detectable only by polling or, worse,
 being killed by the kernel, which means that postmortem analysis of
 the guest is not possible. Once we had the guests in a quiesced
 state, where all the buffers have been flushed and the hardware
 sources released, we would have two modes of operation that can be
 used together and complement each other.

   - Proactive: A qmp event describing the error (severity, topology,
     etc) is emitted. The HA software would have to register to
     receive hardware error events, possibly using the libvirt
     bindings. Upon receiving the event the HA software would know
     that the guest is in a failover-safe quiesced state so it could
     do without fencing and proceed to the failover stage directly.

   - Passive: Polling resource agents that need to check the state of
     the guest generally use libvirt or a wrapper such as virsh. When
     the state is SHUTOFF or CRASHED the resource agent proceeds to
     the facing stage, which might be expensive and usually involves
     killing the qemu process. We propose adding a new state that
     indicates the failover-safe state described before. In this
     state the HA software would not need to use fencing techniques
     and since the qemu process is not killed postmortem analysis of
     the virtual machine is still possible.


HARDWARE ERRORS IN LINUX

 In modern x86 machines there is a plethora of error sources:

   - Processor machines check exception.
   - Chipset error message signals.
   - APEI (ACPI4).
   - NMI.
   - PCIe AER.
   - Non-platform devices (SCSI errors, ATA errors, etc).

 Detection of processor, memory, PCI express, and platform errors in
 the Linux kernel is currently provided by the MCE, the EDAC, and the
 PCIe AER subsystems, which covers the first 5 items in the list
 above. There is some overlap between them with regard to the errors
 they can detect and the hardware they poke into, but they are
 essentially independent systems with completely different
 architectures. To make things worse, there is no standard mechanism
 to notify about non-platform devices beyond the venerable printk().

 Regarding the user space notification mechanism, things do not get
 any better. Each error notification subsystem does its own thing:

   - MCE: Communicates with user space through the /dev/mcelog
     special device and
     /sys/devices/system/machinecheck/machinecheckN/. mcelog is
     usually the tool that hooks into /dev/mcelog (this device can be
     polled) to collect and decode the machine check errors.
     Alternatively,
     /sys/devices/system/machinecheck/machinecheckN/trigger can be
     used to set a program to be run when a machine check event is
     detected. Additionally, when an machine check error that affects
     only user space processes they are signaled SIGBUS.

     The MCE subsystem used to deal only with CPU errors, but it was
     extended to handle memory errors too and there is also initial
     support for ACPI4's APEI. The current MCE APEI implementation
     reaps memory errors notified through SCI, but support for other
     errors (platform, PCIe) and transports covered in the
     specification is in the works.

   - EDAC: Exports memory errors, ECC errors from non-memory devices
     (L1, L2 and L3 caches, DMA engines, etc), and PCI bus parity and
     SERR errors through /sys/devices/system/edac/*.

   - NMI: Uses printk() to write to the system log. When EDAC is
     enabled the NMI handler can also instruct EDAC to check for
     potential ECC errors.

   - PCIe AER subsystem: Notifies PCI-core and AER-capable drivers
     about errors in the PCI bus and uses printk() to write to the
     system log.
---


I would appreciate your comments and advice on any of the issues
presented here.

Thanks,
Fernando

--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]
  Powered by Linux