Im heutigen Blog Post möchten wir euch den Software Stack der Firma HashiCorp vorstellen.

Zu Beginn der Entwicklungszeit von Minecraft Legend haben wir in jeden Container die Adressen und Zugangsdaten von Datenbanken über Environment Variablen in den Container gemappt. Durch die rasante Vergrößerung der Infrastruktur wurden es wöchentlich mehr Variablen und der Überblick über diese ist sehr schnell verloren gegangen. Wir brauchten eine Möglichkeit die Anzahl der Variablen zu reduzieren.

Consul

Microservices oder Services im allgemeinen sollten, wenn es technisch möglich ist, immer so wenig wie möglich untereinander gekoppelt sein.

In Consul lassen sich Services (Datenbanken, Messagebroker, ...) registrieren und auch wieder discovern.

Wird zum Beispiel ein neuer Minecraft Server gestartet und möchte nach dem Start etwas in eine registrierte Redis Datenbank schreiben, muss der Server lediglich zu Consul verbinden und dort die Adresse einer laufenden Version von Redis anfragen. Mit dem zurückgelieferten Host und Port kann sich der Minecraft Server nun auf die Redis Instanz verbinden und seine Daten schreiben.

Jetzt reicht in unseren kleinem Szenario eine Redisinstanz nicht mehr aus, da zu viel gelesen und geschrieben wird. Es muss eine weitere Redisinstanz gestartet werden. Diese registriert sich nun einfach in Consul und ist neben der schon vorhandenen für alle Services erreichbar. Möchte nun ein weiterer Minecraft Server etwas in Redis schreiben, gibt Consul alle laufenden Instanzen von Redis zurück und der Minecraft Server verbindet sich zufällig auf eine der beiden Instanzen. Somit ist es ohne weiteres möglich, die Last auf mehrere Instanzen eines Services zu verteilen.

Consul bietet uns also folgende Vorteile:

  • Lose Kopplung der Services untereinander
  • Dynamisches hinzufügen weiterer Instanzen im Fall von Engpässen
  • Health Checks, die uns helfen, gestoppte oder gestörte Instanzen von Services zu identifizieren

Im folgenden findet ihr einen Screenshot der Weboberfläche von Consul. Dort seht ihr, welche Services bei uns momentan registriert sind.

Consul Weboberfläche
Consul Service Weboberfläche

Durch Consul konnten wir die Anzahl der Environment Variablen schon etwas reduzieren, da alle Hosts und Ports von jeglichen Services weggefallen sind. Doch ein Großteil der Variablen waren Zugangsdaten. Wie wir diese entfernen konnten, lest ihr im folgenden Abschnitt.

Vault

Wie die Adressen der Services, waren die Logindaten am Anfang auch einfach in den Container gemappt. Das hat zum Beispiel auch bei der Änderung eines Datenbankpassworts zu Problemen geführt, da das Passwort in allen Docker Images geändert werden musste. Zusätzlich mussten nach der Änderung alle Images neu gebaut und deployed werden.

Durch Vault konnten wir das Problem elegant lösen.

Jeder Docker Container hat nun nur noch ein Vault Token, mit welchem er sich auf unserem Vault Cluster authentifiziert und autorisiert. Anschließend kann der Container sich die benötigten Zugangsdaten aus Vault laden.

Wir haben in Vault zwei verschiedene Arten von Zugangsdaten hinterlegt: dynamische und statische.

  • Dynamische Zugangsdaten werden bei jeder autorisierten Anfrage eines Services neu generiert. Das bedeutet, dass Vault zum Beispiel in unserem MongoDB Cluster einen neuen Nutzer für den anfragenden Service erstellt und diesen zurückliefert. Dynamische Zugangsdaten können auch zeitlich begrenzt gültig sein.
  • Statische Zugangsdaten sind fest in Vault eingetragen. Dazu zählt zum Beispiel das Passwort zum Redis Cluster, da Redis keine ausgefeilte Nutzerverwaltung, wie zum Beispiel MongoDB bietet.

Vault bietet uns also folgende Vorteile:

  • Die Environment Variablen eines Docker Containers sind auf ein Minimum geschrumpft
  • Ändern wir Zugangsdaten von statischen Services wie Redis oder Kafka, können diese direkt in Vault angepasst werden. Beim nächsten Neustart eines Minecraft Servers, werden direkt die neusten Zugangsdaten aus Vault gelesen.
  • Die Zugangsdaten zu unserer MongoDB sind zeitlich begrenzt gültig. Nach einer fix eingestellten Zeit sind die Zugangsdaten abgelaufen und können nicht mehr verwendet werden.

Nomad

Für uns war schon immer klar, dass wir unsere Minecraft Server und auch andere Services nicht über Screen oder ähnliches starten werden. Das Vorgehen ist leider in der Minecraft Szene sehr weit verbreitet. In der Zeit von Docker und Kubernetes sollte man jedoch auf moderne Lösungen setzen.

Die meisten unserer Services werden daher in Docker gestartet. Anfangs haben wir mit Docker Swarm ein Docker-Netzwerk über mehrere Maschinen aufgebaut und unsere Services über docker-compose gestartet. Mit diesem Ansatz mussten wir aber alle Services von Hand starten und stoppen.

Dementsprechend wollten wir so schnell wie möglich auf eine skalierbare und auch einfach bedienbare Lösung umsteigen. Da uns Kubernetes für unseren Anwendungsfall zu komplex war und wir von Hashicorp bereits schon Consul und Vault genutzt haben, haben wir uns schlussendlich für Nomad entschieden. Über Nomad laufen bei uns aktuell alle Services. Somit sind wir in der Lage die benötigten Services dynamisch hoch oder runter zu skalieren. Die Services registrieren sich automatisch in Consul und werden auch automatisch neu gestartet, sollte der Healthcheck von Consul fehlschlagen.

Durch Nomad ist es auch möglich, ganz einfach weitere Maschinen in das bestehende Cluster mit aufzunehmen. So können wir zum Beispiel bei hoher Spielerauslastung weiter Game-Instanzen buchen, diese per Ansible automatisch konfigurieren und ins Cluster aufnehmen.

Nomad Job für den Charactereditor
Nomad Job Übersicht des Character Editors
Übersicht eine bestimmten gestarteten Instanz