(WS11-08) CEP-basiertes Management virtueller Maschinen

Aus Verteilte Systeme - Wiki
Wechseln zu: Navigation, Suche

Einleitung

CEP (Complex Event Processing) dient der systematischen und automatischen Verarbeitung von Ereignissen. Die Verarbeitung der Ereignisse soll möglichst zeitnah zum Eintritt der Ereignisse geschehen und kontinuierlich ausgeführt werden. Durch geschickte Kombination verschiedener, einfacher Ereignisse ist es möglich komplexere Ereignisse zu modellieren, um dann darauf reagieren zu können. Ein einfaches Beispiel aus der Praxis wäre etwa, aus dem Ereignis "Rauchentwicklung" und dem Ereignis "Hohe Temperatur" auf das komplexere Ereignis "Es brennt" zu schließen und als Reaktion einen Feueralarm auszulösen.

Inhalt des Projektes ist CEP-basiertes Management virtueller Maschinen. Dabei soll mit Hilfe von CEP bestimmte Ereignisse, die von einer virtuellen Maschine ausgelöst werden, verarbeitet werden und die entsprechenden Managementmaßnahmen ausgeführt werden. Als maßgebliche Technologien sollen dabei Esper und libvirt zum Einsatz kommen.

Projektbeschreibung

Problemanalyse

Ein physikalisches System (Host) kann mehrere virtuelle Systeme (Guests) beherbergen. Jedem virtuellen System werden Ressourcen des physikalischen Systems zugeordnet. Da die Ressourcen des Hosts begrenzt sind, sind natürlich auch die Ressourcen für die Guests begrenzt.

Ressourcenschonende Verteilung mehrere virtueller Maschienen in einem Serververbund

In Anlehnung an den Begriff Green IT wurde die Idee für eine "grüne" Managementlösung entwickelt. Ziel soll es sein, die Ressourcen der virtuellen Systeme so zu verwalten, dass die Ressourcen der physischen Systeme optimal ausgenutzt werden. Sprich ein virtuelles System bekommt nur soviel Ressourcen zugeordnet, wie es benötigt, um effizient zu arbeiten. Dabei wird festgelegt, dass ein effizient arbeitendes System 70-90 % seiner Ressourcen ausnutzt. Daraus folgt, dass bei einer zu geringen Ausnutzung zuviel bzw. bei einer zu hohen Auslastung zuwenig Ressourcen zugeordnet sind. Als Managementmaßnahme müssen also Ressourcen entfernt bzw. hinzugefügt werden. Sind die physischen Ressourcen eines Servers erschöpft, können einzelne virtuelle Maschinen auf freie Server migriert werden. Da nicht nur die Ressourcen eines einzelnen physischen Servers effizient genutzt werden sollen, sondern die des ganzen Serververbundes, werden nur soviele Server betrieben, wie nötig sind um alle virtuellen Maschinen effizient zu betreiben. (Siehe Grafik)

Konzept

Um die Effizienz der Ressourcenauslastung der virtuellen und physischen Server zu gewährleisten, ist ein Programm zu entwickeln, das ständig die Informationen über die Systeme ausliest, analysiert und gegebenenfalls Managementmaßnahmen auslöst.

Managementkreislauf

Die Anwendung realisiert einen Managementkreislauf bestehend aus den drei Phasen Beobachtung, Analyse und Steuerung.

Managementkreislauf

  1. In der Beobachtungsphase werden die Informationen über die physischen und virtuellen Systeme mittels SNMP ausgelesen und an Esper übergeben.
  2. In der Analysephase werden die verschiedenen Informationsströme durch Esper ausgewertet.
  3. In der Steuerungsphase werden die Ressourcen mittels libvirt angepasst.

Systemkomponenten

Systemkomponenten

