WildFly en domaine

L’objectif est de mettre en place un domaine WildFly, constitué d’un maître (appelé master) et un esclave (appelé host202).

Principe

Avec WildFly, nous avons le choix entre un mode autonome (standalone) ou en domaine (domain). Le mode standalone est similaire à ce que nous connaissions dans les anciennes versions de JBoss, avec un serveur démarré et administré individuellement. Le mode domain permet de démarrer plusieurs instances avec une seule commande et d’administrer les instances sur plusieurs machines de façon centralisée.

Dans le mode domain, il y a 3 types d’acteurs :

  • des serveurs WildFly sur lesquels sont déployées les applications,

  • un host controller par machine, chacun contrôlant les serveurs WildFly sur cette machine,

  • un domain controller qui pilote l’ensemble de l’environnement.

principe d’un domaine

Sur chaque machine, il faut démarrer un host controller (ou un domain controller), avec la commande

~# $JBOSS_HOME/bin/domain.sh

En démarrant ainsi, la configuration se fait dans les fichiers domain/configuration/host.xml et domain.xml. Le fichier host.xml contient le paramétrage du contrôleur et le domain.xml configure les serveurs WildFly.

Configuration

Contrôleur de domaine / d’hôte

Ce qui différencie un contrôleur de domaine d’un contrôleur d’hôte c’est l’élément <domain-controller> dans host.xml.

Un contrôleur de domain se contrôle localement :

<domain-controller>
  <local/>
</domain-controller>

Un contrôleur d’hôte est contrôlé par un contrôleur de domaine distant :

<domain-controller>
  <remote host="192.168.0.101" port="9990" protocol="remote+http" />
</domain-controller>

Chaque contrôleur doit avoir un nom unique dans l’environnement. On utilise souvent master pour le contrôleur de domaine et on change le nom des contrôleurs d’hôte :

<host name="host202" xmlns="urn:jboss:domain:18.0">
  [...]
</host>

Serveurs WildFly

Dans la terminologie des domaines WildFly, un serveur est une instance de WildFly. Ces serveurs sont démarrés par leurs contrôleurs ; chaque serveur est déclaré dans le fichier host.xml.

<servers>
  <server name="server-one" group="main-server-group">
  </server>
  <server name="server-two" group="main-server-group">
  </server>
</servers>

Le groupe de serveur qui est spécifié ici regroupe des serveurs qui ont le même profil de configuration, le même groupe de sockets et les mêmes applications. La configuration de chaque groupe de serveur est dans domain.xml.

regroupement des serveurs

Sur chaque hôte, chaque groupe fait référence à un profil qui est un assemblage de sous-systèmes, comme le logging, les datasources, web, ejb3,…​ Ce profil représente la configuration des instances.

Authentification (legacy)

Le contrôleur secondaire se connecte au contrôleur de domaine via son interface de gestion. Il doit donc en respecter les contraintes de sécurité, comme l’authentification.

Pour ça, la connexion <remote> doit spécifier le username et le security-realm dans lequel le mot de passe est stocké. Si le username n’est pas renseigné, c’est le name du host qui est utilisé.

<domain-controller>
  <remote host="192.168.0.101" port="9990" protocol="remote+http"
          username="slave" security-realm="SlaveRealm"/>
</domain-controller>

Le mot de passe est stocké en base64 sous la forme d’un élément de <server-identities>.

<security-realm name="SlaveRealm">
  <server-identities>
    <secret value="c2xhdmVfdXNlcl9wYXNzd29yZA==" />
  </server-identities>
</security-realm>
Ce paragraphe legacy ne s’applique que jusqu’à WildFly 24. En effet, l’ancien subsystem de sécurité a été retiré de WildFly 25.

Authentification (elytron)

Avec elytron, la connexion <remote> ne spécifie ni username ni security-realm, mais un contexte d’authentification.

<domain-controller>
  <remote host="192.168.0.101" port="9990" protocol="remote+http"
          authentication-context="hcAuthContext"/>
</domain-controller>

Le mot de passe et le nom d’utilisateur sont stockés dans une configuration d’authentification d'elytron. La relation entre le contexte et cette configuration est faite par l’intermédiaire de règles. Et bien que ça concerne un subsystem, c’est dans le fichier host.xml.

