Aller au contenu

WebWars

Rôle

WebWars fournit Hedgewars directement dans le navigateur à l'adresse https://webwars.lab.djayzone.com. Le moteur de jeu tourne côté navigateur en WebAssembly. Le pod Kubernetes héberge le frontend statique, la passerelle WebSocket et le serveur Hedgewars utilisé pour le lobby et le relais multijoueur.

Le code amont est verrouillé sur le commit c71fb76ed493248a5d007bcf6222dc36f704e2d1 de apmlabs/webwars.

Application suspendue

WebWars est volontairement maintenu à replicas: 0. Les manifests et images du jeu sont conservés. Son Ingress route temporairement vers une page de maintenance légère qui répond HTTP 200, surveillée par Gatus.

Architecture

flowchart LR
  B[Navigateur] -->|HTTPS| T[Traefik]
  T -->|/| F[Nginx frontend]
  T -->|/ws WebSocket| G[Node.js gateway]
  G -->|TCP 46631 localhost| H[Hedgewars server]
  F --> D[Assets WebAssembly immuables]

Les trois processus runtime partagent un même pod. C'est volontaire : le serveur Hedgewars conserve les rooms et l'état du lobby en mémoire. Plusieurs réplicas derrière un équilibrage HTTP fragmenteraient les joueurs entre plusieurs lobbies sans mécanisme de session partagée.

En fonctionnement, le Deployment utilise un seul réplica et une stratégie Recreate. Il est actuellement suspendu avec replicas: 0. Une indisponibilité brève est attendue lors d'un redémarrage ou d'un changement de nœud après réactivation.

Le pod n'est lié à aucun nœud particulier. Comme ses trois images contiennent déjà les artefacts compilés et qu'aucune donnée persistante n'est nécessaire, Kubernetes peut le recréer sur n'importe lequel des trois VPS.

Images immuables

Historique de livraison : le workflow GitHub Actions WebWars images and validation récupérait le commit amont épinglé et construisait trois images linux/amd64. Depuis le passage de la CI au webhook GitHub App et à Dagger, ce workflow hébergé ne doit plus être considéré comme une voie de publication disponible sans autorisation explicite :

  1. ghcr.io/djayzone/webwars-frontend:c71fb76ed493-assets1 assemble les fichiers HTML/JavaScript/WebAssembly et les données Emscripten ;
  2. ghcr.io/djayzone/webwars-gateway:c71fb76ed493-assets1 contient la gateway Node.js et uniquement ses dépendances de production ;
  3. ghcr.io/djayzone/webwars-server:c71fb76ed493-assets1 contient le serveur Hedgewars compilé avec GHC.

Le paquet de données du moteur est volontairement généré sans LZ4. Le chargeur obsolète déjà inclus dans le fichier dist/hwengine.js amont est retiré pendant le build, tandis que les constantes d'environnement Emscripten qui le précèdent sont conservées : sans cette étape ciblée, le runtime interprète le paquet optimisé avec les métadonnées d'un ancien paquet LZ4 de 195 Mo, ou perd les constantes nécessaires à son initialisation. La police CJK wqy-zenhei.ttc, requise au démarrage même avec l'interface française, est explicitement préchargée dans /Data/Fonts ; son absence provoque TTF_OpenFontRW puis l'arrêt immédiat du moteur.

Le bundle JavaScript précompilé du commit amont ne contient pas encore le chargeur dynamique présent dans son fichier source pre.js. Les thèmes et cartes sont donc intégrés au paquet Emscripten principal afin qu'ils existent dans /Data avant le démarrage du moteur. Les invariants de build vérifient explicitement Island/theme.cfg et Lonely_Island/map.cfg, les deux assets qui révélaient auparavant l'erreur. Le fichier est publié sous un nom versionné (hwengine-assets1.data) et le chargeur porte une nouvelle query string afin qu'un navigateur ne réutilise jamais un ancien asset incompatible conservé par le cache immutable.

Historiquement, les Pull Requests reconstruisaient uniquement les images touchées, sans publication ; un push sur main publiait les images modifiées. Ce contrat historique doit être requalifié avant réactivation : un check Dagger webwars vert ne garantit ni la création ni la publication d'une nouvelle image sur GHCR. Un changement de WEBWARS_COMMIT ou WEBWARS_TAG reconstruit volontairement les trois images ; un changement limité au workflow, aux manifests ou à la documentation exécute les validations GitOps sans lancer de build d'image. Une nouvelle exécution sur la même branche annule automatiquement la précédente. Le workflow ne se déclenche que si le dossier WebWars ou son propre fichier change ; une modification MonCouple ou une mise à jour générale du wiki ne reconstruit pas les images. Le pod de production ne clone aucun dépôt, ne télécharge aucune dépendance et ne compile aucun code au démarrage. Le PVC de cache et les quatre init containers ont donc été supprimés.

Le registre GHCR doit laisser ces packages lisibles par le cluster. Un changement de commit amont nécessite un nouveau tag et doit être publié avant la mise à jour du Deployment.

Réseau et TLS

  • IngressClass : traefik ;
  • hôte : webwars.lab.djayzone.com ;
  • certificat : cert-manager via letsencrypt-production dans le Secret webwars-tls ;
  • / est routé vers Nginx sur le port 8081 ;
  • /ws est routé vers la gateway sur le port 8080 ;
  • le port Hedgewars 46631 reste interne au pod et n'est pas exposé par un Service public.

Le wildcard DNS Cloudflare de *.lab.djayzone.com fournit la résolution ; ce sous-domaine reste en DNS only comme les autres noms de ce niveau.

Ressources et santé

Chaque conteneur runtime possède requests/limits et des probes :

  • Nginx : HTTP /index.html ;
  • gateway : HTTP /status ;
  • Hedgewars : sonde TCP sur 46631.

Quand l'application est active, Gatus contrôle la gateway en interne et la route HTTPS publique. Ces deux contrôles sont actuellement retirés afin que l'arrêt volontaire ne soit pas signalé comme un incident.

Réactivation

Pour reprendre les travaux, remettre spec.replicas: 1 dans deployment.yaml via une Pull Request GitOps, rétablir dans la même PR les contrôles Gatus interne et public, puis vérifier le chargement complet du jeu dans un navigateur avant de considérer le service opérationnel.

Mise à jour

Pour mettre WebWars à jour :

  1. choisir et vérifier un nouveau commit amont ;
  2. remplacer toutes les occurrences du commit dans deployment.yaml ;
  3. valider le rendu Kustomize et identifier la voie de build et de publication actuellement autorisée ;
  4. ouvrir une Pull Request ;
  5. publier les trois images immuables via la procédure autorisée, puis relever leurs digests avant promotion GitOps ;
  6. après merge, vérifier que les trois conteneurs deviennent prêts, que le certificat est Ready et qu'une partie hotseat puis une room multijoueur démarrent.

Retour arrière

Revenir au commit GitOps précédent restaure les images et manifests antérieurs. Le lobby et les rooms vivent uniquement en mémoire : un redémarrage les interrompt, mais aucune donnée utilisateur persistante n'est supprimée.

Le dashboard Grafana global conserve le Deployment du jeu désiré à zéro via kube-state-metrics ; l'absence de ses métriques de conteneurs est donc attendue pendant cette suspension. Gatus surveille la page de maintenance publique. Après réactivation, son contrôle doit de nouveau valider le frontend et la gateway réels.