lecture: Container basierte MultiSeat-Systeme

pamlxc

Event_large

Moderne Computersysteme sind in der Regel leistungsfähiger, als dass ein einzelner Benutzer diese beim Arbeiten permanent auslasten könnte.
Dennoch ist es gängig jedem Benutzer an seinem Arbeitsplatz einen eigenen Rechner zur Verfügung zu stellen.
Dies bringt einige Vorteile aber auch viele Nachteile mit sich.
Um diese Herauszustellen und einen geeigneten Ansatz zu finden, um eine effizientere Ausnutzung vorhandener Ressourcen zu erreichen wird das Konzept von MultiSeat-Systemen untersucht und mittels Container-Virtualisierung optimiert.
Es folgt eine Demonstration einer entsprechenden Konfiguration.

Titel: Container basierte MultiSeat-Systeme.
Autor: Axel Schöner

Einleitung:

Moderne Computersysteme sind in der Regel leistungsfähiger, als dass ein
einzelner Benutzer diese beim Arbeiten permanent auslasten könnte. Dennoch ist
es gängig jedem Benutzer an seinem Arbeitsplatz einen eigenen Rechner zur
Verfügung zu stellen. Dies bringt einige Vorteile aber auch viele Nachteile mit
sich. Um diese Herauszustellen und einen geeigneten Ansatz zu finden, um eine
effizientere Ausnutzung vorhandener Ressourcen zu erreichen wird das Konzept von
MultiSeat-Systemen untersucht und mittels Container-Virtualisierung optimiert.

Grundlagen:

Linux Containers:
Bei Linux Containers handelt es sich um eine leichtgewichtige
Virtualisierungslösung, die vielmehr eine Isolation vorhandener Ressourcen und
Prozessen darstellt. Als Grundlage hierzu dient der Einsatz von
Kernel-Namespaces, Cgroups und Capabilities, womit ein einzelner Kernel die
Limitierung und Isolation der Ressourcen sicherstellen kann. Die dazu
notwendigen Voraussetzungen sind seit einiger Zeit im Kernel integriert, zum
Betrieb wird lediglich das im userspace laufende Paket LXC benötigt.
So entfällt die Emulation kompletter oder teilweiser Hardware wie bei QEMU(E),
VMware(E), VirtualBox(E), KVM(V), XEN(VP) oder anderen Emulatoren(E),
Vollvirtualisierern(V), Paravirtualierern(P). Dies minimiert den sonst üblichen
Performance Overhead beim Einsatz von Virtualisierungslösungen.

Kernel Namespaces:
Mit dem Kernelrelease 2.6.19 begann die Integration von Namensräumen im Kernel.
Diese Namensräume dienen dazu, Prozesse von anderen in Hinblick auf bestimmte
Eigenschaften zu isolieren. Jeder dieser Namensräume isoliert Prozesse innerhalb
dieses Namensraums gegenüber Prozessen die sich außerhalb von diesem befinden.