Die drei Phasen des Managementkreislaufs finden sich auch in den verwendeten Komponenten wieder. Zunächet werden die Ressourcenauslastungen der virtuellen und physischen Systeme, mittels SNMP erfasst. Dies setzt voraus, dass sowohl auf den physischen Servern als auch auf den virtuellen Maschinen ein SNMP-Deamon läuft, der Informationen über Ressourcen und deren Auslastung ausliefern. Durch einen SNMP-Agenten in der Managementsoftware wird die Auslastung der einzelnen Systeme, in regelmäßigen Abständen erfragt. Auf Grundlage dieser Informationen wird nun für jedes System ein Datenstrom erzeugt, der von der Esper-Engine verarbeitet wird.

Die gesammelten Informationen, die als Datenströme bei der Esper-Engine ankommen, werden mittels vordefinierter Abfragen analysiert. Ergibt sich aus dieser Analyse ein Handlungsbedarf für die Verteilung der Ressourcen, wird dies über die libvirt realisiert.

Verwendung der libvirt-Bibliothek

Um das Steuern der Server bzw. der zugehörigen virtuellen Maschinen zu ermöglichen, ist es notwendig auf jedem Server einen libvirt-Deamon zu betreiben. Dieser erlaubt das Zuteilen und Entziehen virtueller Ressourcen bzw. das migrieren von virtuellen Maschinen zwischen physischen Servern. Gesteuert werden diese Vorgänge durch den Manager unter Verwendung der libvirt-Bibliothek, die eine Verbindung zu den verschieden Serveren bzw. deren libvirt-Deamons aufbaut.

Realisierung

Das entwickelte Programm, welches den Managementkreislauf abbildet heißt schlicht "Manager". Entwickelt wurde durchgehend in Java, da Java-Bibliotheken für Esper bzw. libvirt verfügbar sind und Java es ermöglicht eine Software zu entwickeln die auf verschiedensten Plattformen läuft.

Managementkreislauf

Im Folgenden werden nun die einzelnen Java-Klassen besprochen die notwendig sind um den Managementkreislauf abzuwickeln. Beispielhaft wird dafür der Arbeitsspeicher als betrachtete Ressource herangezogen.

Managementkreislauf

Ausgangspunk ist die Klasse DomainContol, für die pro virtueller Maschine eine Instanz erzeugt wird. Sie hält eine Instanz der Klasse DomainWatchdog. Dieser ist ein Java-Thread der in festen, definierten Abständen die virtuelle Maschine nach der Auslastung des zugeteilten Arbeitsspeichers fragt. Dies geschieht über den SNMPConnector, der die SNMP-Technologie von der DomainControl kapselt. Auf diese Weise genügt die Angabe eines SNMP-Pfad um einen entsprechenden Wert zu lesen. Der folgende Quelltextauszug zeigt das Auslesen des zugeteilten Arbeitsspeicher einer virtuellen Maschine unter Verwendung des SNMPConnector.

// Beispiel: Auslesen des vorhandenen Arbeitsspeichers für eine virtuelle Maschine
public class DomainConrol{
 ...
 public long getMemory() throws SNMPNoAnswerException {
  try {
   return Long.valueOf(this.snmpConnector.getValue(".1.3.6.1.4.1.2021.4.5.0"));
  } catch (NumberFormatException e) {
   e.printStackTrace();
  } catch (IOException e) {
   e.printStackTrace();
  }
  return -1;
 }
 ...
}

Hat der DomainWatchdog die benötigten Informationen gelesen, erzeugt er ein DomainStatusEvent, welches sämtliche Informationen zur betrachteten virtuellen Maschine enthält. Da wir in unserem Beispiel die Auslastung des Arbeitsspeichers betrachten, genügt es die Größe des zugeteilten Arbeitsspeichers und dessen Auslastung zu ermitteln. Um das erzeugte DomainStatusEvent später wieder der virtuellen Maschine zuordnen zu können, wird die entsprechende DomainControl Instanz im DomainStatusEvent übergeben. Der folgende Quelltextauszug zeigt das DomainStatusEvent.

public class DomainStatusEvent {
 private DomainControl domain;
 private long memory;
 private long usedMemory;
	
 public DomainStatusEvent(DomainControl domain, long memory, long usedMemory) {
  this.domain = domain;
  this.memory = memory;
  this.usedMemory = usedMemory;
 }

