virli/tutorial/devops/devops.md

10 KiB

\newpage

Le mouvement DevOps

Jusqu'à récemment, et encore dans de nombreuses entreprises, les développeurs et les administrateurs système faisaient partie de deux équipes différentes : les uns développant sur leurs machines avec les dernières bibliothèques, utilisant les derniers frameworks à la mode, sans se préoccuper de la sécurité (ils travaillent en root ou avec sudo ;)), tandis que les autres tentaient tant bien que mal de déployer ces services avec les contraintes opérationnelles en tête.
Ces contraintes : tant liées à la sécurité (il faut s'assurer qu'un service n'utilise pas une bibliothèque vulnérable par exemple, donc soit utilisé sur un système à jour, et qu'il ne tourne pas en root), qu'à la disponibilité (si le service est mal codé est contient beaucoup de fuites mémoire, il ne faut pas que les autres services présents sur la même machine en pâtissent).

Une guerre faisait donc rage entre les développeurs qui ne comprenaient pas que les administrateurs système ne pouvaient pas maintenir autant de versions d'une bibliothèque qu'il y avait de services : par exemple dans le cas de plusieurs services en PHP, on pouvait leur demander de déployer des applications utilisant la version 5.6, et la 7.2 pour d'autres, ... lorsqu'il y avait des incompatibilités mineures et plus personne pour s'occuper de la maintenance d'un vieux service toujours utilisé.

Le même principe est aussi valable pour Python, Ruby, ... : les développeurs ont toujours eu tendance à vouloir utiliser les dernières améliorations d'un langage, mais les administrateurs système n'ont alors pas de paquets stables dans la distribution. En effet, les distributions stables telles que Debian, RedHat ou CentOS ont des cycles de vie assez long et se concentrent plus sur la stabilité.
Cette stabilité est obtenue grâce à l'utilisation de versions éprouvées des langages et des bibliothèques, qui assurent un temps de maintenance et de recherche de bugs réduit aux équipes opérationnelles. Si un projet fonctionne bien avec une version donnée d'une de ces distributions, on peut être assez confiant sur le fait que ce sera toujours le cas (du moins tant que la distribution assure le support de sa version). \

Le but du DevOps est donc de retrouver une certaine fluidité entre le développement et l'exploitation. Il s'agit d'un mouvement qui vise à ce que les développeurs, sans avoir à gérer au quotidien la maintenance des serveurs de production, soient davantage impliqués dans les opérations de déploiement. Cela passe notamment par la prise en compte de l'environnement de déploiement dès la phase de conception du projet, puis dès les premiers développements, des tests automatisés sont réalisés directement dans un environnement proche de la production.

Il en résulte moins de friction entre les deux équipes. Les développeurs étant par ailleurs amenés à écrire des recettes de déploiement, tels que des playbooks Ansible ou bien encore des conteneurs Docker. \

Chez Google (et d'autres entreprises qui ont depuis repris l'idée), des équipes sont chargées de développer la fiabilité des systèmes d'information de production. Ce sont les équipes SRE, pour Site Reliability Engineering. On confie alors complètement la responsabilité de l'environnement de production aux développeurs qui sont chargés de l'automatiser. Au-delà de l'automatisation des déploiements de services, il s'agit ici de développer des mécanismes permettant au système de réagir face aux situations telles que les montées en charges, les pannes, ...

::::: {.warning} Attention par contre aux entreprises qui recrutent un profil DevOps, car cela a autant de sens que recruter un développeur Scrum ou un développeur cycle en V : DevOps est une méthodologie. Les entreprises qui recrutent un DevOps recherchent généralement quelqu'un qui fera à la fois du développement logiciel d'un côté et de l'administration système de l'autre : une situation généralement assez difficile à vivre. Alors qu'au contraire, la mouvance DevOps doit être prise au sérieux par l'ensemble des développeurs. Lors d'un entretien d'embauche pour ce genre de poste, assurez-vous bien de ne pas être le seul à faire du DevOps. :::::

Intégration continue

L'intégration continue est la première brique à mettre en place : le but est de compiler automatiquement chaque commit dans un environnement proche de celui de production, puis de lancer les suites de tests du logiciel.

Cela permet de détecter les problèmes au plus tôt dans le cycle de développement, mais cela permet également d'améliorer la qualité du code sur le long terme, car on peut y ajouter facilement des outils qui vont se charger automatiquement de réaliser des analyses : cela peut aller de la couverture des tests, à de l'analyse statique ou dynamique de binaire, en passant par la recherche de vulnérabilités ou de mauvaises pratiques de programmation.

À la fin du processus, il est courant d'exporter les produits de compilation (tarballs, paquets, ISO, conteneurs, ...) ainsi que les journaux et rapports vers un dossier accessible. Cela permet ainsi aux développeurs de voir les problèmes et de pousser les analyses avec leurs propres outils.