Network namespaces:
Namensräume für das Netzwerk ermöglichen die gezielte Bereitstellung von
Netzwerkressourcen für einzelne Prozesse. Diese Ressourcen ( Netzwerkgeräte,
IP-Konfiguration, Sockets ... ) sind nur für die ausgewählten Prozesse
zugreifbar und sichtbar. Dies ermöglicht das Virtualisieren von
Netzwerkressourcen und isoliert diese gegenüber anderer Prozesse. Weiterhin
lassen sich Parameter wie Datendurchsatz dieser Namensräume gezielt über cgroups
limitieren. Um Container zwischen physischen Systemen migrieren zu können,
lassen sich diese Namensräume über das Netzwerk verschieben
(Quelle: http://lxc.sourceforge.net/index.php/about/kernel-namespaces/network/).

PID namespaces:
Durch Verwendung eines eigenen PID(Process ID) Namensraums, besitzen die
Prozesse innerhalb eines Namensraums eigene PID's. Diese sind unabhängig von den
realen PID's des physischen Hosts. Prozesse dieses Namensraums können nur die
zum Namensraum zugehörigen Prozesse sehen und verwenden. Dies ermöglicht es,
innerhalb verschiedener Namensräume die gleichen PID's zu verwenden, ohne mit
denen der anderen Namensräume zu kollidieren. Dies ist zum Beispiel wichtig, da
der init-Prozess innerhalb eines Systems per Definition die PID 1 verwendet.
Grund für die Entwicklung dieses Namensraums, welche vom OpenVZ Team mit Hilfe
von IBM vorangetrieben wurde, war es die Migration von Containern zwischen
unterschiedlichen physischen Hosts zu ermöglichen. Dies setzt jedoch voraus,
dass alle bestehenden PID's kollisionsfrei auf dem Zielrechner weiterverwendet
werden können (Quelle: http://lwn.net/Articles/259217/).

UTS namespaces:
Innerhalb eines eigenen UTS Namensraums können Hostname, Domainname... speziell
für diesen Namensraums gesetzt werden. Diese Eigenschaften gelten nur innerhalb
dieses bestimmten Namensraums und sind nach außen hin nicht relevant. Dies ist
wichtig um innerhalb einer virtuellen Umgebung wie Linux-VServer/openVZ oder
eines Containers eigene Hosteigenschaften zu betreiben
(Quelle: http://lwn.net/Articles/179345/).
''Der Patch wurde von Kirill Korotaev am 24. März 2006 initiiert und von James
Morris und Eric Biederman kommentiert und umgesetzt``.

User namespaces:
Mit Hilfe eines eigenen User Namensraums besteht die Möglichkeit für den
betreffenden Namensraum eine eigene Benutzerverwaltung unabhängig der des
physischen Hosts zu betreiben. Die Repräsentation der UIDs (Userids) ist davon
vollkommen unabhängig gegenüber anderer Namensräume. Dies ermöglicht die
gleichen UIDs innerhalb unterschiedlicher Namensräume ohne Kollision zu
verwenden. Dieser Namensraum basiert auf einem Patch von Cedric Le Goater
welcher am 08 Juni 2007 auf der Linux Kernel Mailing List veröffentlicht wurde
(Quelle: http://lwn.net/Articles/237662/).

IPC namespaces:
IPC (Inter-process communication) ermöglicht die Kommunikation mehrerer Prozesse
untereinander. Dazu stehen mehrere Möglichkeiten zur Verfügung, für Einzelheiten
siehe: (Quelle: http://tldp.org/LDP/lpg/node8.html#SECTION00710000000000000000).
Dieser Namensraum basiert auf einem Patch von Kirill Korotaev welcher am 09 Juni
2006 auf der Linux Kernel Mailing List veröffentlicht wurde:
(Quelle:http://lwn.net/Articles/187274/).

Cgroups:
Cgroups (Control Groups) bieten die Möglichkeit Prozesse in einer hierarchischen
Struktur zusammenzufassen, für die spezifische Eigenschaften, basierend auf
subsystems definiert werden können. Die Zugehörigkeit zu cgroups gelten
ebenfalls für deren Kindprozesse. Die Zugehörigkeit eines Prozesses wird über
die tasklist, innerhalb des entsprechenden Verzeichnisses zur cgroup festgelegt.
Prozesse können in eine andere cgroup migriert werden durch Hinzufügen der
zugehörigen PID' zur tasklist der Ziel cgroup. Subsystems sind Module, welche
bestehende Ressourcen verwalten. Diese Ressourcen lassen sich basierend auf
cgroups einschränken um deren Zugriff zu unterbinden oder um die Nutzung dieser
Ressourcen zu limitieren. Typische Ressourcen sind Prozessoren, Arbeitsspeicher,
Netzwerkressourcen oder ''Kernel Namespaces``. Die Verwendung einer
hierarchischen Struktur ermöglicht es Eigenschaften, von Subsystemen auf
mehreren Ebenen zu unterteilen. Zu jeder dieser Ebenen lassen sich die
Verwendung der möglichen Ressourcen weiter einschränken. Je nach gewünschten
Einschränkungen lassen sich Prozesse gezielt in die tasklist der betreffenden
cgroup aufnehmen, ohne zu jedem Prozess einzeln die Eigenschaften zu setzen.
Cgroups werden auf Dateisystemebene durch ein eigenes Dateisystem(cgroup)
verwaltet und abgebildet. Die bereits erwähnte Hierarchie basiert auf der
Ordnerstruktur innerhalb dieses Verzeichnisses. Das Anlegen einer neuen cgroup
wird durch das Erstellen eines Ordners innerhalb dieser Ordnerstruktur
realisiert. Beim Einbinden eines solchen Filesystems kann gezielt angegeben
werden welche subsystems in diesem zur Verfügung stehen sollen. Wird auf diese
Angabe verzichtet, werden alle verfügbaren subsystems eingebunden. Es gilt zu
beachten, dass beim Ausbinden dieses Filesystems die bestehenden Eigenschaften,
auf bereits zugewiesene Prozesse weiter gelten, nicht jedoch für neue Prozesse.
Grund dafür ist, wie bereits vorab erwähnt, dass die Verwaltung dieser cgroups
rein über dessen Filesystem realisiert werden kann. Informationen zur
Implementierung der cgroups befinden sich in der Kerneldokumentation. Quelle:
Kerneldokumentation 3.0.4 übereinstimmende ältere Version online verfügbar
unter: http://www.mjmwired.net/kernel/Documentation/cgroups/cgroups.txt.
Die Verwaltung der cgroups eines Containers, kann über dessen
Konfigurationsdatei erfolgen, über den Befehl: lxc-cgroup sowie auf manuellem
Weg über das Filesystem.

Capabilities:
Capabilities teilen die Rechte des privilegierten Benutzers (root) in bestimmte
Teilbereiche auf. Diese Capabilities können für unterschiedliche Prozesse
individuell gesetzt werden. Somit lässt sich die Gefahr von Rechtemissbräuchen
minimieren. In Bezug auf den Betrieb von Linux-Containern schafft dies die
Möglichkeit, bestimmte Rechte innerhalb eines Containers einzuräumen und
nicht gewollte Rechte zu verwehren. Weiterhin können ungewollte
Wechselwirkungen, wie zum Beispiel dem ''read only`` mounten des
root-Dateisystems beim Herunterfahren eines Containers verhindert werden.
Eine Übersicht über alle möglichen Capabilities finden sich unter:
http://kernel.org/doc/man-pages/online/pages/man7/capabilities.7.html.

PAM:
Die Abkürzung PAM steht für ``Pluggable Authentication Modules'' und ist ein
gängiges Authentifizierungsverfahren welches auf fast allen Unix basierenden
Betriebssystemen zur Verfügung steht. Entwickelt wurde es 1995 von Vipin Samar
und Charlie Lai bei Sun Microsystems. Durch Verwendung der PAM-API kann auf eine
Vielzahl von Authentifizierungsverfahren zurückgegriffen werden, ohne diese
konkret in eigenen Anwendungen zu integrieren
(Quelle: http://de.wikipedia.org/wiki/Pluggable_Authentication_Modules).
Der Funktionsumfang von PAM geht weit über die eigentliche Authentifizierung
hinaus, so bietet es die Möglichkeit Account- und Passwortrichtlinien zu
verifizieren als auch für die Benutzersitzung notwendige Vor- und Nach-
bereitungen zu tätigen. Zu diesem Zweck ist es in 4 Sektionen unterteilt:
``auth'', ``account'', ``password'' und ``session''. Für jede dieser Sektionen
existieren eine Vielzahl von Modulen, welche wahlweise einzeln oder kombiniert
mit anderen verwendet werden können. Die Kombination verschiedener Module lässt
sich durch Angabe von Richtlinien noch weiter verfeinern.

Vor- und Nachteile:

Vorteile:
- Der Ausfall eines Computers betrifft dies nur einen einzelnen Benutzer.
- Arbeitsplätze können räumlich getrennt voneinander sein.
- Individuelle Betriebssystemkonfiguration pro Benutzer.
- Uneingeschränkte Leistungsfähigkeit(Ressourcen sind nicht geteilt).
- Erhöhte Sicherheit(Prozesse und Netzwerkverbindungen können von anderen nicht
gesehen sowie manipuliert werden).

Nachteile:
- Anschaffungskosten der Hardware steigen linear.
- Erhöhter Strombedarf.
- Mehrfache Lizenskosten für installierte Software.
- Erhöhter Wartungsaufwand der installierten Software.

Konzept:

MultiSeat mit Linux Containers:
Durch den Einsatz moderner Virtualierungstechnik sowie geeigneter Hardware
lassen sich MultiSeat-Systeme erstellen, welche ebenbürdig zu seperaten
Computersystemen sind und deren Nachteile in vielen Bereichen
minimieren/beseitigen können.

Adhoc Generierung von Containern beim Login:
Möglich wird dies durch den Einsatz eines Authentifizierungsmoduls auf Basis von
PAM, welches mittels LXC (Linux Containers) adhoc für jeden neu anzumeldenden
Benutzer eine virtuelle Umgebung bereitstellt. Diese Umgebungen sind von
einander isoliert. Dies bedeutet, jeder Benutzer kann nur seine eigenen Prozesse
sehen und kommuniziert über einen seperaten Netzwerkstack. Zusätzlich lassen
sich für jeden Container Limits setzen (CPU, RAM, IO und Netzwerk), um
Auslastung durch einzelne Benutzer zu beseitigen.

Durch diesen Ansatz können beim Einsatz geeigneter Hardware mehrere
Arbeitsplätze durch einen Computer ohne gegenseitige Behinderung versorgt
werden. Dies steigert die Wirtschaftlichkeit durch Senkung der Anschaffungs- und
Stromkosten. Beim Einsatz mehrere solcher Systeme ist auch das Vorbehalten von
Ersatzhardware kein finanzielles Problem. Der Wartungsaufwand der Software kann
gesenkt werden, da die Softwareumgebung auf einem solchen Computer sämtlichen
Benutzern zur Verfügung steht. Kombiniert mit einer PXE-Infrastruktur kann sogar
die lokale Installation eines solchen Systems entfallen, wobei eine geeignete
Replikation der zu virtualisierenden Betriebssysteme auf lokale Massenspeicher
bei großer Benutzeranzahl sicher sinvoll ist. Ein weiterer Vorteil ergibt sich
aus der adhoc-Erzeugung der virtuellen Umgebungen, bei jedem Anmelden bekommt
der Benutzer eine saubere Umgebung zur Verfügung gestellt, da diese von einem
zuvor erstellten System abgeleitet wird.

Alternativ: Statische Configuration von Containern:
Alternativ zum Einsatz von pamlxc, können Container so vorkonfiguriert werden,
dass diese beim Starten des Computers automatisch starten. Innerhalb der
Konfigurationsdateien der Container können virtuelle Terminals sowie Zugriff auf
Ein- und Ausgabegeräte zugewiesen werden, um dem Benutzer entsprechende
Zugriffsmöglichkeit einzuräumen.

Anforderungen:

Hardware:
Benötigt wird ein Computer, der den Einsatz mehrere Grafikkarten(einige können
dabei mehrere Ausgänge getrennt ansteuern) erlaubt und ausreichend
Schnittstellen (zb. USB) für Peripherie bereitstellt. Neuere Prozessoren bringen
in vielen Fällen bereits eine Grafikeinheit mit, zusätzlich besteht die
Möglichkeit externe USB-Grafikkarten einzusetzen. Um die Anzahl der
USB-Schnittstellen zu erhöhen, sowie den Konfigurationsaufwand zu verringern
bietet es sich an USB-Hubs einzusetzen. Sollen die Arbeitsplätze räumlich
getrennt voneinander betrieben werden, kann auf USB-LAN-USB Umsetzer
zurückgegriffen werden. Die Leistungsfähigkeit der sonstigen Komponenten wie
Prozessor, Größe des Arbeits- und Festplattenspeicher sind je nach
Anwendungszweck auszuwählen.

Betriebssystem:
Es wird ein Linuxsystem mit einem Kernel ab 3.8 benötigt, damit das Setup ohne
Patches funktioniert. Der Einsatz eines Snapshot-fähigem Filesystems wird
empfohlen, um den Platzbedarf zu senken und die Reaktionsgeschwindigkeit bei der
Bereitstellung zu minimieren.

Beispiel Konfiguration:
- Installation von Ubuntu 13.04 auf einem Rechnersystem.
- Installation von LXC und pamlxc.
- Eigene Partition mittels BTRFS für das virtuelle Betriebssystem erstellen.
- Mittels lxc-create gewünschtes Betriebssystem installieren.
- Nachinstallieren weiterer Software.
- Konfigurationsdatei: /etc/security/pamlxc.conf anpassen.
- Konfiguration des XServers sowie des DisplayManagers(zb. XDM).
- Benutzer im Hauptsystem erstellen.

Windows basierte Software:
Um Anwendungen zu betreiben welche nur unter Windows lauffähig sind, kann auf
Wine oder Virtualierungssoftware wie VirtualBox, QEMU, VmWare oder ähnliches
zurückgegriffen werden.

Entwicklungsstand und Ziele:

Aktueller Entwicklungsstand:
Die Funktion des PAM-Moduls gewährleistet bisher Anmeldung auf Terminal-Ebene
als auch über den DisplayManager XDM. GDM funktionierte zum Zeitpunkt der
Erstentwicklung(Oktober 2011), bereitet aktuell jedoch Probleme.

Ziele für die Zukunft:
Geplant ist die Unterstützung eines moderneren DisplayManagers, zum Beispiel:
GDM, KDM oder LightDM. Unterstützung von Anmeldungen per SSH, dadurch könnten
adhoc virtuelle Server erstellt werden, welche entweder bis zur Abmeldung oder
darüber hinaus bestehen.