 public DomainControl getDomain() {return domain;}
 public long getMemory() {return memory;}
 public long getUsedMemory() {return usedMemory;}
}

Das erzeugte DomainStatusEvent übergibt der DomainWatchDog an die EsperEngine, in der die Analyse der eingehenden DomainStatusEvents geschieht. Für die Analyse werden werden mittels EPL Abfragen definiert, die aus den Datenströmen Daten extrahieren und an definierte Listener übergeben. Der folgende Codeausschnitt aus der EsperEngine zeigt welche Abfragen in unserer Beispielimplementierung zum Einsatz kommen und wie sie hinzugefügt werden.

public class EsperEngine {
	EPServiceProvider epService;
        ...
	private void addStatements() {
		...
                addStatement(
				"select domain, usedMemory, memory from esper.DomainStatusEvent where ((usedMemory / memory )* 100) < 20",
				new ExcessMemoryListener());

		addStatement(
				"select domain, usedMemory, memory from esper.DomainStatusEvent where ((usedMemory / memory )* 100) > 50",
				new DeficitMemoryListener());
	}

	public void addStatement(String exp, UpdateListener listener) {
		EPStatement statement = epService.getEPAdministrator().createEPL(exp);
		statement.addListener(listener);
	}
        ...
}

Beide Abfragen verarbeiten die eingehenden DomainStatusEvents und werden immer dann, wenn ein neues Event eintrifft ausgewertet. Wenn die Auslastung des Arbeitsspeichers kleiner as 20 % bzw. größer als 50 % ist, wird die Domain, der zugeteilte Arbeitsspeicher und der genutzte Arbeitsspeicher aus dem Event extrahiert und an den ExcessMemoryListener bzw. den DeficitMemoryListener übergeben. Der entsprechende Listener manipuliert dann auf Basis der extrahierten Daten die virtuelle Maschine. Wie die Manipulation erfolgt, zeigt der folgende Codeausschnitt aus dem ExcessMemoryListener.

public class ExcessMemoryListener implements UpdateListener {
	@Override
	public void update(EventBean[] newEvents, EventBean[] oldEvents) {
		EventBean event = newEvents[0];
		DomainControl domain = (DomainControl) event.get("domain");
		double factor =  0.75;
		
		long memory = (Long) event.get("memory");
		long usedMemory = (Long) event.get("usedMemory");
		long memoryToSet = (long) (memory * factor);

		try {
			System.out.println("ExcessMemoryListener\nDomain: " + domain.getName() + " Memory: " + memory + " Used Memory: " + usedMemory + "\n --> Trying to set it to " + memoryToSet);
			domain.setMemoryLower((long) (memoryToSet));
		} catch (LibvirtException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			System.out.println(e.getMessage());          
		}
	}

}

Der ExcessMemoryListener implementiert das von Esper definierte Interface UpdateListener. Die durch die Abfrage extrahierten Daten liegen im ersten neuen Event. Auf Basis dieser Daten berechnet der ExcessMemoryListener die neue Größe des Arbeitsspeichers und ruft auf der entsprechenden Instanz der DomainControl die Methode zum Setzen des Arbeitsspeichers auf. Damit ist der Managementkreislauf einmal durchlaufen worden. Die Auslastung des Arbeitsspeichers wurde beobachtet, analysiert und die entsprechende Ressource angepasst.

Klassendiagramm

Die gesamte Struktur der Managementsoftware ist dem Klassendiagramm zu entnehmen.

Klassendiagramm

Systemvorraussetzungen

Kernel-based Virtual Machine (KVM)

Hardwarevoraussetzung und Module