Sans déploiement continu (la section suivante), c'est également ces produits de compilation que les administrateurs système vont déployer sans peine, lorsque les développeurs considéreront avoir atteint un jalon, une version stable.

Déploiement continu

Une fois tous les tests passés et les objets produits (on parle d'artifact ou d'assets), il est possible de déclencher un déploiement : il s'agit de rendre accessible aux utilisateurs finaux le service ou les objets.

Dans le cas d'un programme à télécharger (Python, VLC, MariaDB, ...), on va placer les paquets sur le site internet, éventuellement mettre à jour un fichier pointant vers la dernière version (pour que les utilisateurs aient la notification).

Ou bien dans le cas d'un service en ligne (GitHub, Netflix, GMail, ...), il s'agira de mettre à jour le service.

Parfois les deux seront à faire : à la fois publier un paquet ou un conteneur et mettre à jour un service en ligne : par exemple, le serveur Synapse du protocole de messagerie Matrix ou encore Gitlab, tous deux publient des paquets à destination de leurs communautés, et mettent à jour leur service en ligne.\

Il existe pour cela de très nombreuses stratégies : lorsque l'on n'a pas beaucoup de trafic ni beaucoup de machines, on peut simplement éteindre l'ancien service et démarrer le nouveau, si ça prend quelques millisecondes en étant automatisé, cela peut être suffisant compte tenu du faible trafic.

Lorsque l'on a un trafic élevé, de nombreux clients et donc que le service est réparti sur plusieurs machines, on ne peut pas se contenter de tout éteindre et de tout rallumer. Déjà parce que trop de visiteurs vont se retrouver avec des pages d'erreur, et aussi parce qu'en cas de bug logiciel qui n'aurait pas été vu malgré les étapes précédentes, cela pourrait créer une situation catastrophique (imaginez qu'on ne puisse plus valider une commande sur Amazon à cause d'une ligne commentée par erreur !).
On va donc privilégier un déploiement progressif de la nouvelle version (que l'on va étendre sur plusieurs minutes, heures ou mêmes jours), en éteignant tour à tour les instances, et en veillant à ce que les métriques (voir la section suivante !) soient constantes.

Monitoring et supervision

Une fois déployé, le service peut avoir des ratés, alors il convient de le surveiller afin d'être le plus proactif possible dans la résolution des problèmes. La pire situation est celle dans laquelle c'est un utilisateur qui nous informe d'un problème... (sur Twitter !?)

Nous avons réalisé précédemment une partie collecte de métriques, avec nos conteneurs TICK. Nous n'allons donc pas nous en occuper aujourd'hui. \

Notez tout de même qu'il y a deux grandes catégories de logiciels de supervision :

Basée sur des états comme Nagios, Zabbix, ... : ces logiciels vont simplement réaliser des séries de tests définis, à intervalles réguliers et contacter l'administrateur d'astreinte dès qu'un test ne passe plus de manière persistante.

Il y a rarement beaucoup d'intelligence ou d'anticipation automatique dans ces outils. \

Basée sur les métriques comme ELK, Prometheus, InfluxDB, ... : dans la stack TICK que nous avons mis en place précédemment, nous avions placé un agent sur la machine que nous souhaitions analyser. Outre les graphiques présentés dans Chronograf, le dernier outil que l'on n'avait pas configuré était Kapacitor, qui permet après avoir analysé les données, d'alerter en fonction d'une évolution.

L'instrumentation d'une application est une bonne manière de faire remonter des métriques (combien de clients actuellement connectés, combien de messages/transactions traités, ...). Ce sont autant d'informations que l'on peut faire remonter dans sa base de données de métriques. \

La différence entre les deux techniques est que nagios va vous alerter à partir d'un certain seuil que vous aurez préalablement défini (s'il reste moins de 10 % d'espace disque par exemple), tandis que Kapacitor va tenter d'interpréter les indicateurs (et donc vous alerter seulement si la courbe représentant l'espace disque disponible augmente de telle sorte qu'il ne reste plus que quelques heures avant d'être saturé).

Sur la base de ces indicateurs, il est possible d'engager des opérations automatiques, comme par exemple la provision de nouvelles machines pour épauler un service distribuable, qui est proche de la surcharge, acheter de l'espace de stockage supplémentaire auprès du fournisseur, ... \

Enfin, citons le Chaos Monkey, conçu par Netflix, qui est un programme qui va casser de manière aléatoire des éléments de l'environnement de production. Le but est de provoquer sciemment des pannes, des latences, ... à n'importe quel niveau du produit, afin d'en tester (brutalement certes) sa résilience. Cela oblige les développeurs, les opérationnels et les architectes à concevoir des services hautement tolérant aux pannes, ce qui fait que le jour où une véritable panne survient, elle n'a aucun impact sur la production (enfin on espère !).