This repository has been archived on 2021-03-01. You can view files and clone it, but cannot push or open issues or pull requests.
internship-novaquark/slides/notes.md

10 KiB

Titre

Bonjour tout le monde, je suis Pierre-Olivier Mercier et je vais vous présenter le stage que j'ai effectué dans le studio de jeux vidéo Novaquark.

Sommaire

Tout d'abord je vais vous parler de l'entreprise Novaquark, puis nous verrons en quoi consistait le stage avant de détailler les travaux que j'ai effectués.

Novaquark

L'entreprise

Mon maître de stage, Jean-Christophe Baillie, a créé Novaquark début janvier. Quand je suis arrivé mi-février, nous étions 4 dans l'entreprise, dans un petit bureau de l'incubateur de start-ups Agoranov.

Depuis hier, avec l'arrivée d'un game designer, nous sommes 14, dans un bureau bien plus grand et allons dans deux semaines changer de bureau pour occuper le plus grand de l'incubateur.

Dual

Le studio réalise un jeu en ligne massivement multijoueur où les joueurs évoluent dans un unique univers éditable.

Comme vous pouvez le constater sur cette capture d'écran assez récente, le rendu se veut réaliste grâce à l'utilisation de voxels.

À la manière du jeu Eve Online, les joueurs construisent leur propre jeu via les interactions qu'ils ont les uns avec les autres : certains choisiront de se spécialiser dans la construction de vaisseaux spatiaux, d'autres dans la gestion d'un empire, dans la collecte de ressources rares, joueront avec l'économie du jeu, exploreront l'espace à la recherche de nouveaux territoires, ... ou tout à la fois !

Par univers unique, on entend que tous les joueurs partagent un même monde, qui est bien évidemment réparti sur de nombreux serveurs.

Le stage

Durant mes 6 mois de stage, j'ai travaillé avec l'équipe serveur.

Mon but était de mettre en place les bases pour permettre d'adapter le nombre de serveurs à la quantité de joueurs connectés. C'est ce que l'on appelle la mise à l'échelle, scalability, la base du cloud computing.

Lorsque tous les joueurs rentrent chez eux le soir, on doit progressivement démarrer des serveurs pour répartir la charge, mais lorsqu'ils vont se coucher, on ne veut plus payer les serveurs alors qu'ils sont moins actifs et pourraient être regroupés.

Pour réaliser cela, on a besoin de s'intéresser et de relever un certain nombre d'indicateurs tels que la consommation CPU, la bande passante utilisée, le nombre de joueurs connectés sur un serveurs, etc.

Lorsque l'un des indicateurs aura atteint un certain stade, par exemple la consommation CPU à 90%, on vouloir démarrer une nouvelle machine puis déplacer une partie des joueurs sur ce nouveau serveur. Ce n'est pas magique, il faut prévoir des machines pour correctement répartir la charge en amont, tout en essayant de minimiser les échanges entre les machines (pour ne pas engeorger le réseau). Durant mon stage, j'ai principalement travaillé sur l'infrastructure, tandis que mon maître de stage développait le code du serveur.

Par ailleurs, j'ai réalisé des tests de montée en charge, mais pas encore sur l'architecture complète, juste avec un seul serveur car même si les techniques de répartition de charge sont fixées, elles n'ont pas encore été complètement implémentées.

Travail effectué

Relevé de métriques

Le premier projet que j'ai effectué consistait à relever des indicateurs système (métriques système), et à les envoyer à une base de données.

On a sélectionné la base InfluxDB : c'est un projet récent de base de données distribuée adapté aux stockages de données temporelles tels que les événements ou les métriques.

Les éléments relevés sont l'utilisation du CPU, la mémoire disponible, la bande passante utilisée, les entrés/sorties des disques, la charge et l'uptime. Ces données sont synthétisées à partir du système de fichiers processus (/proc).

Pour en faire profiter la communauté naissante de la base de données, nous avons distribué le projet sur GitHub. Il est écrit en Go, comme la base de données, afin de profiter du linkage statique permettant de ne pas avoir de dépendance à l'exécution.

On a annoncé début mars notre projet sur la liste de diffusion d'InfluxDB et depuis nous avons des rapports de bugs et plusieurs demande de merge qui nous sont parvenus.

La base de données met à disposition une interface web permettant de visualiser les données enregistrées, et permet d'étendre cette interface en y ajoutant des tableaux de bord. J'en ai réalisés deux, qui permettent de voir soit les données de toutes les machines d'un seul coup, soit d'une machine en particulier. Sur cette capture d'écran, on voit les différents indicateurs dans le tableau de board Grafana.

D'autres métriques sont envoyées par le serveur de jeu directement : le nombre de joueurs, le temps de latence d'accès à la base de données, ...

Du fait que la bibliothèque pour s'interfacer avec la base de données dans du code C n'avait pas encore été développée, je m'en suis chargé et ai proposé mon code aux développeurs du projet qui l'ont rapidement accepté.