Alle Installationen werden auf Basis von Ubuntu 11.10 durchgeführt. Für den Einsatz von KVM wird eine Hardwarevirtualisierung durch den Prozessor vorausgesetzt. In den aktuellen Prozessoren von AMD und Intel ist eine solche Technologie verbaut, und unter dem Namen AMD virtualization (AMD-V) bzw.Intel virtualization (VT-x) bekannt. Ob der verbaute Prozessor Hardwarevirtualisierung unterstützt, lässt unter Linux unter /proc/cpuinfo erfragen. Ist der Prozessor mit den Flags vmx oder svm gekennzeichnet, bietet er Hardwarevirtualisierung. Der folgende Befehl zeigt die Anzahl der verbauten Kerne, die Hardwarevirtualisierung unterstützen.

grep -E '^flags.*\b(vmx|svm)\b' /proc/cpuinfo | wc -l

Unterstützt der Prozessor Hardwarevirtualisierung, so müssen zwei Kernel-Module geladen sein. Die benötigten Module lauten kvm und kvm_intel für Intel-Prozessoren bzw. kvm und kvm_amd für AMD-Prozessoren. Ob diese geladen sind lässt sich mit folgendem Befehl überprüfen:

lsmod | grep kvm

Sollten die Module nicht geladen sein, kann man sie mit den folgenden Befehlen laden:

## für Intel-Prozessoren
sudo modprobe kvm
sudo modprobe kvm_intel

## für AMD-Prozessoren
sudo modprobe kvm
sudo modprobe kvm_amd

Sollen die Module beim Systemstart geladen werden, sind sie der Datei /etc/modules hizuzufügen.

qemu

KVM an sich stellt nur die direkte Schnittstelle zum Linux-Kernel zur Verfügung, als Virtualisierungsumgebung kommt QEMU zum Einsatz. Für dessen Nutzung das Paket qemu-kvm zu installiern ist.

sudo aptitude install qemu-kvm cgroup-bin

libvirt

Für die Verwendung der libvirt ist schließlich das Paket libvirt0 zu installieren.

sudo aptitude install libvirt0

optionale Programme

Für das Administrieren von virtuellen Maschinen und deren Gastsysteme gibt es eine Reihe nützlichen Programme, die auf die libvirt zurückgreifen und wie folgt zu installieren sind.

sudo aptitude install virt-manager  virt-viewer virtinst libvirt-bin

Installation einer virtuellen Maschine

sudo mkdir /data /data/vms /data/isos

Das ISO-Image zur Installation ist unter der folgenden Adresse zu beziehen:

Debian Netinst-CD-Image

Anschließende kann mit dem folgenden Befehl eine virtuelle Maschine erstellt und gestartet werden. Voraussetzung ist, dass das iISO-Imaga unter /data/isos/debian-6.0.3-i386-netinst.iso liegt und der Benutzer unter /data/vms/debian.img eine fünf Gigabyte große Datei für die virtuelle Maschine anlegen darf.

virt-install --connect qemu:///system --virt-type=kvm --name=debian --ram=512 --cdrom=/data/isos/debian-6.0.3-i386-netinst.iso --os-type=linux --os-variant=debiansqueeze --file=/data/vms/debian.img --file-size=5 --vcpus=4 --network network=mynet

Das ISO-Image wird als CDROM eingebunden und die virtuelle Maschine startet den den Installationsprozess, der nun wie auf einer physischen Maschine verläuft. Bei der sind folgende Konfiguration zu wählen.

  • Hostname: debian
  • Rootpasswort: debian
  • Benutzername: debian
  • Benutzerpasswort: debian


Bei der Softwareauswahl sind die Grafische Desktop-Umgebung und die Standard-Systemwerkzeuge abzuwählen und der SSH-Server hinzu zu fügen.

Netzwerkkonfiguration

Im Rahmen des Projektes wird der Status der virtuellen Maschinen über SNMP erfragt. Um dies zu ermöglicheh müssen die einzelnen virtuellen Maschinen über eine feste IP-Adresse bzw einen festen DNS-Namen ansprechbar sein. Ermöglicht wird dies durch eine spezielle Netzwerkkonfiguration. Zunächst wird ein die Konfiguartion des Netzwerks erstellt und in der Datei mynet.xml gespeicher. Das Netzwerk trägt den Namen mynet, verwender die virtuelle Netzwerkbrücke virbr1, hat die einen Default-Gateway auf 192.168.123.1 der alle Pakete weiterreicht(forward). Ein interner DHCP-Server ist ebenfalls in der Konfiguration enthalten und verteilt IP-Adressen im in einem Range von 192.168.123.2 bis 192.168.123.254.

 <network>
  <name>mynet</name>
  <bridge name="virbr1" />
  <forward/>
  <ip address="192.168.123.1" netmask="255.255.255.0">
   <dhcp>
    <range start="192.168.123.2" end="192.168.123.254" />
   </dhcp>
  </ip>
 </network>

