Vor kurzem habe ich Debian 8 (Jessie) auf meiner Entwicklermaschine, einem HP ProLiant DL380G5, installiert. Als Basissystem habe ich mich dieses Mal für Debian (stable) entschieden, obwohl ich ja sonst fast ausschließlich unter Gentoo arbeite. Das System macht einen sehr guten Eindruck. Interessiert hat mich hierbei am meisten, wie die Integration von systemd unter Debian gelungen ist, nachdem ich mich damit auf einer Gentoo-Maschine schon seit etlichen Monaten beschäftigt habe.
Was mir dabei gut gefällt ist, dass die gewohnte Netzwerkkonfiguration unter /etc/network/interfaces noch immer so genutzt wird. Auf diese Weise konnte ich recht schnell eine Bridge konfigurieren, in der eine meiner externen Schnittstellen mit integriert ist (ich liebe diese Art, weil dann jede VM direkten Zugang zum Netzwerk hat).
Das funktionierte sehr gut. Nach einiger Zeit war klar, dass ich gerne eine Gentoo-Clusterlösung als Testsystem auf dem Server betreiben wollte (wir haben ein Produktivsystem und dieses neue Testsystem soll einfach unser Staging für Updates sicherer machen).
Jetzt ist es so, dass dieser Cluster Bonding und etliche VLANs konfiguriert hat und nun war klar, dass der Weg mit einer Bridge nicht unbedingt optimal dafür ist. Also habe ich mich entschieden, Open-vSwitch auf der Entwicklermaschine aufzubauen. Mit Erfolg.
Im Wesentlichen zeige ich einmal die Konfiguration der Debian-interfaces-Datei und ein Beispiel einer XML-Konfiguration zu einem der beiden Clusterknoten. Zum Schluss, wie das Ganze dann unter Gentoo auf dem ersten Knoten genutzt wird.
Mein Fokus liegt klar auf den VLANs. Zu Bonding bin ich noch nicht weiter tiefer eingestiegen. Wer dazu Ideen und Anregungen hat, gerne in den Kommentaren erwähnen 🙂
Debian interfaces
allow-ovs ovsbr0
iface ovsbr0 inet static
address 172.16.2.244
netmask 255.255.255.0
network 172.16.2.0
broadcast 172.16.2.255
gateway 172.16.2.1
ovs_type OVSBridge
ovs_ports eth0 eth1 vlan108
# HP Switch (Simulation)
post-up /bin/ip addr add 192.168.2.254/24 brd + dev ${IFACE}
pre-down /bin/ip addr del 192.168.2.254/24 brd + dev ${IFACE}
allow-ovsbr0 eth0
iface eth0 inet manual
ovs_bridge ovsbr0
ovs_type OVSPort
allow-ovsbr0 eth1
iface eth1 inet manual
ovs_bridge ovsbr0
ovs_type OVSPort
ovs_options tag=109
allow-ovs ovsbr1
iface ovsbr1 inet manual
ovs_type OVSBridge
post-up /bin/ip link set dev ${IFACE} up
pre-down /bin/ip link set dev ${IFACE} down
#
# VLANs
#
# iQom testing
allow-ovsbr0 vlan108
iface vlan108 inet static
address 217.199.204.9
netmask 255.255.255.248
network 217.199.204.8
broadcast 217.199.204.15
ovs_bridge ovsbr0
ovs_type OVSIntPort
ovs_options tag=108
ovs_extra set interface ${IFACE} external-ids:iface-id=$(hostname -s)
Das Beispiel definiert einen Switch namens ovsbr0. In diesem Switch hängen beide externen Schnittstellen des Servers so wie einVLAN-Device. Der Switch hat selbst eine IP und zusätzlich habe ich noch ein weiteres Netz hinzugefügt, was für den Testcluster selbst eine Relevanz hat.
Die beiden physischen Schnittstellen sind nicht im selben VLAN! eth1 habe ich bewusst in VLAN 109 untagged gepackt. Ich nutze das, um mein Laptop daran anzuschließen und bestimmte Kommunikation mit dem Cluster zu testen.
Weiterhin gibt es ein virtuelles VLAN mit der ID 108. Das nutze ich, um aus Sicht des Test-Clusters eine ansprechbare IP „extern“ zu haben. Heißt so viel wie: Ich kann vom Cluster aus eine IP auf dem VLAN 108 pingen und somit ebenfalls eine bestimmte Kommunikation simulieren.
libvirt XML Konfiguration einer der Knoten
Das sieht auf den ersten Moment schlimm aus. Zerlegen wir das mal:
Der Server hat vier Netzwerkkarten. Jeweils zwei davon bilden ein Bond-Gerät. Das eine Device wird für die interne Clusterkommunikation (corosync, pacemaker, DRBD, …) benutzt, das andere für eine Anbindung an den Switch mit all seinen VLANs. Jetzt kommt vielleicht schnell die Frage auf, wo denn „all die VLANs“ oben definiert wurden? Nirgends. Das geschieht zur Laufzeit des Gastes. Freundlicherweise fügt libvirt alles Notwendige direkt in open-vSwitch hinzu und wir brauchen uns um nichts weiter zu kümmern.
Alle hier gezeigten VLANs sind tagged Ports. D.h. dass der Cluster selbst 802.1Q sprechen muss, was gleich gezeigt wird.
Zuerst zeige ich mal kurz die Switchkonfiguration vor dem Start der MS und dann danach
Vor dem Start
root@dev ~ # ovs-vsctl show
e114dfa1-5ac3-4d92-9590-f92965b16a4e
Bridge "ovsbr1"
Port "ovsbr1"
Interface "ovsbr1"
type: internal
Bridge "ovsbr0"
Port "eth0"
Interface "eth0"
Port "eth1"
tag: 109
Interface "eth1"
Port "vlan108"
tag: 108
Interface "vlan108"
type: internal
Port "ovsbr0"
Interface "ovsbr0"
type: internal
ovs_version: "2.3.0"
Nach dem Start
root@dev ~ # ovs-vsctl show
e114dfa1-5ac3-4d92-9590-f92965b16a4e
Bridge "ovsbr1"
Port "vnet3"
Interface "vnet3"
Port "ovsbr1"
Interface "ovsbr1"
type: internal
Port "vnet2"
Interface "vnet2"
Port "vnet7"
Interface "vnet7"
Port "vnet6"
Interface "vnet6"
Bridge "ovsbr0"
Port "vnet0"
trunks: [0, 100, 102, 104, 105, 106, 107, 108, 109, 200]
Interface "vnet0"
Port "vnet4"
trunks: [0, 100, 102, 104, 105, 106, 107, 108, 109, 200]
Interface "vnet4"
Port "vnet1"
trunks: [0, 100, 102, 104, 105, 106, 107, 108, 109, 200]
Interface "vnet1"
Port "eth0"
Interface "eth0"
Port "eth1"
tag: 109
Interface "eth1"
Port "vlan108"
tag: 108
Interface "vlan108"
type: internal
Port "ovsbr0"
Interface "ovsbr0"
type: internal
Port "vnet5"
trunks: [0, 100, 102, 104, 105, 106, 107, 108, 109, 200]
Interface "vnet5"
ovs_version: "2.3.0"
Viel lässt sich dazu jetzt nicht sagen, denn das ist Cluster-spezifisch. Ich zeige nur kurz, was die Ausgabe von IP so zeigt (der Cluster ist im Beispiel auf beiden Knoten im Standby)
root@node0 /etc/conf.d # ip -4 a l
1: lo: mtu 65536 qdisc noqueue state UNKNOWN group default
inet 127.0.0.1/8 brd 127.255.255.255 scope host lo
valid_lft forever preferred_lft forever
7: bond0: mtu 1500 qdisc noqueue state UP group default
inet 192.168.0.1/24 brd 192.168.0.255 scope global bond0
valid_lft forever preferred_lft forever
8: bond1: mtu 1500 qdisc noqueue state UP group default
inet 172.16.2.230/24 brd 172.16.2.255 scope global bond1
valid_lft forever preferred_lft forever
inet 192.168.2.203/24 brd 192.168.2.255 scope global bond1
valid_lft forever preferred_lft forever
16: bond1.109@bond1: mtu 1500 qdisc noqueue state UP group default
inet 10.1.100.1/16 brd 10.1.255.255 scope global bond1.109
valid_lft forever preferred_lft forever
Die Linkliste
root@node0 /etc/conf.d # ip l l
1: lo: mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: sit0@NONE: mtu 1480 qdisc noop state DOWN mode DEFAULT group default
link/sit 0.0.0.0 brd 0.0.0.0
3: eth0: mtu 1500 qdisc pfifo_fast master bond1 state UP mode DEFAULT group default qlen 1000
link/ether 54:52:00:40:e6:04 brd ff:ff:ff:ff:ff:ff
4: eth1: mtu 1500 qdisc pfifo_fast master bond1 state UP mode DEFAULT group default qlen 1000
link/ether 54:52:00:40:e6:04 brd ff:ff:ff:ff:ff:ff
5: eth2: mtu 1500 qdisc pfifo_fast master bond0 state UP mode DEFAULT group default qlen 1000
link/ether 54:52:00:47:08:bf brd ff:ff:ff:ff:ff:ff
6: eth3: mtu 1500 qdisc pfifo_fast master bond0 state UP mode DEFAULT group default qlen 1000
link/ether 54:52:00:47:08:bf brd ff:ff:ff:ff:ff:ff
7: bond0: mtu 1500 qdisc noqueue state UP mode DEFAULT group default
link/ether 54:52:00:47:08:bf brd ff:ff:ff:ff:ff:ff
8: bond1: mtu 1500 qdisc noqueue state UP mode DEFAULT group default
link/ether 54:52:00:40:e6:04 brd ff:ff:ff:ff:ff:ff
9: bond1.100@bond1: mtu 1500 qdisc noqueue state UP mode DEFAULT group default
link/ether 54:52:00:40:e6:04 brd ff:ff:ff:ff:ff:ff
10: bond1.102@bond1: mtu 1500 qdisc noqueue state UP mode DEFAULT group default
link/ether 54:52:00:40:e6:04 brd ff:ff:ff:ff:ff:ff
11: bond1.104@bond1: mtu 1500 qdisc noqueue state UP mode DEFAULT group default
link/ether 54:52:00:40:e6:04 brd ff:ff:ff:ff:ff:ff
12: bond1.105@bond1: mtu 1500 qdisc noqueue state UP mode DEFAULT group default
link/ether 54:52:00:40:e6:04 brd ff:ff:ff:ff:ff:ff
13: bond1.106@bond1: mtu 1500 qdisc noqueue state UP mode DEFAULT group default
link/ether 54:52:00:40:e6:04 brd ff:ff:ff:ff:ff:ff
14: bond1.107@bond1: mtu 1500 qdisc noqueue state UP mode DEFAULT group default
link/ether 54:52:00:40:e6:04 brd ff:ff:ff:ff:ff:ff
15: bond1.108@bond1: mtu 1500 qdisc hfsc state UP mode DEFAULT group default
link/ether 54:52:00:40:e6:04 brd ff:ff:ff:ff:ff:ff
16: bond1.109@bond1: mtu 1500 qdisc noqueue state UP mode DEFAULT group default
link/ether 54:52:00:40:e6:04 brd ff:ff:ff:ff:ff:ff
17: bond1.200@bond1: mtu 1500 qdisc noqueue state UP mode DEFAULT group default
link/ether 54:52:00:40:e6:04 brd ff:ff:ff:ff:ff:ff
18: ifb0: mtu 1500 qdisc hfsc state UNKNOWN mode DEFAULT group default qlen 32
link/ether 4e:52:af:b2:b3:e3 brd ff:ff:ff:ff:ff:ff
Fazit
Mit Hilfe von Open-vSwitch kann ich sehr realistische Setups virtuell nachbauen, was Kosten und Ressourcen an Hardware spart.
Eine kleine Anmerkung habe ich noch:
Sowohl unter Debian (zum Zeitpunkt dieses Artikels) als auch unter Gentoo (mit systemd!) kann es vorkommen, dass der Switch während des Bodens noch nicht hundert prozentig verfügbar ist. Das ist noch ein bisschen nervig, aber unproblematisch. Ich habe einfach alle VMs auf der Testmaschine aus dem Autostart genommen. Bei Gentoo klappt das, aber gelegentlich kommt das ovsbr0 selbst nicht hoch. Dann sind zwar alle Gäste voll funktional vorhanden und erreichbar, aber die Kommunikation zwischen der physischen Maschine und den Gästen klappt nicht. Ich nutze hier netctl, um mein Netzwerk zu konfigurieren und ein
netctl start ovsbr0
nach einem Neustart behebt dann umgehend das Problem. Wer eine Firewall wie Shorewall auf einer physischen Maschine nutzt, kann hier auch einen Trick anwenden, damit der Server dann nicht unerreichbar ist, wenn das ovsbr0 nicht gleich hoch kam:
wan ovsbr0 tcpflags,nosmurfs,routeback,optional
Das Schlüsselwort „optional“ erlaubt das Nichtvorhandensein einer Netzwerkschnittstelle zur Startzeit von Shorewall.