<subsystem xmlns="urn:wildfly:elytron:14.0">
  <authentication-client>

    <authentication-configuration name="hostAuthConfig"
                                  authentication-name="slave"
                                  realm="ManagementRealm">
      <credential-reference clear-text="slave_user_password"/>
    </authentication-configuration>

    <authentication-context name="hcAuthContext">
      <match-rule match-host="192.168.0.101"
                  authentication-configuration="hostAuthConfig"/>
    </authentication-context>

  </authentication-client>
  ...
</subsystem>

Comme toujours, la configuration avec elytron est complexe, mais avec beaucoup de souplesse.

Le mot de passe est en clair ici. On peut aussi le masquer ou externaliser son stockage dans un credential store.

Découverte du contrôleur de domaine

Dans les fichiers host.xml fournis avec les versions récentes de WildFly, les coordonnées du contrôleur de domaine ne sont pas directement stockées sur l’élément <remote>, mais dans des options de découverte. Cette façon de faire permet de spécifier plusieurs contrôleurs distants. Ça permet de démarrer avec un autre contrôleur si le premier est en panne.

<domain-controller>
  <remote authentication-context="hcAuthContext">
    <discovery-options>
      <static-discovery name="primary" protocol="remote+http"
                        host="192.168.0.101" port="9990"/>
      <static-discovery name="secondary" protocol="remote+http"
                        host="192.168.0.102" port="9990"/>
    </discovery-options>
  </remote>
</domain-controller>

L’exemple ci-dessus utilise un contexte d’authentification d'elytron, mais cette façon de faire est compatible avec la sécurité legacy.

Avec ces options de découverte, il est aussi possible de remplacer la communication réseau par du stockage S2. Je n’ai pas trouvé du documentation WildFly sur le sujet, mais la documentation JBoss EAP, Deploying JBoss EAP on Amazon Web Services l’explique bien et s’applique à WildFly.

Mise en oeuvre (sécurisée)

Ce paragraphe est un exemple de mise en oeuvre d’un domaine WildFly 25. L’environnement est simplifié, avec deux machines ; le maître est sur le serveur 192.168.1.201 et l’esclave sur le serveur 192.168.1.202.

relation host / master

Configuration du master

Le fichier host.xml par défaut convient bien pour cela. Pour simplifier l’environnement, je n’associe qu’un seul serveur au master. Il faut surtout ajouter un login pour l’esclave afin que celui-ci puisse s’authentifier auprès du master et se connecter à son interface de management.

~# $JBOSS_HOME/bin/add-user.sh host202 hostpwd

Le master peut maintenant être démarré, en prenant soin de lier l’interface de management à une adresse publique. Le choix de lier les interfaces applicatives à une adresse publique est secondaire ici (-b 0.0.0.0).

~# $JBOSS_HOME/bin/domain.sh -bmanagement 0.0.0.0

Pour démarrer un contrôleur de domaine sans serveur, on peut démarrer avec host-master.xml.

~# $JBOSS_HOME/bin/domain.sh -bmanagement 0.0.0.0 -Djboss.host.default.config=host-master.xml

Configuration du slave

Pour cela, le pont de départ serait plutôt host-slave.xml. En effet, il faut en priorité spécifier un domain-controller distant,et lui associer un realm qui contient un server-identity.

<domain-controller>
  <remote host="${jboss.domain.master.address}"
          port="${jboss.domain.master.port:9990}"
          protocol="${jboss.domain.master.protocol:remote+http}"
          authentication-context="hcAuthContext"/>
</domain-controller>

Le mot de passe est stockée au niveau de la configuration d’authentification d'elytron (fichier host-slave.xml). Par acquis de conscience, on va le stocker dans un format masqué.

~# bin/elytron-tool.sh mask --salt fzekalzg --iteration 7 --secret hostpwd
MASK-DZlF8QP1ioV;fzekalzg;7
<subsystem xmlns="urn:wildfly:elytron:14.0">
  <authentication-client>
    <authentication-configuration name="hostAuthConfig" realm="ManagementRealm"
                                  authentication-name="host202">
      <credential-reference clear-text="MASK-DZlF8QP1ioV;fzekalzg;7"/>
    </authentication-configuration>
    <authentication-context name="hcAuthContext">
      <match-rule match-host="${jboss.domain.master.address}"
                  authentication-configuration="hostAuthConfig"/>
    </authentication-context>
  </authentication-client>
  ...
</subsystem>

La configuration est prête, on peut donc démarrer l’esclave.

~# $JBOSS_HOME/bin/domain.sh -Djboss.domain.master.address=192.168.1.201 -b 0.0.0.0