Die folgenden Befehle erstellen das virtuellen Netzwerk, starten es und sorgen dafür das es beim booten des Hosts gestartet wird.

virsh net-define mynet.xml; virsh net-start mynet; virsh net-autostart mynet
IP Aliases

Ist eine virtuelle Maschine erstellt, kann ihr mit Hilfe eines IP Alias eine feste IP-Adresse zugeordenet werden. Dafür muss zunächst die MAC-Adresse der virtuellen Maschine ermittelt werden. Dies wie folgt geschehen.

virsh dumpxml name-der-virtuellen-maschine|grep 'mac address'

Für die virtuelle Maschine mit den Namen debian lautet der Befehl wie folgt.

virsh dumpxml debian|grep 'mac address'

Mit der MAC-Adresse kann nun der interne DHCP-Server dazu veranlasst werden der Domain immer die gleiche IP-Adresse zu zuorden. Dies geschieht durch einen Eintrag in der Datei mynet.xml', der für unsere kongrete vrirtuelle Maschine debian wie folgt aussehen kann.

 <host mac="52:54:00:0b:60:3b" name="debian" ip="192.168.123.2"/>

Zu beachten ist, dass die eingetragene MAC-Adresse der zuvor ermittelten MAC-Adresse entsprcht. Die IP sollte innerhalb des DHCP-Ranges liegen. Es empfiehlt sich für den einzutragenden Namen den Namen der Domain zu verwenden. Die angepasste Verion der Datei mynet.xml würde wie folgt aussehen.

 <network>
  <name>mynet</name>
  <bridge name="virbr1" />
  <forward/>
  <ip address="192.168.123.1" netmask="255.255.255.0">
   <dhcp>
    <range start="192.168.123.2" end="192.168.123.254" />
    <host mac="52:54:00:0b:60:3b" name="debian" ip="192.168.123.2"/>
   </dhcp>
  </ip>
 </network>

Um die Konfiguration wirksam zu machen ist das bestehende Netzwerk mynet zulöschen und neu zu erstellen.

virsh net-destroy mynet; virsh net-undefine mynet
virsh net-define mynet.xml; virsh net-start mynet; virsh net-autostart mynet

Start man die nun die Domain neu ist sie unter der angegeben IP-Adresse erreichbar.

virsh shutdown debian; sleep 100; virsh start debian

Um die Domains Über ihren Namen erreichbar zu machen ist die /etc/hosts des Gastsystems mit einem entsprchendem Eintrag zu ergänzen anzupassen.

#ip domainname
192.168.123.2 debian

SNMP

Installation auf auf einer virtuellen Maschine

Installation

Um die Installation zu ermöglichen ist unter Debian Squeeze der non-free-Zweig freizuschalten. Dies gelingt indem die Datei /etc/apt/source.list wie folgt angepasst wird.

deb http://ftp.de.debian.org/debian/ squeeze main non-free
deb-src http://ftp.de.debian.org/debian/ squeeze main non-free

deb http://security.debian.org/ squeeze/updates main non-free
deb-src http://security.debian.org/ squeeze/updates main non-free

deb http://ftp.de.debian.org/debian/ squeeze-updates main non-free
deb-src http://ftp.de.debian.org/debian/ squeeze-updates main non-free

Anschließen sind die Sourcen mit folgendem Befehl neu einzulesen.

aptitude update

Nun können die Pakete snmp-mibs-downloader und snmpd installiert werden.

aptitude install snmp-mibs-downloader snmpd
Konfiguration

