Systèmes & Infrastructure
Avant les services managés, il y a une socket, une table de processus et un paquet. Voici les projets où j'ai dû construire ce que le framework masque d'habitude — et la raison pour laquelle je peux raisonner sur les couches sous un déploiement quand quelque chose casse.
L'automatisation Ansible est un travail conjoint avec Bilal Eddinaoui, dans son dépôt. Le serveur HTTP, la pile de conteneurs et les projets en C sont les miens.
- 180+
- connexions simultanées, un seul thread, sans blocage
- 9
- services dans la pile conteneurisée
- 0
- étape manuelle du serveur nu à la pile en service
Un serveur HTTP monothread, écrit de zéro
Un serveur HTTP/1.1 complet en C++98 — analyse des requêtes, routage, fichiers statiques, pages d'erreur, exécution CGI — sans framework ni bibliothèque pour le travail protocolaire. Il est délibérément monothread : la concurrence vient d'un mécanisme de notification d'événements plutôt que de threads ou de processus, de sorte qu'un seul thread multiplexe toutes les connexions sans jamais bloquer sur aucune.
L'écrire ainsi oblige à affronter ce que les frameworks dissimulent : une socket ne vous remet pas une requête. Elle vous remet des octets, au moment qui lui convient, en morceaux qui ne respectent pas les frontières des messages. Chaque lecture peut n'être qu'une moitié d'en-tête. Chaque écriture peut rester incomplète. La machine à états qui gère cela correctement est le véritable contenu du projet — et la raison pour laquelle ApacheBench et Siege ont pu maintenir plus de cent quatre-vingts connexions simultanées.
- Le comportement du serveur est entièrement piloté par un fichier de configuration — ports, hôtes, noms de serveur, routes, pages d'erreur et chemins CGI — analysé au démarrage plutôt que compilé.
- Les processus CGI sont lancés et leur sortie relayée sans bloquer la boucle d'événements qui sert tous les autres clients.
- Bâti sur kqueue, l'équivalent BSD et macOS d'epoll — même conception, interface différente.
Une pile de conteneurs qui se surveille
Le projet de conteneurisation se fait d'ordinaire avec trois services. Celui-ci en fait tourner neuf : NGINX terminant le TLS comme unique point d'entrée public, WordPress sur php-fpm, MariaDB pour la persistance, Redis pour le cache, FTP et Adminer pour l'administration des fichiers et de la base, et Prometheus avec Node Exporter et Grafana pour les métriques — plus un gestionnaire de sauvegardes que j'ai écrit moi-même, une petite application React et Flask qui capture les fichiers WordPress et la base.
La contrainte qui rend l'exercice instructif est l'interdiction des images applicatives prêtes à l'emploi. Chaque image est construite depuis une distribution de base avec son propre point d'entrée : vous écrivez donc vous-même la supervision des processus, l'ordre de démarrage et la santé de chaque service. La persistance repose sur des volumes nommés et les services communiquent sur un réseau privé : rien n'est joignable autrement que par le proxy.
Puis retirer l'humain du déploiement
Faire tourner cette pile sur son poste prouve qu'elle fonctionne. La poser sur un serveur cloud sans toucher au serveur est un autre problème — c'est le rôle de la couche Ansible : un playbook, exécuté contre des droplets définis dans un inventaire, qui mène d'un serveur nu à une pile en service.
Le provisionnement suit l'ordre qui compte. Le rôle pare-feu installe UFW, passe la politique d'entrée par défaut à « refuser » et ouvre exactement trois ports. Le rôle Docker purge les paquets conflictuels, importe la clé de signature officielle et installe le moteur et le plugin compose depuis le dépôt de l'éditeur plutôt que celui de la distribution. La pile est ensuite transférée, son fichier d'environnement rendu depuis un modèle avec des permissions restrictives, puis chaque conteneur démarré et vérifié — le playbook affirme que le conteneur tourne réellement au lieu de supposer que la commande de démarrage ayant réussi suffit.
Le détail à relever concerne les secrets : le mot de passe root de la base vit dans un coffre chiffré et n'est injecté qu'au rendu, de sorte que le dépôt est publiable et que l'identifiant n'y figure pas.
Le C en dessous de tout cela
Trois projets de plus se trouvent sous les précédents, et ce sont eux qui rendent le reste possible. Une simulation du dîner des philosophes en C, qui est en réalité un exercice de threads, de mutex et d'acceptation qu'un interblocage non reproductible est toujours là. Un shell Unix, c'est-à-dire fork et exec, des tubes, des descripteurs de fichiers et la gestion des signaux — et qui apprend ce que votre terminal faisait pour vous depuis toujours. Et un moteur de raycasting qui rend une vue en première personne en temps réel depuis une grille : de l'arithmétique, un framebuffer, et aucun moteur pour aider.
Aucun n'est un produit. Ils sont la raison pour laquelle un conteneur, une limite de processus ou un descripteur bloqué sont des choses sur lesquelles je raisonne concrètement plutôt que par analogie.
Réalisé avec
- C++98
- C
- kqueue
- Docker Compose
- NGINX
- Ansible
- Prometheus
- Grafana
Projets de cursus, publics en sources. Le serveur HTTP cible BSD et macOS, car il est bâti sur kqueue.