Software Development, DevOps

So geht's: Wildfly als Cluster mit Docker

Wildfly in einem Docker-Container zu betreiben ist nicht schwer. Die Beschreibung dazu findest du auf der Docker-Hub-Seite zum Image von Wildfly. In diesem Blogpost beschreibe ich, wie du mehrere Wildfly-Container startest und diese zu einem Cluster verbindest.

Leider wird in der Wildfly-Dokumentation nicht beschrieben wie man mehrere Wildflys, auf unterschiedlichen Maschinen in einem Netzwerk, in ein Cluster zusammenfügt.

Stattdessen wird nur darauf eingegangen, wie du ein Wildfly-Cluster auf einer Maschine erstellst. Dieses Vorgehen soll laut Dokumentation auch für mehrere Maschinen möglich sein. Das ist allerdings nicht ganz korrekt – weshalb du im Folgenden Schritt für Schritt erfährst, wie es exakt funktioniert.

Wildfly als Cluster mit Docker: verschiedenfarbige Container dicht an dicht gestapelt
Dank an Guillaume Bolduc für die kostenlose Bereitstellung dieses Bildes auf unsplash.

 

Warum Wildfly im Cluster?

Wildfly selbst bietet die Möglichkeit in einem Cluster zu arbeiten und damit Loadbalancing und Ausfallsicherheit zur Verfügung zu stellen. Somit werden beispielsweise Stateful Beans über alle Clusterknoten repliziert. 

Fällt ein Wildfly aus, sei es durch Netzwerkprobleme oder weil sich eine Maschine aufhängt, übernehmen die anderen Wildfly-Instanzen die Aufgaben mit, ohne den State der Anwendung zu verlieren (Ausfallsicherheit).

 

Wildfly in Docker

Wie Wildfly in einem Docker-Container verwendet wird, ist sehr gut auf der Docker Seite von jboss beschrieben. Sie nutzen das jboss-Image und fügen den aktuellen Wildfly hinzu.

Willst du Veränderungen vornehmen, musst du ein eigenes Image schreiben. Ich werde im Folgenden das offizielle jboss-Wildfly-Image nutzen und zu einem eigenen Image erweitern.

(Die Anpassungen können theoretisch auch gänzlich in docker-compose gemacht werden, sind aber bezüglich der Überschaubarkeit getrennt.)

 

Wildfly Multicast

Der Startbefehl von Wildfly im Docker ist:

CMD ["/opt/jboss/wildfly/bin/standalone.sh", "-b", "0.0.0.0"]

Dies startet den Wildfly mit seiner Standardkonfiguration und bindet ihn an die IP 0.0.0.0.

Standardmäßig ist Wildfly nicht in einem Cluster / multicastfähig und findet somit keinen anderen Wildfly in seinem Netzwerk.

jboss beschreibt auf der eigenen Seite, wie man den Wildfly mit dem High-Available-Service startet. Unter 7.2.1 wird beschrieben, dass man die standalone-ha.xml benötigt, um diesen Service zu nutzen. Um alle Features des Netzwerkes, inklusive Infinispan, zu nutzen, werde ich die standalone-full-ha.xml Konfiguration verwenden.

Also muss die Option -Djboss.server.default.config=standalone-full-ha.xml hinzugefügt werden.

Weiterhin musst du noch den Namen und den Port-Offset setzen, da sonst beide versuchen den Port 8080 und den Port 9990 zu verwenden. Ohne die Anpassung kommen sich die beiden Wildflys folglich in die Quere.

-Djboss.socket.binding.port-offset=<offset of your choice> -Djboss.node.name=<unique node name>

Startest du nun den Wildfly local zweimal, wird, sofern ein Deployment vorhanden ist, ein Cluster aufgebaut.

Dies sollte sowohl lokal als auch auf verschiedenen Maschinen im selben Netz funktionieren:

...that another instance of the server can either be on the same machine or on some other machine...

So jedenfalls die Dokumentation von jboss (siehe 7.2.1).

Dies ist allerdings nicht gänzlich korrekt.

In der Dokumentation fehlen ein paar Schritte beziehungsweise Parameter, um die Funktion außerhalb des lokalen Netzes zu verwenden.

Die fehlenden Schritte

Um IPV4 zu nutzen, musst du Java die Option -Djava.net.preferIPv4Stack=true mitgeben.