La base de données expose une API fonctionnant au dessus du protocole HTTP, la bibliothèque que j'ai réalisé utilise donc allégrement la libcurl.

Déploiement centralisé

Recettes Ansible

Avec de nombreux serveurs, on a parfois du mal à gérer et centraliser leur configurations et la mise à jour de l'application pour laquelle ils sont destinés. Et l'on ne parle pas de la mise à jour générale du système corrigeant les failles de sécurités !

Plusieurs outils de déploiement existent tel que Chef, Puppet ou Ansible et permettent de configurer ou de vérifier la configuration d'une ou plusieurs machines. Ils fonctionnent à partir de recettes qui décrivent tous les points de configuration particuliers.

Lorsqu'il faut mettre à jour l'applicatif métier, lorsqu'il y a une base de données à mettre à jour également, on peut lancer des scripts pour s'occuper de la migration, centraliser les résultats et intervenir manuellement si besoin sur les machines sur lesquelles la migration se serait mal passée. Bien sûr, les machines défectueuses auront été mises à l'écart du cluster préalablement afin d'éviter qu'un utilisateur se retrouve à parler avec une machine défectueuse.

Nous avons décidé d'utiliser Ansible pour déployer et mettre à jour les serveurs exécutant des conteneurs applicatifs et les différentes machines virtuelles pour les environnements où l'on ne peut pas utiliser la virtualisation légère : les machines virtuelles à destination des développeurs ainsi que les machines client pour les tests de montée en charge.

Inventaire automatique

L'inventaire des machines est réalisé par un script écrit en Python, respectant les spécifications attendues par Ansible. Il peut récupérer depuis différentes sources (liste des machines de la libvirt pour un environnement local de test, requête AXFR sur un sous-domaine) la liste des machines ainsi que leur IP et qualifie ensuite, à partir d'une nomenclature précise, chaque machine et applique ensuite la recette qui doit être appliquée.

Interface de gestion

Pour le moment, les interactions avec le serveur sont encore relativement limitées, donc tous les développeurs n'ont pas encore besoin de cette machine virtuelle et se contente d'un serveur commun, mais à terme, elle permettra de charger différents scénarios de tests adapté à chaque développeur, via une interface simplifiée : aujourd'hui c'est une interface sommaire réalisée avec Curses, mais lorsque la demande sera plus forte, une interface web offrira les mêmes possibilités.

Virtualisation légère

On utilise Docker pour créer et exécuter des conteneurs applicatifs. Il s'agit de virtualisation légère : un environnement complet est embarqué, de la même manière que l'on a l'habitude de faire avec VirtualBox, mais au lieu de simuler une machine complète, le noyau va créer un espace d'exécution isolé permettant de lancer un autre système en parallèle.

Les conteneurs applicatifs sont très pratiques pour tester un environnement avant de le mettre en production, car comme il ne dépend d'aucun composant extérieur, quelque soit la machine sur laquelle il sera exécuté, il devrait avoir le même comportement. Seule les données partagées peuvent altérer le fonctionnement.

Docker est un projet récent, qui sussite un très fort engouement depuis sa création ; la première version finale est sortie il y a deux mois, ce qui permet de rassurer quant à sa stabilité pour les environnements de production.

Tests de montée en charge

On a fait les tests de montée en charge en installant sur une machine type un serveur de jeu.

Pour simuler un grand nombre de joueurs, on a fait appel au cloud d'Amazon sur lequel on a lancé un grand nombre de machines virtuelles exécutant des clients effectuant des actions de manière aléatoire : connexion, déplacements et pose d'éléments.

Cela nous a donné une première idée sur la viabilité de l'architecture choisie. Il aurait été impensable que le serveur sature avec seulement une cinquantaine de joueurs. Il s'est avéré que lors du premier test de monté en charge, un problème inhérent à l'ordonnanceur de la bibliothèque sous-jacente que nous utilisons nous a fait quelques frayeurs en faisant cracher le serveur inexplicablement avec quelques centaines de joueurs connectés.

L'architecture complète telle qu'elle a été pensée n'a pas encore pu être testée de cette manière car il reste encore des éléments à implémenter du côté du serveur de jeu, concernant notamment le partage des données.

Conclusion

Grâce à ce stage, j'ai pu travaillé avec des notions avant-gardistes que sont les problèmatiques d'un monde unique réparti.

Je suis monté en compétence sur des technologies d'avenir émergentes que son la virtualisation légère et les conteneurs applicatifs.

Je me suis intéressés à des sujets récurrents : le cloud computing, le déploiement, la sécurité.

Et j'ai contribué à des projets libres : Ansible, InfluxDB et SBT.

Finalement, mon travail ayant été apprécié, un CDI m'a été proposé à l'issue de ce stage pour continuer à travailler sur ces problématiques.

Mon exposé est maintenant terminé, je vous invite à poser vos éventuelles questions.