Per Dafault-Einstellungen ermöglicht der SNMP-Demon nur ein lokales Abfragen eines eingeschränkten SNMP-Baums. Um diese Abfragen über den gesammten SNMP-Baum aus dem Netzwerk zu ermöglichen sind folgende Zeilen in der Datei /etc/snmp/snmpd.conf hinzuzufügen.

agentAddress  udp::161
view   systemonly  included   .1

Um die Ändereungen wirksam zu machen ist den SNMP-Deamon mit folgendem Befehl neuzustarten.

/etc/init.d/snmpd restart

Anschließende sollte die virtuelle Maschine auf SNMP-Abfragen über das Netzwerk antworten.

snmpwalk -v1 -cpublic ip-der-virtuellen-maschine

Um die neu installierten MIBs zu verwenden, ist die Datei /etc/snmp/snmp.conf wie folgt anzupassen.

# As the snmp packages come without MIB files due to license reasons, loading
# of MIBs is disabled by default. If you added the MIBs you can reenable
# loaging them by commenting out the following line.
# mibs :

Esper

Um Esper 4.4.0 in einem Java Projekt zu verwenden, muss folgende Bibliothek zum Projekt hinzugefügt werden.

  • esper-4.4.0.jar

Außerdem benötigt Esper selbst einige Bibliotheken. Diese sind in der Esperdistrubution enthalten und befinden sich im Verzeichnis esper/lib.

  • antlr-runtime-3.2.jar
  • cglib-nodep-2.2.jar
  • commons-logging-1.1.1.jar
  • log4j-1.2.16.jar

Fazit

Im folgenden Abschnitt sind unsere Erfahrungen und Erkenntnisse, die aus dem Projekt folgern zusammengefasst.

Das angestrebte Ziel virtuelle Maschinen mit Hilfe von Complex Event Processing zu steuern wurde erreicht. Der dabei gewählte Ansatz wurde beispielhaft implementiert, dabei wurde als zu managende Ressource der Arbeitsspeicher gewählt.

Aus der beispielhaften Implementierung wurde erkennbar, dass SNMP als Beobachtungskomponente eine gute Wahl war, weil SNMP ausgereift, anpassbar und leicht auf zu beobachtenden Systemen einzurichten ist.

Der Ansatz libvirt als Steuerungskomponente für verschiedenste Virtualisierungslösungen zu verwenden ist prinzipiell eine sinnvolle Idee, allerdings bringt dies auch Probleme mit sich, da libvirt nicht von jeder Virtualisierungslösung gleich gut unterstützt wird. Es wäre also eventuelle ratsam sich auf eine Virtualisierungslösung zu beschränken.

Esper wird bisher nur in einer sehr rudimentären Art genutzt und bietet daher noch große Möglichkeiten. So könnte zum Beispiel die Menge der betrachteten Größen und verschiedenen Maschinen erhöht werden um so höheres Wissen abzuleiten. Zum Anderen könnte der zeitliche Verlauf der Ressourcenauslastung mit in die Auswertung der Anfragen einfließen. Daraus würden sich Wechselwirkungen zwischen den Maschinen erkennen lassen und damit bessere Managemententscheidungen getroffen werden.

Abschließend ist festzuhalten, dass der gewählte Ansatz ein interessantes Forschungsfeld öffnet.

Notizen

Repository-URLs fuer 2011maitmanagement01

Domain name --> MAC

http://rwmj.wordpress.com/2010/10/26/tip-find-the-ip-address-of-a-virtual-machine/

http://aglitke.wordpress.com/2011/06/21/what-is-the-ip-address-of-my-guest/

https://help.ubuntu.com/community/KVM/Networking#IP_Aliases

Literatur

JavaDoc für libvirt [1]

Ubunte Serverguide - libvirt [2]

CPU-Ressourcen in KVM auf Debian Squeeze steuern: Cgroups [3]

Complex Event Processing (CEP) [4]

Kontinuierliche Kontrolle [5]

Getting started with Esper in 5 minutes. [6]