À la base j’étais en train de répondre à l’email «Longévité des OS»… et puis en me relisant j’ai noté que ma réponse était un peu hors sujet: désolé :-)
Voici un petit retour d’expérience de plus de 15 ans avec un parc d’environ 15 000 machines physiques actuellement réparties dans le monde entier pour du CDN vidéo.
Le problème de la gestion de la durée de vie de l’OS en production a été résolu en passant en mode «rolling release».
Le concept de montée de version est donc une tâche comme une autre, surtout quand la vie de la version en production n’est que de 4 semaines maximum.
Pourquoi 4 semaines ? Car on met 4 semaines à mettre l’ensemble du parc à jour, et dès qu’une version est déployée on passe à la suivante. On se permet une pause pendant les fêtes de fin d’année.
L' équipe «ops» est composée de moins de 8 personnes, mais en réalité c’est uniquement 1 seule personne (celle d’astreinte) qui gère l’ensemble du parc pendant sa semaine d’astreinte.
Les 7 autres pendant ce temps, ils sont soit en vacances soit en train de coder les outils d’automatisation de leurs tâches, pour pouvoir survivre à leur prochaine semaine d'astreinte.
Et donc pour la mise à jour de l’ensemble du parc, la personne «on duty» lance un script, qui va se charger de mettre l’ensemble des machines, par groupe (un seul membre de chaque cluster à la fois par exemple pour ne pas perturber le service). Et ceci va se dérouler sur environ 4 semaines, pour laisser le temps de détecter un problème et de mettre en pause le déploiement en cas de découverte de problème de dernière minute.
Pour arriver à cela, le principe KISS est prioritaire sur l’ensemble du reste (pas de documentation par exemple: un nouvel arrivé dois être capable de comprendre comment cela fonctionne en lisant le code qui doit donc rester simple.
Pour cela, voici ce qui a été choisi:
- Pour l’OS il faut un truc simple qui offre tout l’outillage pour s’autoconstruire intégralement depuis ses sources: du FreeBSD;
- Pour les applications, l’arbre des ports FreeBSD dispose du reste (ici c’est du nginx pour l’essentiel).
- Et pour le processus de MaJ c’est la fonctionnalité Boot-Environment de ZFS est utilisée. On compile une sorte de «firmware» (OS+applications) qui est déployé sur un dataset ZFS et on indique au système de démarrer sur ce nouveau dataset. En cas de problème lors du démarrage, il va redémarrer automatiquement sur l’ancien. À par les fichiers de configuration du système (merci le concept POLA de FreeBSD), rien n’est utilisé de l’ancien dataset. Les disques qui stockent le contenu, eux, sont en UFS et ne sont pas touchés par ces mises à jour.
- Et toutes les 4 semaines, on synchronise notre version interne avec les dernières versions disponibles. Pas les branches de «production», mais les branches de «dévelopement», c’est trop facile sinon.
- Et tous les jours ou presque, on pousse nos contributions vers les projets open source utilisés, ce qui simplifie énormément le merge de notre branche interne lors de nos synchros.
La tâche de créer ce firmware est dédiée à l’équipe «dev OS»: Moins de 10 personnes aussi, mais c’est beaucoup car il y a un gros travail d'optimisation (cf les conférences de Drew Gallatin par exemple), mais ça, c'est pour nous permettre d’acheter les machines les moins chères, et donc de mettre plus d’argent dans la création de contenu.
Et maintenant avec ça il faut un système de test de régression aux petits ognons… ha ben cela tombe bien, c’est aussi inclus avec FreeBSD qui embarque plus de 9000 tests de régression (cela va du kernel aux outils userland).
Exemple des rapports de tests FreeBSD en ligne:
Ces tests de régression sont lancés sur des VMs ici, puis tous les jours on lance un test A/B de charge réelle.
Mais il nous est très compliqué de simuler en labo la diversité des équipements de nos clients et leur réseau domestique.
Alors pour nous aider l’équipe «dev client», celle qui code le client qui tourne dans vos télés, smartphones, consoles, etc. a fait du bon boulot: Le logiciel ouvre et supervise plusieurs sessions vers plusieurs serveurs pour basculer le plus rapidement vers un autre serveur en cas de problème.
Et grâce à cette robustesse notre domaine de jeu s’étends… à toute la production :-)
On peut redémarrer un serveurs en pleine charge sans aucun problème (et on en profite). Bon, cela n’est plus très vrais avec nos prototypes 400Gb/s et 800Gb/s: L’impact est un peu trop visible sur certains liens Internet.
Donc tous les soirs, on passe une partie de la production sur la version «du jour». C’est la version jeune de quelques heures qui a passée les tests de régression en VM.
Cette version est déployée sur une 50aine de serveurs qui disposent d’un double pratiquement identique. C'est-à-dire à la même hauteur dans le rack d'à côté pour essayer d’avoir les températures/vibrations/etc. les plus comparables.
Le lendemain, après environ 12 heures de charge, on reçoit des raports d’analyses statistiques des différences entre les 2 groupes.
Et là, on compare tout ce que l’on peut: consommation électrique, température des SFP, nombre d’IO disques, charge CPU par processus, etc. En plus des données provenant des serveurs on dispose aussi de la comparaison des stats remontées par les logiciels clients qui se sont connectés sur chacun de ces 2 groupes (utile par exemple pour découvrir que l’on a cassé le TLS sur une famille de matériel clients).
Et après 4 semaines d’itération la version «du jour - 1» est sélectionnée pour être la version «production» et débute son déploiement sur l’intégralité de la production.
Pour le détail technique de la gestion des branches, cf une ancienne présentation du manager de l’équipe:
En cas de problème ou patch de sécurité à déployer rapidement, le processus est le même: On applique le patch et on reconstruit un nouveau firmware.
Bref, pour résumer:
- du KISS dans les équipes (il n’existe pas de poste «chef de projet» par exemple), dans les process et dans les choix techniques ;
- Quand on a peur d’une tâche comme la montée de version, le plus simple est d’en faire tous les jours ;-)
Salutations,
Olivier