Im zweiten, wichtigsten Schritt, musst du jgroups an die IP deines Rechners binden. Hierbei kannst du bei Linux und Mac einfach $(hostname -i) verwenden.

-Djgroups.bind_addr=$(hostname -i)

Weiterhin wird ein Passwort benötigt, sodass jboss ein sicheres Cluster aufbauen kann:

-Djboss.messaging.cluster.password=<PASSWORT>

Fehlt die Funktion, wird im Log entsprechend ausgegeben, dass ein Passwort notwendig ist. In der standalone-full-ha wird dies mit CHANGE ME!! dargestellt.

Sind diese Schritte erledigt, kannst du Wildfly auf verschiedenen Maschinen im selben Netzwerk starten. Sie werden sich nun automatisch zu einem Cluster zusammenfinden.

 

Wildfly im Docker mit Multicast

Wendest du alle oben beschriebenen Optionen an, kannst du ein Dockerfile erstellen, welches einen multicastfähigen Wildfly erzeugt. Im Beispiel füge ich noch ein HelloWorld.war hinzu, welches ich später von außen erreichen kann.

Diese Optionen können auch ausschließlich über das docker-compose File konfiguriert werden, sind hier aber aus Gründen der Übersicht getrennt.

  FROM jboss/wildfly

  ADD helloworld.war /opt/jboss/wildfly/standalone/deployments/

  ARG WILDFLY_NAME
  ARG CLUSTER_PW

  ENV WILDFLY_NAME=${WILDFLY_NAME}
  ENV CLUSTER_PW=${CLUSTER_PW}


  ENTRYPOINT /opt/jboss/wildfly/bin/standalone.sh -b=0.0.0.0 -bmanagement=0.0.0.0 -Djboss.server.default.config=standalone-full-ha.xml -Djboss.node.name=${WILDFLY_NAME} -Djava.net.preferIPv4Stack=true -Djgroups.bind_addr=$(hostname -i) -Djboss.messaging.cluster.password=${CLUSTER_PW}

 

docker-compose.yml

Das oben dargestellte Image kannst du nun in einem docker-compose.yml verwenden, um ein Cluster zu erstellen.

  version: '3.5'
  services:

   wildfly1:
     build:
       context: .
       args:
         WILDFLY_NAME: wildfly_1_test
         CLUSTER_PW: secret_password
     image: wildfly_1_test
     ports:
     - 8080:8080
     networks:
       wildfly_network:

   wildfly2:
     build:
       context: .
       args:
         WILDFLY_NAME: wildfly_2_test
         CLUSTER_PW: secret_password
     image: wildfly_2_test
     ports:
     - 8081:8080
     networks:
       wildfly_network:

  networks:
   wildfly_network:
     ipam:
       driver: default

Hier werden zwei Wildfly-Container erstellt und beide in einem gemeinsamen Netzwerk hochgefahren. Der Netzwerkmodus ist IPAM (hier sehr gut beschrieben). Hierbei kümmert sich Docker automatisch um das IP-Management im Netzwerk.

Startest du nun Docker, mit docker-compose up, werden die beiden Images gebaut und die Wildfly-Container hochgefahren.

Nun müssten sich die beiden Wildflys zu einem Cluster verbinden; erkennbar am Log:
Received new cluster view for channel ejb: [wildfly_2_test|1] (2) [wildfly_2_test, wildfly_1_test].

Erreichbar ist das HelloWorld.war unter:

  • localhost:8080/helloworld/HelloWorld und
  • localhost:8081/helloworld/HelloWorld

(die beiden Ports die auf die Hostmaschine weitergeleitet werden).

Den verwendeten Code und das Beispiel findest du in folgendem Github-Repo.

 

Fazit

Wildfly mit Docker zu verwenden ist kein Hexenwerk. Mehrere Instanzen zu einem Cluster zu verbinden auch nicht, sofern man die Stelle findet, die in der Dokumentation von jboss leider (noch) fehlt.

Hoffentlich musstest du nicht zu lange nach diesen Informationen suchen, und kannst mithilfe dieses Blogbeitrags schnell dein Cluster aufbauen.

Hast du noch Fragen oder Diskussionsbedarf?
Dann hinterlasse mir jetzt deinen Kommentar!

   
Über Auryn Engel

Auryn Engel ist Anfang 2019 nach dem Abschluss seines Master-Studiums zu itemis in Leipzig gestoßen. Als Full-Stack-Entwickler beschäftigt er sich mit Java EE, Spring Boot, React und Vue.js.