Dafür zeichnen die Neutron-Agents verantwortlich. Konkret lassen sich drei Problemfelder ausmachen:
Für jedes der drei Probleme gibt es in OpenStack einen sogenannten Agent. Agents sind grundsätzlich die Gegenstücke zu Plugins: Sie laufen auf den Hosts innerhalb der Cloud und setzen dort Netzwerkbefehle so um, wie das Plugin im Neutron-Server es vorgibt. Neutron unterscheidet dabei zwischen Agents, die im Hinblick auf ein Plugin spezifisch sind – beispielsweise den Open-vSwitch-Agent – und generischen Agents, die mit allen Neutron-Plugins funktionieren. Der Plugin-spezifische Agent läuft in der Regel auf jedem Host mit Ausnahme des Cloud-Controllers, während die generischen Agents meist nur auf einigen ausgewählten Hosts arbeiten.
Im konkreten Beispiel von Open vSwitch ist das genau so: Der Neutron-Open-vSwitch-Agent läuft auf allen Hypervisor-Hosts – und zudem auf dem Netzwerkknoten, den fast alle OpenStack-Konzepte derzeit vorsehen. Er hat eine maßgebliche Aufgabe: Zwischen den einzelnen Hosts baut er GRE-Tunnel im Stil eines MESH-Netzwerkes auf. Spezifische VMs werden mit virtuellen Netzwerkkarten gestartet, die (über Umwege) in diese GRE-Tunnel durchgeleitet werden. Open vSwitch kümmert sich um die Sicherheit: Vereinfacht ausgedrückt sind jene GRE-Tunnel die virtuellen Switche und die NICs der VMs die dazugehörigen Ports.
Open vSwitch selbst ist bekanntlich im Wesentlichen ein Frontend für OpenFlow, und über OpenFlow-Tags sorgt Neutron qua Open vSwitch dafür, dass eine Trennung von Paketen auf Kundenebene stattfindet. Was über die Netzwerkkarte der VM1 vom Kunden 1 auf Host A in den GRE-Tunnel geht, ist also mit einem Tag versehen, das nur entsprechend getaggte Interfaces auf anderen Hypervisor-Hosts ebenfalls zu Gesicht bekommen ( Abbildung 2 ). Anhand des OSI-Layer-Modells wird deutlich, dass hier im Grunde ein virtueller Layer 2 in einem physischen Layer 3 gebaut wird. Die Plugin-spezifischen Agents heißen in OpenStack deshalb oft auch L2-Agents.
Zu den L2-Agents gesellt sich der DHCP-Agent zusammen mit dem L3-Agent. Wie bereits erwähnt ist es mittlerweile durchaus üblich, einen separaten Knoten für die Netzwerkdienste einer OpenStack-Cloud abzustellen; der Netzwerkknoten hat die Aufgabe, sämtliche VMs mit der Außenwelt zu verbinden und auch dafür zu sorgen, dass neu gestartete VMs eine passende IP per DHCP erhalten. Darum kümmern sich die beiden genannten Agents.
Doch wie funktioniert diese Technik genau und welche Komponenten sorgen auf dem Netzwerkknoten für die reibungslose Funktion? Soviel vorab: Ein L2-Agent läuft selbstverständlich auch auf dem Netzwerkknoten. Denn damit VMs über den Netzwerkknoten mit der Außenwelt kommunizieren können, gelten natürlich die gleichen Bedingungen wie für die Kommunikation der VMs untereinander. Über den Draht zu den Hypervisor-Systemen wandern auch die DHCP-Antworten: Für jedes Tenant-Netzwerk startet der DHCP-Agent auf dem Netzwerkknoten eine Instanz von
»dnsmasq
«
[3]
mit einer entsprechend präparierten Konfiguration. Weil User beim Starten einer VM festlegen müssen, mit welchem virtuellen Netz die VM verbunden sein soll, landet ein DHCP-Request von einer VM über den GRE-Tunnel zwischen dem Hypervisor-Host und dem Netzwerkknoten beim passenden
»dnsmasq
«
und bekommt eine entsprechende Antwort. Ganz ähnlich funktioniert auch der Ablauf bei der sogenannten Layer-3-Kommunikation, also mit der Außenwelt.
Was in der Theorie simpel klingt, hat in der Praxis allerdings einen gewaltigen Pferdefuß. Damit Kunden wirklich ihre Netzwerktopologien selbst festlegen können, anstatt auf eine zentrale Verwaltung angewiesen zu sein, ist es zwingend notwendig, dass jeder Kunde grundsätzlich jedes Netz nutzen kann. Kunde 1 muss also das Netz 192.168.0.0/24 genauso nutzen können wie Kunde 2. Solange Netzwerk-Traffic nur zwischen den Hypervisor-Hosts passiert, ist das – den OpenFlow-Tags sei Dank – auch kein größeres Problem. Auf dem Knoten, der für das Netzwerk verantwortlich zeichnet, entsteht jedoch ein großes Problem: Wenn aus zwei unterschiedlichen GRE-Tunneln Pakete aus dem genannten Netzwerk ankommen, die beide über die gleiche externe Netzwerkkarte an die Außenwelt verschickt werden sollen, muss der Netzwerkknoten die Pakete trennen können. Der Open-vSwitch-Agent in OpenStack Neutron setzt dafür auf Namespaces ( Abbildung 3 ).
Namespaces sind eine Kernel-Funktion, die in unterschiedlichen Varianten daherkommt; innerhalb eines Namespaces sind Prozesse "eingesperrt", sehen den Rest des Systems also nicht. Im Grunde sind sie eine Art
»chroot
«
– sie stehen für PIDs genauso zur Verfügung wie für Netzwerke. Ein Prozess, der in einem Network Namespace gestartet wird, sieht also nicht die Netzwerkkarten des Systems, sondern lediglich die innerhalb dieses Namespaces existierenden Devices. Diesen Umstand macht sich Neutron zunutze: Für jedes interne sowie für jedes externe Netzwerk existiert auf dem Netzwerkknoten jeweils ein spezifischer Namespace. In den Namespaces landen die Pakete, die zuvor den Netzwerkknoten über die GRE-Tunnel erreicht haben. Sie befinden sich also von Anfang an "am richtigen Ort", sodass der Netzwerkknoten Pakete zuordnen kann. Damit ein Kundennetzwerk Zugriff auf die Außenwelt hat, muss der Kunde der Cloud zudem eine Verbindung zwischen dem externen Netzwerk und dem internen DHCP-Netz schaffen, um eine Brücke zu bauen. Indem der Anbieter ein eventuell vorhandenes, externes Netz entsprechend fragmentiert und Kunden die einzelnen Fragmente zur Verfügung stellt, sorgt er also für echte Freiheit der Kunden in Sachen Netzwerktopologie.