Photo from the top of the roof of the oecumenic centre. // Foto vom Dach des Ökumenischen Zentrums.
Photo of big satellite dish with fiberoptic LNBs. // Foto von großer Satellitenschüssel mit Glasfaser LNBs.
Photo of multiplexers taking in a single optical fiber and demultiplexing it to coaxial cables. // Foto von Multiplexern die jeweils aus einer einzelnen Glasfaser mehrere Koaxialkabel demultiplexen.
Photo showing the backside of a 19'' 4U server with lots of TV tuner cards connected to lots of coaxial cable. // Foto der Rückseite eines 19'' 4HE Servers mit vielen TV Karten die wiederum mit vielen Koaxialkabeln verbunden sind.
Photo of rack with 3 big routers and lots of fiberoptic patchpanels. // Foto eines Racks mit 3 großen Routern und vielen Glasfaserpatchpaneln.
Wie einige im August vielleicht gemerkt haben, hat es von Montag Nacht (14. August 2017) bis Mittwoch Abend einige technische Probleme bei uns gegeben. Diese haben dazu geführt, dass das Selfnet-WLAN nicht mehr funktioniert hat. Doch was war die Ursache dafür?
Alles fängt damit an, dass einige virtuelle Maschinen nicht mehr normal funktionieren. Schnell ist klar, dass dies kein Problem der jeweiligen virtuellen Maschinen, sondern unseres Storage-Clusters ist.
Unser Storage-Cluster basiert auf Ceph und stellt allen virtuellen Maschinen die Festplatten und damit etwa 100 TiB Speicherplatz bereit. Es besteht aus 3 Knoten (Nodes): Ein großer Klotz in Vaihingen (storage-1), ein weiterer großer Klotz in der Heilmannstraße (storage-2) und ein kleinerer nochmals in Vaihingen (storage-3). In der Theorie sollte der Cluster auch noch weiterhin funktionieren, wenn ein Knoten ausfällt.
Die erste Diagnose war, dass der Link (Verbindung) von storage-2 zum Core-Router dort wackelig ist. Deshalb entscheidet man sich dazu storage-2 komplett abzuschalten. Die Hoffnung: Das Ceph sammelt sich dann und verteilt die Inhalte neu, damit wieder hinreichende Redundanz sichergestellt ist. Das tritt jedoch entgegen unserer Annahme nicht ein.
Virtuelle Maschinen, welche viel Disk-IO (also Lese- und Schreiboperationen) verursachen (z.B. Mail, DHCP wegen logging oder Radius), stellten daher sofort ihren Dienst ein. Auf wundersame Weise überleben die IRC und Jabber/XMPP Server die Zeit ohne funktionierende Festplatten.
Erste Versuche den Link (Glasfaser und Optik) zwischen storage-2 und heilmann-core zu reparieren, scheiterten an einem SFP (Optik), auf dessen Schachtel Intel draufstand aber wohl doch nicht Intel drin war und deshalb die Netzwerkkarte den SFP nicht akzeptiert.
Um das Netz für unsere Mitglieder wieder halbwegs verfügbar zu machen, wird dann in den Morgenstunden des Dienstags (etwa zwischen 5 und 6 Uhr) auf kvm-dev (Virtualisierungsserver) die virtuelle Maschine 'notfall-1' mit lokaler Festplatte erzeugt und dort mit Ansible (schick, wa?) ein resolver und DHCP-Server installiert. Glücklicherweise hat einer von uns noch von der DHCP-Migration vor einer Woche die von den Update-Skripten erzeugte DHCP-Konfiguration im /tmp Ordner liegen. Sonst wäre das deutlich schwerer gewesen...
Auch nachdem erfolgreich in storage-2 und den heilmann-core neue SFPs und neue Patchkabel eingebaut wurden, will sich das Ceph immer noch nicht wieder zusammenbauen. Mal geht es aufwärts mit der Anzahl an 'guten' Objekten, um dann wieder zu sinken. So läuft das dann bis Mittwoch Abend. Im tcpdump
zwischen den Storage-Kisten fallen uns recht viele ACKs auf, aber mit iperf
laufen dennoch 10GBit/ über den Link...
Einem unserer aktiven Mitglieder fällt dann im IRC Chat auf, dass
ich hab grad die vermutung, dass der link zwischen heilmann-core-2 und -1 hin ist
ich hatte gerade jede menge loss dazwischen und testweise das routing umgebogen, dass der weg zu storage-2 nicht über den link geht
Daraufhin fängt sich Ceph wieder. Im weiteren Verlauf der Dinge stellt sich dann heraus, dass nicht der link zwischen den beiden Core-Routern in der Stadt wackelig ist, sondern die Strecke vom vaih-core-1 zum heilmann-core-2 wackelig ist. Auch das Tauschen und Putzen aller Glasfasern und SFPs ändert daran nichts.
Mit dem Routing über den kade-core hat sich das Ceph dann auch im nu zusammen gebaut, aber manche virtuelle Maschinen wollen gar nicht booten. Andere virtuelle Maschinen kommen nicht über die Initramdisk hinaus. Alles ganz komisch.
Also haben wir eine der Festplatten (der virtuellen Maschinen) mit rbd map
als Blockdevice auf einem der kvm-hosts (Virtualisierungsserver) gemapped und mit cat /dev/rbd0 | xxd
einen Dump (Speicherauszug) erstellt. Feststellung: Nach ein paar Megabyte bleibt die Operation hängen und will sich weder durch ^C noch mit kill -9
beenden lassen. Vermutlich findet bei rbd map
die Kommunikation mit den storage-nodes im Kernel statt und der syscall bleibt hängen. Das ist zum Debuggen natürlich gar nicht schön.
Deshalb haben wir mit rbd import
die Platte auf stdout (Standardausgabe) geschrieben und festgestellt, dass auch dies nach ein paar MB hängen bleibt, sich aber im Gegensatz zu der Methode davor mit ^C abbrechen lässt. Ein wenig Debuggen mit strace
zeigt, dass sich rbd
mit einem OSD (so heißen bei Ceph die Daemons (Dienste), die an den Platten im Storage dranhängen) auf Port 6914 verbinden wollte, aber ein "connection refused zurück kam". netstat
bestätigt, dass da tatsächlich ein OSD auf dem Port lauscht. Es stellt sich heraus, dass in der Firewall auf allen Storage-Knoten nur Ports 6700-6900 offen waren, Ceph aber die Ports 6800-7300 benützt. Interessanterweise steht in den Release notes von Ceph nichts von der Portänderung sondern nur in den verschiedenen Versionen der Dokumentation.
Nachdem das repariert war, wollen auch alle virtuellen Maschinen wieder hochfahren. Ein stichprobenartiges fsck
(Dateisystemüberprüfung) fand nirgendwo Fehler.
Woran lag's also?
Ursächlich war die kaputte Glasfaserstrecke zwischen Vaihngen und der Innenstadt. Dies hat zu Paketverlusten geführt aber der Link war noch da und deshalb sah das Routing keinen Grund, die betroffene Strecke nicht zu nehmen. Dem Ceph kann man hier nichts vorwerfen, Zitat:
und halb-kaputtes "Kabel" fickt am Ende jedes System
Das zweite Problem war, dass sich das Ceph nach Abschalten von einem der drei Knoten nicht wieder zu einem funktionierendem Zustand zurückkehren konnte. Weshalb wissen wir noch nicht. Die Firewallregeln von oben kann man ausschließen, da alle anderen OSDs auf nicht gesperrten Ports liefen.
Das dritte Problem war, dass die Firewall auf den storage-nodes falsch konfiguriert war. Weshalb das davor nicht aufgefallen ist wissen wir nicht genau. Wir vermuten, dass die OSD's bis jetzt immer zufällig auf den 'freigeschalteten Ports' liefen und das mit der neuen Version von Ceph sich der Bereich der Portnummern geändert/erweitert hat.
Was wollen wir noch verbessern?
Wir vermuten, dass durch die OSD-Crashes wegen kaputtem Netz einige Objekte nur auf storage-2 ge-ack-t waren, der restliche cluster hat diese dann nach dessen abschalten nicht gefunden und I/O blockiert. Deshalb konnten storage-1 und storage-3 sich nach abscahlten von storage-2 nicht mehr syncen.
Um das in Zukunft zu verhindern überlegen wir uns gerade wie wir unser Routing (OSPF) verbessern können. Folgende Möglichkeiten werden im Moment diskutiert um bei defekten Verbindungen die Routen möglichst schnell über andere Verbindungen laufen zu lassen:
-
BFD (Bidirectional Forwarding Detection): Hierbei werden zwischen zwei Routern viele Pakete hin und hergeschickt. Sollten einige Pakete nicht oder nicht intakt ankommen wird der Link automatisch deaktiviert. Die Folge: OSPF baut die Routen neu und der Pakete nehmen einen anderen Weg.
-
OSPF Metriken: Der defekte Link (Glasfaserstrecke) ist die (geographisch) längste die wir im Moment haben. Es bietet sich hier an die Metriken aller Links im Wohnheimnetzwerk über ihre Entfernung voneinander in Kilometern zu setzen.
-
Carrier-Delay: Wenn ein Link instabil ist und häufig an/aus geht (flappt) müssen alle OSPF Teilnehmer (Router) ihren "Shortest Path Baum" neu bauen. Carrier-Delay sorgt dafür, dass ein Link erst dann verwendet wird wenn dieser eine gewisse Zeit stabil läuft.
-
Dampening: Immer wenn ein Link down geht, bekommt dieser Link einen Malus (Penalty). Sollte diese über einen Schwellenwert steigen wird der Link deaktiviert. In bestimmten Zeitabständen wird der Penalty Wert halbiert.
In the last few months we observed weird behaviour regarding some of our servers that resulted in our servers not being able to reach the internet over IPv6[1]. The servers could reach other devices within the same layer 2 network but not much else.
[1] The current standard protocol alongside the ancient IPv4 protocol that has been deprecated in the year 1998.
On digging further we discovered that there was an additional default route to the linklocal fe80::0123:45ff:fe67:89ab IPv6 address.
$ ip -6 route
2001:db8::/64 dev eth0 proto kernel metric 256
fe80::/64 dev eth0 proto kernel metric 256
default via 2001:db8::254 dev eth0 metric 1024
default via fe80::0123:45ff:fe67:89ab dev eth0 proto kernel metric 1024 expires 1717sec hoplimit 64
At first we just removed the additional default route from one of the servers.
$ ip -6 route del fe80::0123:45ff:fe67:89ab dev eth0
But this only worked for about 2 minutes. After that the additional default route appeared again.
Since the IPv6 address included the 'ff:fe' pattern we knew that this is in fact an autoconfigured address.
Therefore with some quick searching we found out the brand of the device.
By looking at the switch the servers were attached to we could also find the port of the device in question because we knew the MAC address.
Digging deeper we suspected router advertisements as the culprit (because the bad default route reappeared after a short time).
Running tcpdump on all 3 of our virtualisation servers confirmed that the problem persisted in both server networks (Allmandring and Heilmannstraße) and was in fact caused by 2 devices (one in each server room).
$ sudo tcpdump -vvvv -ttt -i br-server icmp6 and 'ip6[40] = 134'
The devices causing the problem were our Cisco ASAs. This is a VPN/Firewall/... appliance. We only use the VPN functionality and all functionality not related to VPN has been deactivated on both devices.
But since most organisations that operate this kind of device use it primarily as a firewall appliance - we suspect by default - router advertisements are turned on for the main network interface to divert all traffic through the device. (In our case this did not work because the Firewall/Gateway functionality was deactivated entirely so the packages sent from the different servers were just dropped.)
Temporarily the problem could be fixed by disabling the auto-learning of default routes (and removing the defective default routes on the affected servers).
$ sudo sysctl net.ipv6.conf.all.accept_ra=0
After deactivating router advertisements on the two ASA devices the problem could be solved without reconfiguring every server and without having to keep this in mind for future deployments.
We are now looking into implementing RA Guard. :-)
PS: Instead of staring at the manpage the arguments for tcpdump have been copied shamelessly from https://gist.github.com/hgn/383308615d8c96551afa.
Update 2017-10-31: In August 2017 we overhauled our virtualisation Servers so they are basically routers.
In this scenario there is no single network bridge on the virtualisation Server but every virtual machine has it's own network interface on the VM Host including a BGP Daemon, a NDP Proxy and an ARP Proxy.
Once a VM is booted up the interface on the host system becomes active and the BGP Daemon announces the IP addresses of the VM to the network.
This does not only mitigate the problem (because rogue router advertisements are not proxied to the VMs) but also makes it possible to live migrate all VMs to the different virtualisation hosts even without having "one unified" server network.
With this one can save a lot of money for routers capable of Layer-2-VPN / EVPN and still be able to live migrate VMs. Also there are cases where you do not want to or simply cannot aggregate or even renumber old subnets so a L2VPN would not help anyway.
We plan to describe what we did in detail later in another blog article.