2011
04.25

Comme vous avez peut-être pu le remarquer, je n’ai pas du tout posté d’articles ici pendant le mois dernier. Raison simple : j’étais principalement overbooké par l’organisation de la finale de Prologin, qui s’est déroulée du vendredi 22 au lundi 25 avril. Pour ceux qui ne le savent pas, Prologin est le concours national d’informatique pour les moins de 20 ans, et je suis secrétaire et administrateur système principal de l’association qui organise ce concours.

Pendant la finale du concours, 100 candidats doivent programmer une intelligence artificielle pour un jeu dont les règles changent tous les ans et sont rédigés par une petite équipe de gens motivés de l’association. Ils ont pour cela 36h, qu’ils passent dans les locaux de l’EPITA au Kremlin-Bicêtre à programmer, mais également à s’amuser un peu grâce aux différentes animations proposées par les organisateurs du concours (tournois de jeux, bataille d’eau, château gonflable, piscine à mousse, etc.). Côté administration système, il y a donc le problème de fournir à 100 candidats et (au moins) 10 organisateurs un système fonctionnant correctement et pouvant être déployé rapidement. L’autre problématique est de fournir un système permettant aux candidats de lancer des matches entre les intelligences artificielles qu’ils ont programmé, et permettant aux organisateurs de lancer des tournois contenant des milliers de matches de manière rapide.

Système utilisé par les candidats

Afin de répondre à nos contraintes de déploiement rapide, nous avons utilisé une solution à base de boot en PXE + disque système monté en NFS3 sur un serveur central dupliqué (nfsroot0 et nfsroot1). Ces deux serveurs utilisent DRBD en mode actif-actif afin de répliquer en temps réel les données modifiées d’un côté sur l’autre serveur. Pour profiter de cette fonctionnalité, il a également fallu utiliser un système de fichiers gérant l’écriture simultanée depuis plusieurs machines. Les principaux compétiteurs de ce côté là étaient OCFS2 et GFS, nous avons choisi le premier car il semblait plus simple à configurer et à administrer pour des néophytes de ce genre de technologies. La moitié des machines des candidats utilise nfsroot0 et l’autre moitié utilise nfsroot1 afin de distribuer la charge assez intense que supportent ces deux serveurs. Cette distribution est faite à base de round-robin DNS très classique.

La même chose a été mise en place pour /home, contenant les dossiers personnels de tous les candidats, et /srv/stechec, qui est utilisé pour stocker les intelligences artificielles et logs de matches qui servent au concours. Ces deux points de montage NFS sont tous deux sur nfshome0 et nfshome1, dupliqués de la même manière que pour / (DRBD + OCFS2).

Pour gérer tout ce qui est PXE, DHCP et DNS, nous avons utilisé dnsmasq, solution tout en un qui fait tout ce qu’il faut à partir de /etc/ethers et /etc/hosts. Même s’il a crashé plusieurs fois lors du reboot de 120 machines simultanément, nous n’avons globalement pas à nous plaindre de cette brique qui a fait tout ce qu’il fallait.

Enfin, tout tourne sur du Archlinux. Choix totalement subjectif et surement assez mauvais sur le long terme (c’est loin d’être un système stable comme Debian), mais on migrera ce qu’il faut quand ça sera nécessaire.

Distribution du lancement de matches

Lorsque les candidats programment leur intelligence artificielle, ils ont à leur disposition un intranet (programmé avec Django) leur permettant d’uploader leur code afin de le faire concourir. Lorsque le code est uploadé, il est automatiquement compilé, puis peut être utilisé pour lancer des matches. Lorsqu’un match est lancé via l’intranet, les logs des IA ainsi qu’un replay du match peuvent être téléchargés dès sa complétion.

Afin de distribuer les compilations des IA et le lancement des matches, j’ai programmé durant les semaines dernières deux programmes : un worker qui est lancé sur toutes les machines des candidats, et un master qui tourne sur nfsroot0 et qui sert à dispatcher les matches sur les différents workers. Ces deux programmes sont codés en Python avec Gevent (bibliothèque de programmation asynchrone), et communiquent via du XML-RPC dans les deux sens afin de s’échanger des messages. Du failover automatique est mis en place pour gérer le cas de la perte d’une machine, et le dispatching se fait de manière à ne pas surcharger une seule machine : les tâches sont distribuées équitablement sur les 120 machines.

Lors du lancement d’un match, l’intranet stocke donc dans une base de données PostgreSQL toutes les informations nécessaires, puis le master (qui poll la base de données toutes les 2 secondes) va redispatcher vers un worker, qui va s’occuper du lancement du match et renvoyer les résultats au master, qui va les inscrire dans la base de données.

Le lancement d’un match côté worker

Pour lancer des matches entre intelligences artificielles, Prologin utilise un programme codé vers 2005 par des membres de l’association, nommé Stechec. Il s’agit d’un serveur permettant de charger dynamiquement une bibliothèque dynamique contenant les règles d’un jeu, et une bibliothèque dynamique représentant l’intelligence artificielle jouant à ce jeu.

Stechec est codé en C++ et est totalement libre (sous licence GPLv2). Les sources de la version utilisée pour la finale de Prologin 2011 seront bientôt mises sur Github, mais la version précédente peut être trouvée sur Bitbucket.

Conclusion

Au final, tout a bien marché. Quelques pannes ont évidemment eu lieu (souvent à cause de problèmes de configuration réseau), mais globalement ce fut une bonne finale du point de vue système, surtout en prenant en compte que tout a été refait cette année. Ce fut par contre très crevant (une seule nuit de vendredi matin à lundi matin…) et je vais prendre un peu de temps à me remettre en forme… oh, wait, j’ai une soutenance demain :'( .