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"
Wie gewünscht 🙂
Gentoo Netzwerk-Konfiguration unter openrc
dns_domain_lo="testing.example.com" dns_servers="127.0.0.1" dns_options="edns0" rc_net_eth0_provide="!net" rc_net_eth1_provide="!net" rc_net_eth2_provide="!net" rc_net_eth3_provide="!net" # Internal bonding for Corosync and DRBD slaves_bond0="eth2 eth3" mode_bond0="balance-rr" miimon_bond0="100" downdelay_bond0="200" updelay_bond0="100" config_bond0="192.168.0.1/24 brd +" # External bonding slaves_bond1="eth0 eth1" mode_bond1="active-backup" # 802.3ad on prod arp_interval="2000" arp_ip_target="192.168.2.254" # HP Switch config_bond1=" 172.16.2.230/24 brd + 192.168.2.203/24 brd + " metric_bond1="1000" routes_bond1="default via 172.16.2.1" vlans_bond1="100 102 104 105 106 107 108 109 200" config_bond1_100="null" config_bond1_102="null" config_bond1_104="null" config_bond1_105="null" config_bond1_106="null" config_bond1_107="null" config_bond1_108="null" config_bond1_109="10.1.100.1/16 brd +" config_bond1_200="null"
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.
Have fun…