Die Technik hinter is.uberspace.online

Posted by luto on Tuesday, April 28, 2020

is.uberspace.online sagt euch zu jeder Tages- und Nachtzeit, wie es um unsere Infrastruktur steht. Wir veröffentlichen dort geplante Wartungsarbeiten, aber auch spontane Gebrechen sowie die Entwarnungen zu beiden. Aber wie läuft das eigentlich im Hintergrund ab?

status

Die meisten Statusseiten wie die von Pretix oder Intercom haben nur eine Hand voll Komponenten, über die berichtet wird: Website, API und vielleicht ein diffuses “Kundensysteme”. Für viele Anbieter ist das auch vollkommen ausreichend: Ist der Service down, ist er eben für alle down. Andere wie DigitalOcean gehen mehr ins Detail und listen ihre zwölf Standorte. Auch hier: Standort weg, alle Kunden an dem Standort weg - vereinfacht gesagt.

Unsere Situation ist da etwas extremer: Da bei uns jeder Host quasi autark ist, gibt es meistens nur Probleme mit einzelnen Hosts und nicht gleich mit allen auf ein Mal. Eine Ausnahme sind Netzwerkprobleme, die gesondert aufgeführt werden. Daher möchten unsere User auch den Status ihres Hosts auf der Statusseite sehen, nicht nur ein diffuses “irgendwo gibt es Probleme”.

Die meisten Statusseiten-Provider wie “statuspage.io” aber auch OpenSource-Lösungen sind gebaut, um über den Status von drei, zehn oder vielleicht zwanzig Komponenten berichten zu können. Nicht aber den von 180 Uberspace-Hosts. Wir mussten also etwas kreativer werden.

Datenflut

Fünf Komponenten lassen sich in einem Web-Interface schnell zusammenklicken und ändern sich zudem auch nicht häufig. Bei 180 Stück und ein paar neuen jede Woche wären wir eine gute Zeit lang beschäftigt. Zum Glück haben wir vor ein paar Jahren angefangen, mit Netbox eine sauber strukturierte Liste all unserer Hosts zu pflegen:

netbox

Wir haben also eine Statusseite, die Daten braucht und ein Netbox, das Daten hat. Außerdem bieten beide eine API an. Besser wirds nicht! 😁

Das Ergebnis hört auf “cachet_netbox_sync” und lebt auf GitHub.

Auf Basis einer kurzen Config im INI-Format nimmt das Tool Listen von Hosts oder anderen Dingen aus Netbox und legt in Cachet entsprechend Komponenten an:

[source.netbox.u7]
endpoint=virtualization.virtual_machines
filters.tenant=uberspace-7
filters.status=1
group_by_field=tenant.name

[source.netbox.sites]
endpoint=dcim.sites
filters.tag=uberspace
group=Network

In diesem Beispiel schnappt sich der erste Block alle aktiven (lies: Fertig gebauten) VMs, filtert die U7-VMs heraus, gruppiert sie noch unter “Uberspace 7” und schreibt sie anschließend ins Cachet. Dort sind sie dann direkt sichtbar.

Der zweite Block macht das selbe, aber mit ganzen Rechenzentren: FRA2 und FRA3. Die ändern sich zwar nicht so oft, so ist aber a) klar, wie die Einträge erstellt wurden, b) sind die Bezeichnungen im Cachet garantiert klar, sodass wir sie automatisiert bearbeiten können und c) die Quelle für alle Daten in Cachet die selbe: netbox.

Wir haben bei der Entwicklung brav darauf gedachtet, keine Uberspace-Spezifika in den Code einzubauen. URLs zu unserer Infrastruktur finden sich natürlich nicht im Code. Durch die oben skizzierten [source.netbox.u6]-Blöcke können potentielle Nutzer des Tools beliebige Daten aus Netbox ziehen: VMs, Bleche, Steckdosenleisten, Patch-Kabel, …

Wenn bei euch in der Firma oder privat also zufällig ein Cachet und ein Netbox rumliegt und ihr viel zu viele Hosts habt, tobt euch aus:

https://github.com/Uberspace/cachet_netbox_sync

Automatisierung

Nun ist ein Tool zwar besser, als neue Hosts manuell im Netbox klicken zu müssen, noch besser wäre es aber doch, würde das komplett ohne unser Zutun passieren.

Viele unsere Automatisierungen laufen über die GitLab CI unserer internen Instanz. So bauen wir Pakete, liefern Updates aus und aktualisieren - seit neuestem - auch unser Cachet:

---
sync_cachet:
  image:
    name: uberspace/cachet_netbox_sync
    # https://gitlab.com/gitlab-org/gitlab-runner/issues/1170#note_271904909
    entrypoint: [""]
  script:
    - cachet_netbox_sync --config cachet_netbox_sync.ini

Außerdem liegt im Repository noch eine entsprechende cachet_netbox_sync.ini, die definiert, von welchem Netbox, welchem Cachet und welche Daten verarbeitet werden sollen. Über GitLabs “Pipeline schedules” wird der Sync dann jede Stunde ausgeführt.

Ein Cronjob hätte es freilich auch getan, so müssen wir uns aber keine Gedanken machen, auf welchem Host das Script läuft und die Dokumentation schreibt sich auch fast von selbst. Außerdem gibt es im GitLab Logging und Monitoring gleich gratis dazu.

Das Image uberspace/cachet_netbox_sync dazu ist natürlich auf Docker Hub zu finden.

Darstellung

cachet_netbox

Um die Statusseite nicht mit 180 Zeilen vollkommen zu überladen zeigen wir nur Hosts an, die gerade ein Problem haben. Wenn kein Host schwächelt sind nur die drei großen Kategorien zu sehen: “Network,” “Uberspace 6” und “Uberspace 7.” Hinter den Kulissen haben wir allerdings die volle Liste aller Hosts hinterlegt.

Cachet hat leider kein Feature, um Komponenten basierend auf ihrem Status auszublenden, also mussten wir hier auf CSS und JavaScript-Hacks zurückgreifen. Wenn kein JavaScript da ist, zeigen wir einfach die volle Liste an. Den zugegebenermaßen schrecklichen Code dazu können geneigte Leserinnen selbst im HTML-Code der Seite nachschlagen.

Um das in Zukunft ohne CSS- und JS-Hacks lösen zu können, haben wir beim Projekt einen Pullrequest eingereicht.

RSS

Bei allen Neuerungen haben wir leider auch einen Wermutstropfen zu vermelden: Cachet kann, in der Version, die wir einsetzen, kein RSS. Es gibt allerdings einen Pullrequest, um das (wieder) einzubauen. Bis der durch ist, verliert die Statusseiten allerdings leider ihren Feed.

Automatische Incidents

In Zukunft möchten wir Incidents aus unserem Incinga-Monitoring direkt auf der Statusseite anzeigen. Sobald der Automatismus sie angelegt hat befüllen wir sie noch händisch mit Details und schließen sie letztendlich, wenn alles wieder gut ist. Da unser Incinga ebenfalls aus der Netbox befüllt wird, passen die Puzzleteile auch wunderbar zusammen.

PS: Nein, nein, das alles ist überhaupt nicht overengineered.

Aber lustig wars und wartbar ist es auch ;)