<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Linux on Zwindler's Reflection</title><link>https://blog.zwindler.fr/tags/linux/</link><description>Recent content in Linux on Zwindler's Reflection</description><generator>Hugo -- gohugo.io</generator><language>fr</language><copyright>Licensed under CC BY-SA 4.0</copyright><lastBuildDate>Fri, 13 Feb 2026 18:00:00 +0200</lastBuildDate><atom:link href="https://blog.zwindler.fr/tags/linux/index.xml" rel="self" type="application/rss+xml"/><item><title>Touraine Tech 2026 - Récap du jour 2</title><link>https://blog.zwindler.fr/2026/02/13/recap-touraine-tech-2026-jour2/</link><pubDate>Fri, 13 Feb 2026 18:00:00 +0200</pubDate><guid>https://blog.zwindler.fr/2026/02/13/recap-touraine-tech-2026-jour2/</guid><description>&lt;img src="https://blog.zwindler.fr/2026/02/tnt26-entree2.webp" alt="Featured image of post Touraine Tech 2026 - Récap du jour 2" /&gt;&lt;h2 id="jour-2---cest-reparti-"&gt;Jour 2 - C&amp;rsquo;est reparti !
&lt;/h2&gt;&lt;p&gt;Me voici dans le train du retour et je prend un peu de temps pour mettre en forme mes notes de la journée. C&amp;rsquo;est parti pour le récap du jour 2 de Touraine Tech 2026 !&lt;/p&gt;
&lt;p&gt;Après une soirée speakers très sympa dans un bar à jeux, je me suis levé un poil trop tard et j&amp;rsquo;ai loupé la keynote&amp;hellip; Dommage 😅.&lt;/p&gt;
&lt;h2 id="lorsquun-simple-bug-réseau-vous-emmène-dans-les-entrailles-de-linux"&gt;Lorsqu&amp;rsquo;un simple bug réseau vous emmène dans les entrailles de Linux
&lt;/h2&gt;&lt;p&gt;Florian Forestier nous a raconté une histoire de debugging &lt;strong&gt;épique&lt;/strong&gt;.&lt;/p&gt;
&lt;img src="https://blog.zwindler.fr/2026/02/tnt26-kernel.avif"
alt="Talk debugging kernel Linux"
loading="lazy"
decoding="async"&gt;
&lt;p&gt;Le contexte : une équipe de 3 devs en mode &amp;ldquo;You build it, you run it&amp;rdquo;, avec une stack Golang/Svelte. Tout va bien, quand soudain arrive un manager qui dit &amp;ldquo;ça marche PAS&amp;rdquo;. La PKI est en panne, sur du hardware custom&amp;hellip; provenant de matériel reconditionné tchèque (pour la modique somme de 200k€ tout de même).&lt;/p&gt;
&lt;p&gt;Le matériel incriminé : des DL380 Gen 10 avec des cartes QLogic FastlinQ 45000. Il y en a 8, et aucune ne fonctionne.&lt;/p&gt;
&lt;p&gt;L&amp;rsquo;enquête commence :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Les cartes sont visibles dans le BIOS ✓&lt;/li&gt;
&lt;li&gt;&lt;code&gt;lspci&lt;/code&gt; les détecte ✓&lt;/li&gt;
&lt;li&gt;Mais &lt;code&gt;ip link&lt;/code&gt; ne les voit pas ✗&lt;/li&gt;
&lt;li&gt;&lt;code&gt;dmesg&lt;/code&gt; affiche des erreurs sur les drivers &lt;code&gt;qed&lt;/code&gt;/&lt;code&gt;qede&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Testé avec Ubuntu, CentOS, Alpine Linux -&amp;gt; KO partout. Impossible d&amp;rsquo;avoir des drivers pour des kernels récents compatibles avec Proxmox.&lt;/p&gt;
&lt;p&gt;Après une semaine d&amp;rsquo;échecs collectifs, Florian a une &amp;ldquo;idée à la con&amp;rdquo; : installer une vieille Ubuntu 18.04. Moi ça me fait rire, parce que j&amp;rsquo;aurais commencé par là ! Quand on a du vieux matériel, on teste avec un OS contemporain du matériel.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Bingo !&lt;/strong&gt; Ça fonctionne.&lt;/p&gt;
&lt;p&gt;À partir de là, investigation par dichotomie : Debian 12 avec le kernel 4.15 de Ubuntu -&amp;gt; OK. Bug présent en 4.17, absent en 4.16, puis rechercher le commit dans les modifications sur les pilotes qed/qede.&lt;/p&gt;
&lt;p&gt;La solution : un code &amp;ldquo;non supporté&amp;rdquo; pas pris en compte dans une fonction ajoutée en 4.16. &lt;strong&gt;3 lignes de fix.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Pour reverser le correctif dans le kernel Linux, il a fallu écrire sur la bonne mailing-list, avec ses 8 pages de règles. 3 semaines entre l&amp;rsquo;envoi du mail et le merge (habituellement 1-2 semaines).&lt;/p&gt;
&lt;p&gt;Un beau REX de debugging bas niveau ! J&amp;rsquo;étais vraiment content de l&amp;rsquo;avoir vu :).&lt;/p&gt;
&lt;h2 id="lampoule-qui-en-savait-trop--voyage-au-cœur-de-la-sécurité-des-objets-connectés"&gt;L&amp;rsquo;ampoule qui en savait trop : voyage au cœur de la sécurité des objets connectés
&lt;/h2&gt;&lt;p&gt;Paul Pinault nous a plongé dans le monde de la sécurité IoT.&lt;/p&gt;
&lt;img src="https://blog.zwindler.fr/2026/02/tnt26-iot.avif"
alt="Talk sécurité IoT"
loading="lazy"
decoding="async"&gt;
&lt;p&gt;Quelques chiffres pour poser le contexte : &lt;strong&gt;300 millions d&amp;rsquo;ampoules connectées&lt;/strong&gt; vendues chaque année, dont 60% en WiFi (vs Zigbee/ZWave). Et côté réglementation, ça bouge :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;RED&lt;/strong&gt; (août 2025) : garantie sécurité cyber EN18031, mises à jour possibles et sécurisées, communications chiffrées, données personnelles nettoyées, plus de mots de passe par défaut&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Cyber Resilience Act&lt;/strong&gt; (2026-2027) : SBOM obligatoire, MAJ pendant 10 ans minimum&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Paul a donc disséqué (à la DREMMEL 🤣) une ampoule connectée équipée d&amp;rsquo;un ESP32-U4WD, avec ses 2 oscillateurs RTC/horloge et son eFuse, pour voir s&amp;rsquo;il pouvait la compromettre.&lt;/p&gt;
&lt;p&gt;Les vecteurs d&amp;rsquo;attaque analysés :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Port série et JTAG&lt;/strong&gt; : désactivés post-usine&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Pairing WiFi&lt;/strong&gt; : pas RED-compliant (HTTP car pas d&amp;rsquo;Internet au moment du pairing = pas de certificat, WiFi ouvert)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;BLE Pin&lt;/strong&gt; : pas possible sur une ampoule&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;BLE pairing&lt;/strong&gt; : la voie privilégiée&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Point rigolo : pour que les télécommandes soient CRA/RED compliant, l&amp;rsquo;ampoule doit aussi devenir une gateway BLE vers Internet (sinon, pas de mise à jour).&lt;/p&gt;
&lt;h2 id="au-secours--mes-images-pourrissent-mes-perfs"&gt;Au secours ! Mes images pourrissent mes perfs
&lt;/h2&gt;&lt;p&gt;Antoine Caron et Mathieu Mure nous ont parlé d&amp;rsquo;un sujet crucial pour les performances web : les images.&lt;/p&gt;
&lt;img src="https://blog.zwindler.fr/2026/02/tnt26-images.avif"
alt="Talk optimisation images web"
loading="lazy"
decoding="async"&gt;
&lt;p&gt;Un peu d&amp;rsquo;histoire&amp;hellip; En &lt;strong&gt;1992&lt;/strong&gt;, la toute première image est affichée sur le web : &lt;a class="link" href="https://www.letemps.ch/culture/musiques/y-trente-ans-web-souvrait-musique-geneve" target="_blank" rel="noopener"
&gt;les Cernettes (du CERN, évidemment)&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Aujourd&amp;rsquo;hui, 99.9% des sites web ont au moins 1 image, et 68% des pages mobiles ont leur LCP (Largest Contentful Paint) lié à une image.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Le royaume des formats&lt;/strong&gt; :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Morts/vieillissants : BMP, GIF, JPEG, PNG&lt;/li&gt;
&lt;li&gt;Modernes : WebP, AVIF, SVG, JPEG XL&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Après une chouette explication de comment ça fonctionne &amp;ldquo;en théorie&amp;rdquo;, Antoine et Mathieu nous on montré qu&amp;rsquo;à compression égale, les formats récents prennent moins de place, mais surtout, affichent des artefacts visuels bien moindres dans les hauts niveaux de compression (notamment AVIF).&lt;/p&gt;
&lt;p&gt;Les bonnes pratiques présentées :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Taille adaptative&lt;/strong&gt; avec &lt;code&gt;srcset&lt;/code&gt; pour laisser le navigateur choisir la meilleure taille&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Balises &lt;code&gt;&amp;lt;picture&amp;gt;&lt;/code&gt;&lt;/strong&gt; avec plusieurs &lt;code&gt;&amp;lt;source&amp;gt;&lt;/code&gt; pour gérer différents formats&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;fetchpriority=&amp;quot;high&amp;quot;&lt;/code&gt;&lt;/strong&gt; au-dessus de la ligne de flottaison&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;loading=&amp;quot;lazy&amp;quot;&lt;/code&gt;&lt;/strong&gt; en dessous&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Sharp&lt;/strong&gt; en JS pour le traitement côté serveur&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Git LFS&lt;/strong&gt; pour éviter de commit des fichiers lourds&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Cache de build&lt;/strong&gt; pour éviter de reconstruire chaque image à chaque CI&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Bref, j&amp;rsquo;ai du boulot sur ce blog (je le savais&amp;hellip;).&lt;/p&gt;
&lt;h2 id="makers-de-père-en-fils"&gt;Makers de Père en Fils
&lt;/h2&gt;&lt;p&gt;Matthias et Sylvain Gougouzian nous ont présenté un talk bonbon sur leurs projets makers en famille.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.zwindler.fr/2026/02/tnt26-makers.avif"
alt="Talk Makers de Père en Fils"
loading="lazy"
decoding="async"&gt;
Un duo pétillant, pour ne pas dire explosif 😂 ! Matthias (le fils) est super cash (pour rester poli), c&amp;rsquo;était très rigolo à voir.&lt;/p&gt;
&lt;p&gt;L&amp;rsquo;idée de Sylvain : initier ses enfants à l&amp;rsquo;électronique, comme nous à l&amp;rsquo;époque en cours de techno. Objectif : faire 1 à 2 projets par an ensemble.&lt;/p&gt;
&lt;p&gt;Après découverte de &lt;strong&gt;Scratch&lt;/strong&gt; (apprendre le code par blocs), &lt;strong&gt;Pyrates&lt;/strong&gt; (approfondir avec Python), &lt;strong&gt;Micro:Bit&lt;/strong&gt; (code visuel avec accéléromètres et boutons), &lt;strong&gt;TinkerCAD&lt;/strong&gt; (conception 3D de projets physiques), Sylvain s&amp;rsquo;est dit que c&amp;rsquo;était le moment de passer à un vrai projet DE ZERO. Recréer un équivalent &lt;a class="link" href="https://nabaztag.com/" target="_blank" rel="noopener"
&gt;du Nabaztag&lt;/a&gt; !&lt;/p&gt;
&lt;p&gt;Ils ont utilisé la méthode &lt;strong&gt;MoSCoW&lt;/strong&gt; pour prioriser :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Must have&lt;/strong&gt; : Météo (LEDs), Moteurs&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Should have&lt;/strong&gt; : Écran, GreenIT&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Could have&lt;/strong&gt; : Micro, HP, Carte SD&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Won&amp;rsquo;t have&lt;/strong&gt; : Bourse, Traffic&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Choix techniques : ESP32/Raspberry Pico avec MicroPython.&lt;/p&gt;
&lt;p&gt;Le moment touchant du talk : apprendre à se dire les choses. Matthias n&amp;rsquo;osait plus parler à son père quand une tâche était trop grosse, par peur de décevoir. C&amp;rsquo;est un point qu&amp;rsquo;en tant que parent, on peut trop facilement oublier&amp;hellip;&lt;/p&gt;
&lt;p&gt;Une fois les problèmes de communication réglé, ils ont pu découper en étapes : PoC d&amp;rsquo;abord (NeoLED, écran, servomoteur, bouton, carte microSD), puis passage au MVP avec la forme physique sur TinkerCAD.&lt;/p&gt;
&lt;p&gt;Un bel exemple de transmission intergénérationnelle.&lt;/p&gt;
&lt;h2 id="another-world-une-belle-leçon-darchitecture-logicielle"&gt;Another World, une belle leçon d&amp;rsquo;architecture logicielle
&lt;/h2&gt;&lt;p&gt;Olivier Poncet nous a fait découvrir les entrailles d&amp;rsquo;un jeu cultissime (bon, moi je le connaissais pas 🫣) : Another World.&lt;/p&gt;
&lt;img src="https://blog.zwindler.fr/2026/02/tnt26-anotherworld.avif"
alt="Talk Another World"
loading="lazy"
decoding="async"&gt;
&lt;p&gt;Un talk que je voulais voir depuis longtemps, mais comme je savais que je le verrai à TNT26, j&amp;rsquo;avais décidé de ne pas regarder le replay !&lt;/p&gt;
&lt;p&gt;Another World, c&amp;rsquo;est un jeu vidéo d&amp;rsquo;aventure/action cinématique sorti en 1991, fait par &lt;strong&gt;une seule personne&lt;/strong&gt; (sauf la musique) : Eric Chahi, pionnier du jeu vidéo français des années 80-90.&lt;/p&gt;
&lt;p&gt;Les specs impressionnantes :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Exécutable de &lt;strong&gt;24 Ko&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Assets de 1.2 Mo (images et sons)&lt;/li&gt;
&lt;li&gt;Un moteur graphique polygonal 2D (pour les animations fluides et séquences cinématiques)&lt;/li&gt;
&lt;li&gt;Un moteur sonore 4 pistes PCM&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Une machine virtuelle&lt;/strong&gt; pour tout gérer !&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Le matériel de l&amp;rsquo;époque : Amiga 500 avec 1 Mo de RAM et un HDD de 20 Mo, augmenté d&amp;rsquo;un Genlock (caméscope/magnétoscope) et d&amp;rsquo;un magnétophone. Eric Chahi a créé ses propres outils en GFA Basic. Il a utilisé la &lt;strong&gt;rotoscopie&lt;/strong&gt; : capturer une image vidéo, détourer les assets pour créer les animations. Toutes les peintures et graphismes sont faits à la main.&lt;/p&gt;
&lt;p&gt;Les données sont compressées avec l&amp;rsquo;algo &lt;strong&gt;ByteKiller&lt;/strong&gt;, répandu sur Amiga, économe en RAM.&lt;/p&gt;
&lt;p&gt;La VM est impressionnante agit comme une vrai machine : &lt;strong&gt;64 threads&lt;/strong&gt;, &lt;strong&gt;256 registres&lt;/strong&gt;, &lt;strong&gt;29 instructions / 200+ opcodes&lt;/strong&gt;. Olivier est rentré dans les détails de l&amp;rsquo;implémentation des opcodes et de leur conception.&lt;/p&gt;
&lt;p&gt;Le moteur vidéo utilise des framebuffers avec 4 pages (2 backgrounds + 2 fenêtres principales, 2 actives et 2 inactives). Les polygones sont hiérarchisés dans des &amp;ldquo;bounding boxes&amp;rdquo; pour gérer l&amp;rsquo;affichage et les collisions. Les backgrounds, trop complexes pour être calculés en temps réel, sont pré-dessinés et mis en &amp;ldquo;cache&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;Difficile de tout retranscrire, Olivier nous a montré 1001 autres annecdotes sur les optimisations et autres astuces malines dans ce jeu. Olivier n&amp;rsquo;avait plus de temps pour nous montrer sa réimplémentation du jeu en C++ (qui fonctionne dans un navigateur avec WASM, si je ne dis pas de bêtises).&lt;/p&gt;
&lt;p&gt;Une vraie leçon d&amp;rsquo;ingénierie avec les contraintes de l&amp;rsquo;époque !&lt;/p&gt;
&lt;h2 id="communauté-et-remerciements"&gt;Communauté et remerciements
&lt;/h2&gt;&lt;p&gt;Comme toujours, le meilleur d&amp;rsquo;une conférence reste les rencontres.&lt;/p&gt;
&lt;p&gt;Je retiens surtout les longues (très longues) discussions avec Horacio et Yannick de Clever Cloud. J&amp;rsquo;ai aussi enfin pris le temps de papoter avec Estelle, Geoffrey, Julien (x3, décidément 🙃), Valentin, Stéphane (x2), Aurélie, Florian, Jérôme, et sûrement plein d&amp;rsquo;autres que j&amp;rsquo;ai oubliés dans le &amp;ldquo;blur&amp;rdquo; de la conférence.&lt;/p&gt;
&lt;img src="https://blog.zwindler.fr/2026/02/tnt26-foues.avif"
alt="Fouées tourangelles partagées lors de la conférence"
loading="lazy"
decoding="async"&gt;
&lt;p&gt;Un grand merci à l&amp;rsquo;équipe d&amp;rsquo;organisation de Touraine Tech pour cette édition 2026 réussie. Le passage sur 2 jours et le changement de lieu ont été de bonnes décisions. À l&amp;rsquo;année prochaine !&lt;/p&gt;</description></item><item><title>Créer un cluster Kubernetes sur Clever Cloud avec les apps Linux</title><link>https://blog.zwindler.fr/2025/07/20/kubernetes-sur-clever-cloud-linux/</link><pubDate>Sat, 19 Jul 2025 13:00:00 +0200</pubDate><guid>https://blog.zwindler.fr/2025/07/20/kubernetes-sur-clever-cloud-linux/</guid><description>&lt;img src="https://blog.zwindler.fr/2025/07/k8s-clever.webp" alt="Featured image of post Créer un cluster Kubernetes sur Clever Cloud avec les apps Linux" /&gt;&lt;h2 id="introduction"&gt;Introduction
&lt;/h2&gt;&lt;p&gt;Après avoir testé les &lt;a class="link" href="https://blog.zwindler.fr/2025/07/07/je-reessaye-les-sites-statiques-chez-clever/" &gt;apps statiques chez Clever Cloud&lt;/a&gt;, j&amp;rsquo;ai voulu pousser plus loin l&amp;rsquo;exploration des nouvelles fonctionnalités.&lt;/p&gt;
&lt;p&gt;Clever Cloud a en effet lancé récemment un nouveau type d&amp;rsquo;application : les &lt;strong&gt;apps Linux&lt;/strong&gt;. Ces dernières permettent de déployer des applications génériques sur une machine Linux, sans runtime prédéfini. Un peu comme avoir sa propre VM, mais managée par Clever Cloud.&lt;/p&gt;
&lt;p&gt;Du coup, pour &amp;ldquo;rigoler&amp;rdquo; (et par pure curiosité technique), j&amp;rsquo;ai décidé de créer un &lt;strong&gt;control plane Kubernetes&lt;/strong&gt; complet sur ce type d&amp;rsquo;instance. Pourquoi ?&lt;/p&gt;
&lt;p&gt;D&amp;rsquo;abord parce que je parle tout le temps de Kubernetes. Et ensuite, pour faire un petit clin d&amp;rsquo;œil aux copains de chez Clever Cloud : ils annoncent depuis des mois leur offre Kubernetes managée qui devrait sortir (soon™).&lt;/p&gt;
&lt;p&gt;Et en poussant les runtimes Linux dans leurs retranchements, ça m&amp;rsquo;a permis de découvrir pas mal de fonctionnalités que (j&amp;rsquo;avoue) je ne connaissais pas chez Clever.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Disclaimer&lt;/strong&gt; : ce projet est purement éducatif et expérimental. Ne l&amp;rsquo;utilisez pas, même pour un usage personnel !&lt;/p&gt;
&lt;h2 id="le-projet--k8s-on-clever-linux"&gt;Le projet : k8s-on-clever-linux
&lt;/h2&gt;&lt;p&gt;J&amp;rsquo;ai créé un dépôt GitHub dédié à ce projet : &lt;a class="link" href="https://github.com/zwindler/k8s-on-clever-linux" target="_blank" rel="noopener"
&gt;k8s-on-clever-linux&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Le principe est simple : déployer tous les composants du control plane Kubernetes (etcd, kube-apiserver, kube-controller-manager, kube-scheduler) comme des processus sur une app Linux Clever Cloud.&lt;/p&gt;
&lt;p&gt;Le projet s&amp;rsquo;inspire fortement de mon tutoriel &lt;a class="link" href="https://github.com/zwindler/demystifions-kubernetes" target="_blank" rel="noopener"
&gt;demystifions-kubernetes&lt;/a&gt;. Et d&amp;rsquo;ailleurs, pour tester le &lt;em&gt;proof of concept&lt;/em&gt;, c&amp;rsquo;est ce que j&amp;rsquo;ai bêtement déroulé, pour valider la faisabilité.&lt;/p&gt;
&lt;p&gt;Cependant, dans le cas de Clever, plutôt que de lancer tous les composants un par un en déroulant un script bash (ce qui est fait dans github.com/zwindler/demystifions-kubernetes), j&amp;rsquo;ai fait un poil plus rusé&amp;hellip;&lt;/p&gt;
&lt;h2 id="découverte-de-mise"&gt;Découverte de Mise.
&lt;/h2&gt;&lt;p&gt;Mais d&amp;rsquo;abord un peu de contexte :&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Clever Cloud platform provides a multi-runtime environment, including many tools to deploy and run your applications. The Linux runtime is a versatile solution to build and deploy any kind of application. The Mise package manager helps you to install and manage any supported dependencies Clever Cloud doesn’t provide by default such as Dart, Gleam, Zig for example.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://www.clever-cloud.com/developers/doc/applications/linux/" target="_blank" rel="noopener"
&gt;Documentation officielle des Linux runtimes chez Clever Cloud&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Déjà, ça parle d&amp;rsquo;un truc qui s&amp;rsquo;appelle &lt;strong&gt;Mise package manager&lt;/strong&gt;. C&amp;rsquo;est quoi ça ?&lt;/p&gt;
&lt;p&gt;Il s&amp;rsquo;agit d&amp;rsquo;un projet de &lt;em&gt;Jeff Dickey&lt;/em&gt; (&lt;a class="link" href="https://jdx.dev/" target="_blank" rel="noopener"
&gt;jdx.dev&lt;/a&gt;). Sur nos apps Linux, ça va nous permettre d&amp;rsquo;installer une partie des dépendances d&amp;rsquo;une part, et d&amp;rsquo;ordonnancer le lancement de commandes pour &lt;em&gt;build&lt;/em&gt;, puis pour &lt;em&gt;run&lt;/em&gt; notre projet dans l&amp;rsquo;instance Linux&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://mise.jdx.dev/dev-tools/" target="_blank" rel="noopener"
&gt;mise.jdx.dev&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="découpage-de-lapplication"&gt;Découpage de l&amp;rsquo;application
&lt;/h2&gt;&lt;p&gt;Maintenant qu&amp;rsquo;on en sait plus, voilà comment j&amp;rsquo;ai découpé l&amp;rsquo;application avec Mise :&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Initialisation (&lt;code&gt;mise.toml&lt;/code&gt;)&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Même si tous les prérequis ne sont pas tous disponibles dans Mise, je peux quand même déléguer le téléchargement d&amp;rsquo;une partie d&amp;rsquo;entre eux, ce qui va alléger le script de téléchargement des dépendances par rapport à &lt;strong&gt;démystifions kubernetes&lt;/strong&gt;. C&amp;rsquo;est toujours bon à prendre :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-toml" data-lang="toml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;tools&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;cfssl&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;latest&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;etcd&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;latest&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;kubectl&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;latest&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;helm&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;latest&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Phase de build (&lt;code&gt;.mise-tasks/build&lt;/code&gt;)&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Télécharge tous les binaires Kubernetes&lt;/li&gt;
&lt;li&gt;Génère les certificats pour l&amp;rsquo;authentification des composants&lt;/li&gt;
&lt;li&gt;Configure les paramètres statiques&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Mise en cache&lt;/strong&gt; : cette phase n&amp;rsquo;est exécutée que lors des changements de code&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;De cette manière, en cas de reboot de l&amp;rsquo;application, on ne perd pas les certificats et on gagne un peu de temps pour le redéploiement.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Phase de run (&lt;code&gt;.mise-tasks/run&lt;/code&gt;)&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Lancer tous les composants de notre control plane Kubernetes&lt;/li&gt;
&lt;li&gt;Génère un bootstrap token pour ajouter des Nodes&lt;/li&gt;
&lt;li&gt;Lance un serveur HTTP qui écoute sur le port 8080 et ne sert&amp;hellip; rien.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Pourquoi un serveur HTTP ? Eh bien tout simplement parce que&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Linux runtime only requires a CC_RUN_COMMAND to execute, with a working web application listening on 0.0.0.0:8080.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Si je ne mets rien en écoute sur le port 8080, Clever va logguer que mon app est en panne (alors que non).&lt;/p&gt;
&lt;h2 id="focus-sur-mise-pour-installer-les-dépendances"&gt;Focus sur Mise pour installer les dépendances
&lt;/h2&gt;&lt;p&gt;Concrêtement, comment ça se présente quand on lance une app dans Clever Cloud avec un mise.toml ?&lt;/p&gt;
&lt;p&gt;Ben tout simplement comme ça :&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;2025-07-20T15:54:04.304Z mise etcd@3.6.2 install
2025-07-20T15:54:05.302Z mise etcd@3.6.2 download etcd-v3.6.2-linux-amd64.tar.gz
2025-07-20T15:54:06.403Z mise etcd@3.6.2 checksum etcd-v3.6.2-linux-amd64.tar.gz
2025-07-20T15:54:06.422Z mise etcd@3.6.2 extract etcd-v3.6.2-linux-amd64.tar.gz
2025-07-20T15:54:06.705Z mise etcd@3.6.2 ✓ installed
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;La liste des tools disponibles avec mise est ici :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://mise.jdx.dev/registry.html" target="_blank" rel="noopener"
&gt;mise.jdx.dev/registry&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Et on peut remarquer que les tools viennent de différentes sources telles qu&amp;rsquo;aqua, pipx, ubi, asdf&amp;hellip; Ça me donne envie de tester ça pour les dépendances qui me manquent donc attendez-vous à un prochain article sur le sujet :).&lt;/p&gt;
&lt;h2 id="mais-ils-sont-où-les-binaires-du-control-plane-de-kubernetes-"&gt;Mais&amp;hellip; ils sont où les binaires du control plane de Kubernetes ?
&lt;/h2&gt;&lt;p&gt;Initialement, j&amp;rsquo;avais mis tout ça dans la phase de &lt;code&gt;run&lt;/code&gt;. Sauf que David m&amp;rsquo;a proposé de découvrir une autre fonctionnalité de Clever Cloud que je n&amp;rsquo;avais jamais utilisée : les Workers.&lt;/p&gt;
&lt;p&gt;Les &lt;strong&gt;Workers&lt;/strong&gt; sont des processus en arrière-plan qui tournent en parallèle de votre application principale.&lt;/p&gt;
&lt;p&gt;Pour notre cluster Kubernetes, c&amp;rsquo;est &lt;strong&gt;parfait&lt;/strong&gt; ! Plutôt que de lancer tous les composants dans un script bash, chaque composant du control plane devient un worker dédié :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Worker 0&lt;/strong&gt;: &lt;code&gt;./run-scripts/start-etcd.sh&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Worker 1&lt;/strong&gt;: &lt;code&gt;./run-scripts/start-kube-apiserver.sh&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Worker 2&lt;/strong&gt;: &lt;code&gt;./run-scripts/start-kube-controller-manager.sh&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Worker 3&lt;/strong&gt;: &lt;code&gt;./run-scripts/start-kube-scheduler.sh&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Worker 4&lt;/strong&gt;: &lt;code&gt;./run-scripts/post-boot.sh&lt;/code&gt; - bootstrap tokens, RBAC, worker scripts&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Avec en bonus la possibilité de configurer le comportement de redémarrage :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;CC_WORKER_RESTART=on-failure&lt;/code&gt; (par défaut) : redémarre seulement en cas d&amp;rsquo;erreur&lt;/li&gt;
&lt;li&gt;&lt;code&gt;CC_WORKER_RESTART=always&lt;/code&gt; : redémarre toujours&lt;/li&gt;
&lt;li&gt;&lt;code&gt;CC_WORKER_RESTART_DELAY=1&lt;/code&gt; : délai en secondes avant redémarrage&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="installation-et-configuration"&gt;Installation et configuration
&lt;/h2&gt;&lt;p&gt;Bon, clairement, cette partie n&amp;rsquo;est pas la plus user-friendly du tutoriel. Si vous voulez plus de détails sur ce qui est fait et pourquoi, vous pouvez aller jeter un œil directement sur le dépôt &lt;a class="link" href="https://github.com/zwindler/k8s-on-clever-linux" target="_blank" rel="noopener"
&gt;github.com/zwindler/k8s-on-clever-linux&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Les grandes étapes sont :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Créer l&amp;rsquo;app Linux &lt;code&gt;clever create --type linux --github zwindler/k8s-on-clever-linux&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Configuration de la redirection TCP&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;Linux runtime only requires a CC_RUN_COMMAND to execute, with a working web application listening on 0.0.0.0:8080.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Pour rappel, Clever Cloud s&amp;rsquo;attend à ce qu&amp;rsquo;on expose une app en HTTP non sécurisé sur le port 8080. Sauf que moi, je veux exposer l&amp;rsquo;API server Kubernetes en HTTPS. On va donc activer la &amp;ldquo;redirection TCP&amp;rdquo; : Clever Cloud attribue un port aléatoire (dans les 5XXX) qui redirige vers le port 4040 de votre application (et donc je dois dire à l&amp;rsquo;API server de ne pas écouter sur le 6443, mais 4040) :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ clever tcp-redirs add --namespace default
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Successfully added tcp redirection on port: &lt;span class="m"&gt;5131&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;Configuration du domaine&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Une fois le port TCP connu, on peut configurer notre domaine.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;clever domain add k8soncleverlinux.domain.org
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Dans mon cas, l&amp;rsquo;API server sera accessible sur le domaine &lt;code&gt;k8soncleverlinux.zwindler.fr&lt;/code&gt; et sur le port &lt;code&gt;5131&lt;/code&gt;. Comme ces deux valeurs seront différentes pour vous, j&amp;rsquo;ai vite codé un script qui permet de prendre les valeurs par défaut pour moi, mais vous permettre de les écraser si vous spécifiez des valeurs sur VOTRE app Clever Cloud :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;clever env &lt;span class="nb"&gt;set&lt;/span&gt; K8S_DOMAIN k8soncleverlinux.zwindler.fr
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;clever env &lt;span class="nb"&gt;set&lt;/span&gt; K8S_TCP_PORT &lt;span class="m"&gt;5131&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;blockquote&gt;
&lt;p&gt;Je suis vraiment sympa.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;Configuration des workers : pour ça j&amp;rsquo;ai fait un script &lt;code&gt;./setup-clever-workers.sh&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Ce script configure 5 workers dont j&amp;rsquo;ai parlé plus haut et qui sont gérés par systemd.&lt;/p&gt;
&lt;h2 id="déploiement-et-test"&gt;Déploiement et test
&lt;/h2&gt;&lt;p&gt;Si tout s&amp;rsquo;est bien passé, l&amp;rsquo;app devrait correctement se lancer, Mise devrait lancer la phase de &lt;code&gt;build&lt;/code&gt; (surtout télécharger les dépendances qui manquent), puis la phase de &lt;code&gt;run&lt;/code&gt; (les dépendances connues de Mise, et les workers une fois que &lt;code&gt;run&lt;/code&gt; se termine) :&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;2025-07-19T13:10:45.130Z Successfully deployed in 0 minutes and 18 seconds
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Les workers en tâche de fond devraient démarrer tous les composants de notre control plane Kubernetes. Au bout de quelques secondes (1 minute max), on devrait avoir un control plane fonctionnel, et tout un tas de certificats et autres secrets.&lt;/p&gt;
&lt;p&gt;Mais comment le tester ? Via SSH sur l&amp;rsquo;instance Clever Cloud ! Car oui, on peut SSH sur cette instance :)&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ clever ssh
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Last login: Fri Jul &lt;span class="m"&gt;18&lt;/span&gt; 20:17:00 UTC &lt;span class="m"&gt;2025&lt;/span&gt; on pts/0
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl version
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Client Version: v1.33.2
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Kustomize Version: v5.6.0
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Server Version: v1.33.2
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;🎉 &lt;strong&gt;Ça marche !&lt;/strong&gt; On a bien un control plane Kubernetes qui tourne sur Clever Cloud !&lt;/p&gt;
&lt;p&gt;Et si vous avez bien travaillé (c&amp;rsquo;est à dire correctement configuré votre domaine et le port), on peut même l&amp;rsquo;utiliser depuis l&amp;rsquo;extérieur en copiant le fichier &lt;code&gt;admin.conf&lt;/code&gt; localement et en modifiant l&amp;rsquo;&lt;code&gt;endpoint&lt;/code&gt; dans le YAML :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl cluster-info
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Kubernetes control plane is running at https://k8soncleverlinux.zwindler.fr:5131
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="ajout-dun-worker-node"&gt;Ajout d&amp;rsquo;un worker node
&lt;/h2&gt;&lt;p&gt;Deuxième hic dans mon histoire. Un control plane sans worker, c&amp;rsquo;est pas terrible.&lt;/p&gt;
&lt;p&gt;Et je ne peux pas utiliser l&amp;rsquo;app de type Linux de chez Clever car je n&amp;rsquo;ai pas assez de privilèges pour changer les options kernel (routage) et installer &lt;strong&gt;containerd&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Mais je n&amp;rsquo;allais pas en rester là. Dans mon projet &amp;ldquo;Démystifions Kubernetes&amp;rdquo;, j&amp;rsquo;installe un worker directement sur la machine du control plane et j&amp;rsquo;utilise le &lt;code&gt;admin.conf&lt;/code&gt; (cluster-admin) pour enrôler l&amp;rsquo;hôte courant en tant que Node.&lt;/p&gt;
&lt;p&gt;C&amp;rsquo;est cracra, mais quand je suis en conf et que j&amp;rsquo;ai 20 minutes pour speedrun, c&amp;rsquo;est acceptable.&lt;/p&gt;
&lt;p&gt;Ici, j&amp;rsquo;ai fait l&amp;rsquo;effort d&amp;rsquo;aller regarder comment faire pour enrôler des Nodes avec un bootstrap token et c&amp;rsquo;est assez intéressant.&lt;/p&gt;
&lt;p&gt;La doc officielle de kube est plutôt bien faite et je ferai peut-être un article à part sur le sujet, c&amp;rsquo;est assez facile en fait, avec un flag à ajouter dans l&amp;rsquo;API server, quelques RBAC et un secret bien spécifique à générer.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://kubernetes.io/docs/reference/access-authn-authz/bootstrap-tokens/" target="_blank" rel="noopener"
&gt;https://kubernetes.io/docs/reference/access-authn-authz/bootstrap-tokens/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Je vous épargne les détails, le projet va générer automatiquement un script pour ajouter des nodes externes :&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;2025-07-19T13:51:47.848Z ✓ Worker setup script generated: setup-worker-node.sh
2025-07-19T13:51:47.849Z 📋 Next steps:
2025-07-19T13:51:47.849Z 1. Copy setup-worker-node.sh to your external worker node
2025-07-19T13:51:47.849Z 2. (Optional) Edit NODE_NAME_OVERRIDE and NODE_IP_OVERRIDE if auto-detection is incorrect
2025-07-19T13:51:47.849Z 3. Ensure your worker node has sudo privileges and internet access
2025-07-19T13:51:47.849Z 4. Run the script on your worker node: sudo ./setup-worker-node.sh
2025-07-19T13:51:47.849Z 5. Check the node joined with: kubectl get nodes
&lt;/code&gt;&lt;/pre&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Script généré automatiquement&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;#!/bin/bash&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# External Worker Node Setup Script for Kubernetes&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;API_SERVER_ENDPOINT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;https://k8soncleverlinux.zwindler.fr:5131&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;BOOTSTRAP_TOKEN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;xxxxxx.xxxxxxxxxxxxxxxx&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ... (configuration complète et certificats/secrets inclus)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Il suffit de copier ce script sur une VM Linux quelconque et de l&amp;rsquo;exécuter. Le script :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Installe containerd, kubelet, kube-proxy&lt;/li&gt;
&lt;li&gt;Configure automatiquement l&amp;rsquo;authentification via bootstrap token&lt;/li&gt;
&lt;li&gt;Démarre les services&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;✓ Worker node setup completed!
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get nodes
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME STATUS ROLES AGE VERSION
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;coucou1 NotReady &amp;lt;none&amp;gt; 13m v1.33.3
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Le node apparaît en &amp;ldquo;NotReady&amp;rdquo; car il manque le plugin CNI. Flannel fonctionne parfaitement :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl apply -f https://github.com/flannel-io/flannel/releases/latest/download/kube-flannel.yml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get nodes
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME STATUS ROLES AGE VERSION
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;coucou1 Ready &amp;lt;none&amp;gt; 30m v1.33.3
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get pods -A
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAMESPACE NAME READY STATUS RESTARTS AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kube-flannel kube-flannel-ds-b65jg 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 14m
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Le &lt;strong&gt;cluster est fonctionnel 😎😎😎 !&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;On a maintenant un cluster Kubernetes complet avec control plane sur Clever Cloud et worker externe&amp;hellip; Avant la sortie du kube managé de Clever.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.zwindler.fr/2025/07/Trollface.avif"
loading="lazy"
&gt;&lt;/p&gt;
&lt;h2 id="limitations-et-évolutions-possibles"&gt;Limitations et évolutions possibles
&lt;/h2&gt;&lt;p&gt;Le worker externe n&amp;rsquo;étant pas dans le réseau Clever Cloud, l&amp;rsquo;API server ne peut pas communiquer avec le kubelet (dans le sens api-server -&amp;gt; kubelet uniquement). Cela limite les fonctionnalités comme &lt;code&gt;kubectl logs&lt;/code&gt;, &lt;code&gt;kubectl exec&lt;/code&gt;, etc. Une solution possible serait d&amp;rsquo;utiliser les &lt;a class="link" href="https://www.clever-cloud.com/developers/doc/develop/network-groups/" target="_blank" rel="noopener"
&gt;Network Groups&lt;/a&gt; de Clever Cloud pour créer un réseau privé sécurisé.&lt;/p&gt;
&lt;p&gt;Si ce projet continue de m&amp;rsquo;amuser, plusieurs améliorations sont envisageables :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;exploration des Network Groups (dont je viens de parler)&lt;/li&gt;
&lt;li&gt;intégration de &lt;a class="link" href="https://github.com/k3s-io/kine" target="_blank" rel="noopener"
&gt;Kine&lt;/a&gt;. Cela permettrait d&amp;rsquo;utiliser les bases de données existantes de Clever Cloud (PostgreSQL, MySQL) comme DB pour Kubernetes, ce qui permettrait éventuellement de rendre cette install &amp;ldquo;HA&amp;rdquo; ce qui serait aussi débile que rigolo&lt;/li&gt;
&lt;li&gt;création des packages aqua/ubi manquants (les binaires de kubernetes et &lt;code&gt;cfssljson&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="conclusion"&gt;Conclusion
&lt;/h2&gt;&lt;p&gt;J&amp;rsquo;ai commencé ce projet comme une blague et j&amp;rsquo;ai finalement mis le doigt dans plein de petites fonctionnalités cools de chez Clever Cloud et dont j&amp;rsquo;ignorais l&amp;rsquo;existence (ou alors, que j&amp;rsquo;avais vu passer mais pas creusé).&lt;/p&gt;
&lt;p&gt;Même si ça m&amp;rsquo;a pris quelques soirées, c&amp;rsquo;était super intéressant. La première itération a été très vite fonctionnelle et je me suis pris au jeu des améliorations successives.&lt;/p&gt;
&lt;p&gt;Le code complet est disponible sur &lt;a class="link" href="https://github.com/zwindler/k8s-on-clever-linux" target="_blank" rel="noopener"
&gt;GitHub&lt;/a&gt; si vous voulez reproduire l&amp;rsquo;expérience ou contribuer !&lt;/p&gt;
&lt;p&gt;Et vous, quels projets fous avez-vous envie de tester avec les apps &lt;strong&gt;Linux&lt;/strong&gt; ? 😄 Moi, j&amp;rsquo;attends mon accès au k8s managé de Clever Cloud maintenant 😝 (comment ça, je suis un gros &lt;em&gt;forceur&lt;/em&gt; ???)&lt;/p&gt;</description></item><item><title>Sécurité des mots de passes ESXi 5.X et 6.X</title><link>https://blog.zwindler.fr/2020/04/06/securite-des-mots-de-passes-esxi-5-x-et-6-x/</link><pubDate>Mon, 06 Apr 2020 06:50:00 +0000</pubDate><guid>https://blog.zwindler.fr/2020/04/06/securite-des-mots-de-passes-esxi-5-x-et-6-x/</guid><description>&lt;img src="https://blog.zwindler.fr/2015/07/vmware2.webp" alt="Featured image of post Sécurité des mots de passes ESXi 5.X et 6.X" /&gt;&lt;h2 id="pourquoi-tu-nous-parles-desxi-5-"&gt;Pourquoi tu nous parles d’ESXi 5 ?
&lt;/h2&gt;&lt;p&gt;En voilà une bonne question ! Comme la majorité des blogueurs tech, j’ai dans mes brouillons une bonne 30aines d’articles en attente depuis plus ou moins longtemps (demandez à &lt;a class="link" href="https://blog.seboss666.info/" target="_blank" rel="noopener"
&gt;Seboss666&lt;/a&gt; ce qu’il en pense).&lt;/p&gt;
&lt;p&gt;Ca fait presque deux ans que je n’ai pas touché à un serveur VMware et pourtant, cette doc était pratiquement &amp;ldquo;prête à poster&amp;rdquo;. Tout comme &amp;ldquo;&lt;em&gt;Intégrer un RHEL 7 dans un Active Directory avec Ansible&lt;/em&gt;&amp;rdquo; et &amp;ldquo;&lt;em&gt;Mise en place de DRBD 8.4 sous CentOS 6.3&lt;/em&gt;&amp;rdquo;, mais c’est une autre histoire&amp;hellip;&lt;/p&gt;
&lt;p&gt;Et comme je n’aime pas gâcher, je &lt;em&gt;&amp;ldquo;profite&amp;rdquo;&lt;/em&gt; du confinement pour déconfiner des vieilles docs avant qu’elles ne soient plus définitivement plus d’actualité (trop tard, &lt;a class="link" href="https://blogs.vmware.com/vsphere/vsphere-7" target="_blank" rel="noopener"
&gt;vSphere 7 vient de sortir&lt;/a&gt;).&lt;/p&gt;
&lt;h2 id="les-mots-de-passe-dans-vsphere"&gt;Les mots de passe dans vSphere
&lt;/h2&gt;&lt;p&gt;Un truc que je n’ai pas trouvé très très clair et qu’il est possible dans VMware d’avoir des comptes utilisateurs internes à l’ESXi avec des mots de passe plutôt bof complexes. En effet, il est tout à fait possible d’avoir un mot de passe avec que des lettres minuscules (voire même des chiffres ??) ce qui -nous sommes d’accord- est absolument catastrophique.&lt;/p&gt;
&lt;p&gt;Lorsqu’on sait qu’on a parfois besoin de se loguer sur la console à distance et que l’émulation des terminaux KVM des constructeurs est une bouse intergalactique qui vous transforme votre AZERTY en un gloubiboulga à mis chemin entre le QWERTY et DVORAK, c’est parfois tentant&amp;hellip;&lt;/p&gt;
&lt;p&gt;Bref, j’ai voulu comprendre la logique de VMware pour l’acceptation de la longueur des mots de passe.&lt;/p&gt;
&lt;p&gt;En fait, tout est expliqué, en fonction des versions, dans ce KB (lien mort, comme tout chez VMware).&lt;/p&gt;
&lt;h2 id="password-quality-control-pam-module"&gt;Password quality-control PAM module
&lt;/h2&gt;&lt;p&gt;Je ne savais pas, mais VMware utilise tout simplement le module PAM &lt;a class="link" href="https://linux.die.net/man/8/pam_passwdqc" target="_blank" rel="noopener"
&gt;Password quality-control PAM&lt;/a&gt;. Il permet de réaliser des contrôles simples sur la qualité des mots de passe choisi pour les utilisateurs Linux.&lt;/p&gt;
&lt;p&gt;Globalement, on dispose, via ce module, de différents flags pour valider une politique simple de gestion de mot de passe sur un système Linux (car oui, ESXi c’est un Linux).&lt;/p&gt;
&lt;p&gt;Les arguments retenus par VMware sont uniquement basés sur une taille minimale de mots de passe en fonction du nombre de type de caractères différents dont dispose ce mot de passe. Voilà à quoi ça ressemble :&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;password requisite /lib/security/$ISA/pam_passwdqc.so retry=N min=N0,N1,N2,N3,N4
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Par défaut, voici ce que vous allez trouver dans vSphere 6 :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;retry=3 : Un utilisateur a droit à trois tentatives pour entrer un mot de passe suffisant.&lt;/li&gt;
&lt;li&gt;N0=12 : Le mot de passe comportant des caractères d’une seule classe doit contenir au moins 12 caractères.&lt;/li&gt;
&lt;li&gt;N1=9 : Le mot de passe comportant des caractères de deux classes doit contenir au moins neuf caractères, mais qui n’est pas éligibles aux conditions des passphrases.&lt;/li&gt;
&lt;li&gt;N2=8 : Le mot de passe respecte les conditions des passphrases. Il comporte des caractères de deux classes et doit contenir au moins huit caractères.&lt;/li&gt;
&lt;li&gt;N3=7 : Le mot de passe comportant des caractères de trois classes doit contenir au moins sept caractères.&lt;/li&gt;
&lt;li&gt;N4=6 : Le mot de passe comportant des caractères des quatre classes doit contenir au moins six caractères.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="procédure-pour-modifier-la-politique-de-sécurité"&gt;Procédure pour modifier la politique de sécurité
&lt;/h2&gt;&lt;p&gt;Si pour une raison ou pour une autre, vous souhaitez modifier ces paramètres (pour les durcir, hein !), voici la marche à suivre :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Connectez-vous au Shell ESXi et obtenez les privilèges root.&lt;/li&gt;
&lt;li&gt;Ouvrez le fichier passwd avec un éditeur de texte.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;vi /etc/pam.d/passwd
&lt;/code&gt;&lt;/pre&gt;&lt;ul&gt;
&lt;li&gt;Modifiez la ligne suivante :&lt;/li&gt;
&lt;/ul&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;password requisite /lib/security/$ISA/pam_passwdqc.so retry=3 min=disabled,20,20,15,10
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Cette commande vous permettra de désactiver la possibilité d’ajouter des utilisateurs dans ESXi dont les mots de passe n’ont qu’une classe de caractères et de complexifier fortement les autres types de mots de passe.&lt;/p&gt;
&lt;p&gt;Il existe de nombreux autres paramètres. Je vous invite à aller lire &lt;a class="link" href="https://linux.die.net/man/8/pam_passwdqc" target="_blank" rel="noopener"
&gt;la page man de ce module&lt;/a&gt; pour améliorer encore la sécurité des mots de passe dans vos ESXi.&lt;/p&gt;
&lt;h2 id="bonus-gui-pour-esxi-60"&gt;Bonus GUI pour ESXi 6.0
&lt;/h2&gt;&lt;p&gt;Si vous êtes allergique à la console jaune et noire d’ESXi (ou que vous n’avez pas la main sur un KVM), sachez que depuis ESXi 6.0, il est possible de modifier directement les valeurs du module PAM depuis la console vSphere. Ça se passe dans les options avancées de l’hôte (cf &lt;a class="link" href="https://www.vladan.fr/esxi-6-0-security-password-complexity-changes/" target="_blank" rel="noopener"
&gt;cet article de Vladan&lt;/a&gt;).&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Password Complexity Rules – change here where In previous versions of ESXi, password complexity changes had to be made by hand-editing the /etc/pam.d/passwd file on each ESXi host. In vSphere 6.0 now this can be done by adding an entry in Host Advanced System Settings, enabling centrally managed setting changes for all hosts in a cluster.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;img src="https://blog.zwindler.fr/2017/12/esxi_cluster3.avif"
loading="lazy"
&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Ouah, cébo !&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="sources"&gt;Sources
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;VMware KB 1012033 (lien mort, comme tout chez VMware)&lt;/li&gt;
&lt;li&gt;Doc vSphere 5, en français (lien mort, comme tout chez VMware)&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://linux.die.net/man/8/pam_passwdqc" target="_blank" rel="noopener"
&gt;Page man de pam_passwdqc&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="http://www.vladan.fr/esxi-6-0-security-password-complexity-changes/" target="_blank" rel="noopener"
&gt;Vladan : ESXi 6.0 Security and Password Complexity Changes&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Transparent Hugepages : mesurer l’impact sur les performances</title><link>https://blog.zwindler.fr/2020/02/24/transparent-hugepages-mesurer-limpact-sur-les-performances/</link><pubDate>Mon, 24 Feb 2020 07:30:00 +0000</pubDate><guid>https://blog.zwindler.fr/2020/02/24/transparent-hugepages-mesurer-limpact-sur-les-performances/</guid><description>&lt;img src="https://blog.zwindler.fr/2020/02/thp_nothp-1.webp" alt="Featured image of post Transparent Hugepages : mesurer l’impact sur les performances" /&gt;&lt;h2 id="encore-les-transparent-hugepages-"&gt;Encore les Transparent Hugepages ?
&lt;/h2&gt;&lt;p&gt;Il y a quelques jours, j’ai posté un article pour vous aider à &lt;a class="link" href="https://blog.zwindler.fr/2020/02/10/redis-mongodb-rabbitmq-desactiver-les-transparent-huge-pages/" &gt;désactiver les Transparent Hugepages&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;A là suite de ça, Seboss666 (qui tient un &lt;a class="link" href="https://blog.seboss666.info/" target="_blank" rel="noopener"
&gt;super blog bien Geek/sysadmin comme j’aime&lt;/a&gt;) m’a fait remarquer en commentaire que j’expliquais surtout comment désactiver les THP. Mais je n’ai pas beaucoup parlé d’à quoi ça sert (à part que &lt;a class="link" href="https://blog.zwindler.fr/2016/10/26/comprendre-configurer-selinux-rhel-7/" &gt;c’est mal aimé, comme SELinux&lt;/a&gt;) et si ça a vraiment un impact sur les perfs.&lt;/p&gt;
&lt;p&gt;Il m’a passé un &lt;a class="link" href="https://alexandrnikitin.github.io/blog/transparent-hugepages-measuring-the-performance-impact/" target="_blank" rel="noopener"
&gt;article hyper intéressant, en anglais, sur le sujet&lt;/a&gt;. Comme je ne l’aurais pas mieux écris moi-même ET que le but du blog est d’être une ressource francophone, j’ai donc proposé à l’auteur, Alexandr Nikitin, de le traduire en français. Le voilà donc.&lt;/p&gt;
&lt;h2 id="introduction"&gt;Introduction
&lt;/h2&gt;&lt;p&gt;TL;DR ce post a pour but d’expliquer en un mot ce que sont les Transparent Hugepages (THP), décrire les techniques qui seront utilisées pour mesurer leur impact sur les performances et enfin, montrer leur effet sur une application réelle.&lt;/p&gt;
&lt;p&gt;Il est inspiré par un &lt;a class="link" href="https://groups.google.com/forum/#!topic/mechanical-sympathy/sljzehnCNZU" target="_blank" rel="noopener"
&gt;thread a propos des Transparent Huge Pages sur le &amp;ldquo;Mechanical Sympathy group&amp;rdquo;&lt;/a&gt;. Ce thread expose les pièges, les problématiques de performances ainsi que l’état actuel dans les dernières versions du kernel. Une grosse quantité d’information peut y être trouvé.&lt;/p&gt;
&lt;p&gt;En général, vous allez trouver beaucoup de recommendations sur Internet à propos des Transparent Hugepages. La plupart d’entre eux vous diront de désactiver totalement les THP, comme Oracle Database (lien mort), &lt;a class="link" href="https://docs.mongodb.com/manual/tutorial/transparent-huge-pages/" target="_blank" rel="noopener"
&gt;MongoDB&lt;/a&gt;, &lt;a class="link" href="https://web.archive.org/web/20171212085403/https://developer.couchbase.com/documentation/server/current/install/thp-disable.html" target="_blank" rel="noopener"
&gt;Couchbase (lien mort, j&amp;rsquo;utilise Internet Archive)&lt;/a&gt;, MemSQL (lien mort), &lt;a class="link" href="http://doc.nuodb.com/Latest/Content/Note-About-%20Using-Transparent-Huge-Pages.htm" target="_blank" rel="noopener"
&gt;NuoDB&lt;/a&gt;. Certains logiciels utilise la fonctionnalité, comme par exemple &lt;a class="link" href="https://www.postgresql.org/docs/9.6/static/kernel-resources.html#LINUX-HUGE-PAGES" target="_blank" rel="noopener"
&gt;PostgreSQL&lt;/a&gt; (la fonctionnalité hugetlbpage, pas exactement les THP) et &lt;a class="link" href="https://my.vertica.com/docs/7.2.x/HTML/index.htm#Authoring/InstallationGuide/BeforeYouInstall/transparenthugepages.htm" target="_blank" rel="noopener"
&gt;Vertica&lt;/a&gt;. Il existe beaucoup de retours d’expériences de professionnels qui ont eu à se battre contre des freeze de leur système et l’ont &amp;ldquo;corrigé&amp;rdquo; simplement en désactivant les THP. &lt;a class="link" href="https://www.perforce.com/blog/tales-field-taming-transparent-huge-pages-linux" target="_blank" rel="noopener"
&gt;1&lt;/a&gt;, &lt;a class="link" href="https://community.microfocus.com/borland/managetrack/accurev/w/accurev_knowledge_base/27749/recommendation-to-disable-linux-kernel-transparent-hugepages-thp-setting-for-performance-improvement" target="_blank" rel="noopener"
&gt;2&lt;/a&gt;, &lt;a class="link" href="https://web.archive.org/web/20200702063613/http://structureddata.org/2012/06/18/linux-6-transparent-huge-pages-and-hadoop-workloads/" target="_blank" rel="noopener"
&gt;3 (lien mort, j&amp;rsquo;utilise Internet Archive)&lt;/a&gt;, &lt;a class="link" href="https://blogs.oracle.com/linux/performance-issues-with-transparent-huge-pages-thp" target="_blank" rel="noopener"
&gt;4&lt;/a&gt;, &lt;a class="link" href="https://www.percona.com/blog/why-tokudb-hates-transparent-hugepages/" target="_blank" rel="noopener"
&gt;5&lt;/a&gt;, &lt;a class="link" href="https://engineering.linkedin.com/performance/optimizing-linux-memory-management-low-latency-high-throughput-databases" target="_blank" rel="noopener"
&gt;6&lt;/a&gt;. Toutes ces histoires tendent à propager une vision faussée et le préjugé que cette fonctionnalité est dangereuse.&lt;/p&gt;
&lt;p&gt;Malheureusement, je n’ai pas trouvé de post qui mesure ou montre comment mesurer l’impact et les conséquences d’activer ou de désactiver cette fonctionnalité. C’est ce que ce post va tenter de répondre.&lt;/p&gt;
&lt;h2 id="les-transparent-hugepages-en-bref-presque"&gt;Les Transparent Hugepages en bref (presque)
&lt;/h2&gt;&lt;p&gt;Pour fonctionner, presque toutes les applications et les systèmes d’exploitation nécessitent de la mémoire &amp;ldquo;virtuelle&amp;rdquo;. La mémoire virtuelle de tous les logiciels est ensuite mappée dans la mémoire physique. Ce mapping est géré par le système d’exploitation, qui maintient &lt;a class="link" href="https://en.wikipedia.org/wiki/Page_table" target="_blank" rel="noopener"
&gt;une structure de donnée en RAM (page table)&lt;/a&gt;. Pour passer de l’adresse virtuelle à l’adresse physique (page table walking), &lt;a class="link" href="https://fr.wikipedia.org/wiki/Unit%C3%A9_de_gestion_m%C3%A9moire" target="_blank" rel="noopener"
&gt;on utilise un composant du CPU (la MMU)&lt;/a&gt;. En plus de servir de table de traduction, la MMU sert également de cache des pages récemment utilisées. On appelle ce cache le Translation lookaside buffer (TLB).&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Lorsqu’une adresse virtuelle doit être traduite dans une adresse physique, on cherche d’abord dans le TLB. Si un résultat est trouvé (TLB hit), l’adresse physique est retournée et l’accès à la mémoire peut continuer. Cependant, si on ne trouve pas de résultat (TLB miss), la MMU va devoir rechercher le mapping de l’adresse dans la table de pages (page table) si il existe.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Ce processus de &amp;ldquo;page table walk&amp;rdquo; est coûteux en temps car il peut nécessiter plusieurs accès à la mémoire (cependant, avec de la chance on peut retrouver la page mémoire dans un des caches L1/L2/L3 du CPU). Cependant, on ne peut pas non plus compter tout le temps sur le TLB car sa taille est limitée (généralement quelques centaines de pages, au maximum).&lt;/p&gt;
&lt;p&gt;Les systèmes d’exploitation gèrent la mémoire virtuelle en utilisant des pages (des blocks contigus de mémoire). Généralement, la taille d’une page mémoire est de 4 Ko. Petite règle de trois, 1 Go de RAM équivaut à 256000 pages, et 128 Go à 32,7 millions de pages. Clairement, on ne va pas pouvoir tout stocker dans le TLB et nous allons donc souffrir de problèmes de performances à cause des &amp;ldquo;TLB miss&amp;rdquo;. Il y a deux façons d’améliorer cette situation. La première est d’augmenter la taille du TLB. Cependant, c’est coûteux et l’impact n’est pas significatif, surtout sur les systèmes disposant d’une très grande quantité de RAM. La seconde consiste à augmenter la taille d’une page est ainsi, avoir moins de pages à mapper. Les OS et les CPUs modernes sont typiquement capable de supporter des pages &amp;ldquo;larges&amp;rdquo; de 2 Mo, voire même de 1 Go. Ainsi, avec des pages de 2 Mo, 128 Go de RAM devient seulement 64000 pages.&lt;/p&gt;
&lt;p&gt;Ce n’est pas pour rien que Linux supporte les Transparent Hugepages. C’est une optimisation ! Cela permet de gérer un grand nombre de pages de manière automatique et transparente pour les applications. Les bénéfices sont évidents : pas de modification à faire du coté des application, le nombre de &amp;ldquo;TLB miss&amp;rdquo; est réduit, le &amp;ldquo;page table walking&amp;rdquo; devient moins coûteux. Cette fonctionnalité peut être découpée en deux parties : allocation et maintenance.&lt;/p&gt;
&lt;p&gt;Le THP fonctionne de la même manière pour ce qui est de l’allocation de la mémoire et nécessite que le système d’exploitation trouve des blocs alignés et contigus de mémoire. Dans ce cas précis, il souffre également des mêmes problèmes que les pages de mémoire classiques, à savoir la fragmentation. Si l’OS ne sait pas trouver de blocs de mémoire continus, il va essayer de &amp;ldquo;compacter&amp;rdquo;, réclamer les partions inutilisées ou &amp;ldquo;page out&amp;rdquo; les autres pages. Ce processus est couteux et peut provoquer de grosses latences (jusqu’à quelques secondes). Heureusement, ce problème a été adressé dans la &lt;em&gt;version 4.6 du kernel Linux&lt;/em&gt; (avec l’option defer) ; l’OS retourne dans le mode classique (page de 4K) si jamais il ne trouve pas de place pour une hugepage.&lt;/p&gt;
&lt;p&gt;La deuxième partie est la maintenance. Si une application ne modifie ne serait ce qu’un seul octet de mémoire, elle va consommer la taille d’une page entière, à savoir 2 Mo si on utilise des hugepages, ce qui est clairement un gaspillage de mémoire vive. Pour palier à ça, il existe une tâche de fond qui s’appelle khugepaged. Ce processus scanne les pages et essaye de défragmenter et concaténer toutes les pages presque vides dans une seule page. Cependant, même si c’est une tâche de fond, elle va bloquer les pages sur lesquelles elle fonctionne, ce qui peut aussi provoquer des pic de latence. Un dernier problème reste qu’il est parfois nécessaire de découper les grosses pages, car tous les composants de l’OS ne supportent pas les hugepages. C’est le cas de la swap par exemple. L’OS doit alors découper les grosses pages en plus petites pour ces composants là. Encore une fois, cette opération peut dans certain cas dégrader les performances et augmenter la fragmentation.&lt;/p&gt;
&lt;p&gt;Le meilleur endroit pour apprendre comment fonctionnent les Transparent Hugepage est évidemment &lt;a class="link" href="https://www.kernel.org/doc/Documentation/vm/transhuge.txt" target="_blank" rel="noopener"
&gt;la documentation officielle du Kernel Linux&lt;/a&gt;. Cette fonctionnalité dispose de plusieurs éléments de configuration ainsi que des flags pour modifier son comportement. Ils évoluent avec le Kernel lui même.&lt;/p&gt;
&lt;h2 id="comment-le-mesurer-"&gt;Comment le mesurer ?
&lt;/h2&gt;&lt;p&gt;C’est probablement la partie la plus importante de ce post. Basiquement, il y a deux façon de mesurer l’impact de cette fonctionnalité : les CPU counters et les kernel functions.&lt;/p&gt;
&lt;h3 id="cpu-counters"&gt;CPU counters
&lt;/h3&gt;&lt;p&gt;Commençons par les CPU counters. J’utilise &lt;em&gt;perf&lt;/em&gt;, qui est un outil génial et simple pour réaliser ce genre de mesures. &lt;em&gt;Perf&lt;/em&gt; dispose nativement d’alias pour les événements du TLB : dTLB-loads, dTLB-load-misses pour les hit et les miss en load; dTLB-stores, dTLB-store-misses (idem mais pour les stores).&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;[~]# perf stat -e dTLB-loads,dTLB-load-misses,dTLB-stores,dTLB-store-misses -a -I 1000
# time counts unit events
1.006223197 85,144,535 dTLB-loads
1.006223197 1,153,457 dTLB-load-misses # 1.35% of all dTLB cache hits
1.006223197 153,092,544 dTLB-stores
1.006223197 213,524 dTLB-store-misses
...
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Et la même chose pour les instructions (iTLB-load, iTLB-load-misses).&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;[~]# perf stat -e iTLB-load,iTLB-load-misses -a -I 1000
# time counts unit events
1.005591635 5,496 iTLB-load
1.005591635 18,799 iTLB-load-misses # 342.05% of all iTLB cache hits
...
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;En réalité, perf supporte seulement un petit sous ensemble de tous les événements alors que les CPUs ont des centaines de compteurs pour évaluer la performance. Pour les CPUs Intels par exemple, on peut trouver la liste de tous les compteurs disponibles sur le site &lt;a class="link" href="https://download.01.org/perfmon/index/" target="_blank" rel="noopener"
&gt;Intel Processor Event Reference&lt;/a&gt;, dans le &lt;a class="link" href="https://www.intel.com/content/www/us/en/architecture-and-technology/64-ia-32-architectures-software-developer-vol-3b-part-2-manual.html" target="_blank" rel="noopener"
&gt;Intel® 64 and IA-32 Architectures Developer’s Manual: Vol. 3B&lt;/a&gt; ou bien encore dans &lt;a class="link" href="https://github.com/torvalds/linux/blob/510c8a899caf095cb13d09d203573deef15db2fe/tools/perf/pmu-events/arch/x86/haswell/virtual-memory.json" target="_blank" rel="noopener"
&gt;les sources du Kernel Linux&lt;/a&gt;. Le manuel du développeur contient également des codes d’événements que nous devons passer pour analyser les performances.&lt;/p&gt;
&lt;p&gt;Si on regarde les compteurs relatifs au TLB, voilà ce qu’on peut trouver d’intéressant :&lt;/p&gt;
&lt;table class=""&gt;
&lt;tr&gt;
&lt;th&gt;
Mnemonic
&lt;/th&gt;
&lt;th&gt;
Description
&lt;/th&gt;
&lt;th&gt;
Event Num.
&lt;/th&gt;
&lt;th&gt;
Umask Value
&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
DTLB_LOAD_MISSES.MISS_CAUSES_A_WALK
&lt;/td&gt;
&lt;td&gt;
Misses in all TLB levels that cause a page walk of any page size.
&lt;/td&gt;
&lt;td&gt;
08H
&lt;/td&gt;
&lt;td&gt;
01H
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
DTLB_STORE_MISSES.MISS_CAUSES_A_WALK
&lt;/td&gt;
&lt;td&gt;
Miss in all TLB levels causes a page walk of any page size.
&lt;/td&gt;
&lt;td&gt;
49H
&lt;/td&gt;
&lt;td&gt;
01H
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
DTLB_LOAD_MISSES.WALK_DURATION
&lt;/td&gt;
&lt;td&gt;
This event counts cycles when the page miss handler (PMH) is servicing page walks caused by DTLB load misses.
&lt;/td&gt;
&lt;td&gt;
08H
&lt;/td&gt;
&lt;td&gt;
10H
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
ITLB_MISSES.MISS_CAUSES_A_WALK
&lt;/td&gt;
&lt;td&gt;
Misses in ITLB that causes a page walk of any page size.
&lt;/td&gt;
&lt;td&gt;
85H
&lt;/td&gt;
&lt;td&gt;
01H
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
ITLB_MISSES.WALK_DURATION
&lt;/td&gt;
&lt;td&gt;
This event counts cycles when the page miss handler (PMH) is servicing page walks caused by ITLB misses.
&lt;/td&gt;
&lt;td&gt;
85H
&lt;/td&gt;
&lt;td&gt;
10H
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
PAGE_WALKER_LOADS.DTLB_MEMORY
&lt;/td&gt;
&lt;td&gt;
Number of DTLB page walker loads from memory.
&lt;/td&gt;
&lt;td&gt;
BCH
&lt;/td&gt;
&lt;td&gt;
18H
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
PAGE_WALKER_LOADS.ITLB_MEMORY
&lt;/td&gt;
&lt;td&gt;
Number of ITLB page walker loads from memory.
&lt;/td&gt;
&lt;td&gt;
BCH
&lt;/td&gt;
&lt;td&gt;
28H
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;p&gt;&lt;em&gt;Perf&lt;/em&gt; supporte le compteur &lt;code&gt;*MISS_CAUSES_A_WALK&lt;/code&gt; via un alias. Mais nous devrons trouver l’identifiant numérique des autres événements pour les passer en arguments. Point important, les numéros d’événements et les valeurs &lt;em&gt;umask&lt;/em&gt; associées dépendent de chaque CPU. Par exemple, la liste ci dessus est spécifique à l’architecture Intel Haswell ! Il vous sera nécessaire d’adapter ces codes à votre CPU.&lt;/p&gt;
&lt;p&gt;Une des métriques clé est le nombre de cycle CPU passés à faire du page table walking :&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;[~]# perf stat -e cycles \
&amp;gt; -e cpu/event=0x08,umask=0x10,name=dcycles/ \
&amp;gt; -e cpu/event=0x85,umask=0x10,name=icycles/ \
&amp;gt; -a -I 1000
# time counts unit events
1.005079845 227,119,840 cycles
1.005079845 2,605,237 dcycles
1.005079845 806,076 icycles
...
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Une autre métrique importante est le nombre de lecture mémoire qui causent des TLB miss ; ces lectures ne profitent pas du cache CPU et sont donc coûteuses :&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;[~]# perf stat -e cache-misses \
&amp;gt; -e cpu/event=0xbc,umask=0x18,name=dreads/ \
&amp;gt; -e cpu/event=0xbc,umask=0x28,name=ireads/ \
&amp;gt; -a -I 1000
# time counts unit events
1.007177568 25,322 cache-misses
1.007177568 23 dreads
1.007177568 5 ireads
...
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id="kernel-functions"&gt;Kernel functions
&lt;/h3&gt;&lt;p&gt;Une autre façon surpuissante de mesurer l’impact des THP sur les performances et la latence est d’utiliser les fonctions de tracing/probing du Kernel Linux. J’utilise &lt;a class="link" href="https://sourceware.org/systemtap/" target="_blank" rel="noopener"
&gt;SystemTap&lt;/a&gt; pour ça, qui est un outil pour instrumenter dynamiquement les systèmes Linux en production.&lt;/p&gt;
&lt;p&gt;La première fonction intéressante pour le cas qui nous intéresse est &lt;code&gt;__alloc_pages_slowpath&lt;/code&gt;. Elle est exécutée lorsqu’il n’y a pas de bloc contigu de mémoire vive disponible lors d’une allocation. A son tour, cette fonction appelle la fonction de &amp;ldquo;récupération&amp;rdquo; et de &amp;ldquo;compaction&amp;rdquo; des pages, qui je le rappelle est une opération très couteuse qui peut engendrer des pics de latence.&lt;/p&gt;
&lt;p&gt;La seconde fonction intéressante est &lt;code&gt;khugepaged_scan_mm_slot&lt;/code&gt;. Elle est exécutée en tâche de fond par le thread &lt;em&gt;khugepaged&lt;/em&gt; du Kernel. Ce thread scanne les &lt;em&gt;hugepages&lt;/em&gt; et essaye de les compacter en une seule.&lt;/p&gt;
&lt;p&gt;J’utilise un script SystemTap pour mesurer le temps d’exécution d’une fonction. Ce script stocke tous les temps d’exécution en microsecondes et affiche périodiquement un histogramme. Il ne consomme que quelques Mo par heure, en fonction du nombre d’exécutions. Le premier argument est la sonde à utiliser, le second est un nombre (en ms) pour afficher les statistiques.&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;#! /usr/bin/env stap
global start, intervals
probe $1 { start[tid()] = gettimeofday_us() }
probe $1.return
{
t = gettimeofday_us()
old_t = start[tid()]
if (old_t) intervals &amp;lt;&amp;lt;&amp;lt; t - old_t
delete start[tid()]
}
probe timer.ms($2)
{
if (@count(intervals) &amp;gt; 0)
{
printf(&amp;#34;%-25s:\n min:%dus avg:%dus max:%dus count:%d \n&amp;#34;, tz_ctime(gettimeofday_s()),
@min(intervals), @avg(intervals), @max(intervals), @count(intervals))
print(@hist_log(intervals));
}
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Voici un exemple avec la fonction &lt;code&gt;__alloc_pages_slowpath&lt;/code&gt; :&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;[~]# ./func_time_stats.stp &amp;#39;kernel.function(&amp;#34;__alloc_pages_slowpath&amp;#34;)&amp;#39; 1000
Thu Aug 17 09:37:19 2017 CEST:
min:0us avg:1us max:23us count:1538
value |-------------------------------------------------- count
0 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 549
1 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 541
2 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 377
4 |@@@@ 54
8 |@ 12
16 | 5
32 | 0
64 | 0
...
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Il est également intéressant de savoir observer l’état général de l’OS. Un bon exemple peut être la fragmentation de la mémoire. &lt;strong&gt;/proc/buddyinfo&lt;/strong&gt; est un outil utilise pour aider au diagnostic dans ce genre de cas. &lt;strong&gt;Buddyinfo&lt;/strong&gt; va nous donner des pistes pour estimer la taille maximale que l’on peut allouer sans risque, ou pourquoi la précédent allocation a échoué par exemple. De même, on peut aussi trouver des informations utiles dans &lt;strong&gt;/proc/pagetypeinfo&lt;/strong&gt;.&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;cat /proc/buddyinfo
cat /proc/pagetypeinfo
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Vous pouvez en apprendre plus en lisant &lt;a class="link" href="https://elixir.bootlin.com/linux/v3.10.107/source/Documentation/filesystems/proc.txt" target="_blank" rel="noopener"
&gt;la documentation officielle (lien mort, j&amp;rsquo;utilise Internet Archive)&lt;/a&gt; ou alors en lisant &lt;a class="link" href="http://andorian.blogspot.lt/2014/03/making-sense-of-procbuddyinfo.html" target="_blank" rel="noopener"
&gt;cet article&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="jvm"&gt;JVM
&lt;/h2&gt;&lt;p&gt;La JVM supporte les Transparent Hugepages via l’ajout de l’option &lt;code&gt;-XX:+UseTransparentHugePages&lt;/code&gt;. Cependant, on aura alors un message d’avertissement contre de possibles problèmes de performance :&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;-XX:+UseTransparentHugePages On Linux, enables the use of large pages that can dynamically grow or shrink. This option is disabled by default. You may encounter performance problems with transparent huge pages as the OS moves other pages around to create huge pages; this option is made available for experimentation.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Il est intéressant d’activer l’usage des large pages pour le &amp;ldquo;Metaspace&amp;rdquo; :&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;-XX:+UseLargePagesInMetaspace Use large page memory in metaspace. Only used if UseLargePages is enabled.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;De plus, utiliser l’option -XX:+AlwaysPreTouch avec les hugepages peut être une bonne idée. Cela permet de réallouer toute la mémoire physique utilisé par le tas (heap) et ainsi éviter une surcharge supplémentaire due à l’initialisation ou à la compaction. Cependant, cela induira une augmentation du temps nécessaire pour initialiser la JVM.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;-XX:+AlwaysPreTouch Enables touching of every page on the Java heap during JVM initialization. This gets all pages into the memory before entering the main() method. The option can be used in testing to simulate a long-running system with all virtual memory mapped to physical memory. By default, this option is disabled and all pages are committed as JVM heap space fills.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Aleksey Shipilёv montre l’impact sur la performance dans son article de post &lt;a class="link" href="https://shipilev.net/jvm-anatomy-park/2-transparent-huge-pages/" target="_blank" rel="noopener"
&gt;JVM Anatomy Park #2: Transparent Huge Pages&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="un-exemple-de-la-vie-réelle--une-jvm-très-chargée"&gt;Un exemple de la vie réelle : une JVM très chargée
&lt;/h2&gt;&lt;p&gt;Regardons maintenant quel impact ont réellement les Transparent Hugepages sur une application réelle. Prenons une application lancée dans une JVM : un serveur TCP basé sur netty et recevant un trafic important. Le serveur reçoit jusqu’à 100k requêtes par secondes, analyse chaque requête, effectue un appel réseau à une base de données pour chacun des appels, fait un certain nombre de calculs dessus, puis retourne un réponse. L’application en question possède une heapsize de 200 Go. Les mesures ont été réalisées sur des serveurs de production, ainsi que la charge réelle de production. Les serveurs n’étaient pas surchargés et recevaient 50% du nombre maximal de requêtes qu’ils étaient capables de traiter.&lt;/p&gt;
&lt;h3 id="transparent-hugepages-désactivées"&gt;Transparent Hugepages désactivées
&lt;/h3&gt;&lt;p&gt;Désactivons les THP :&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;echo never &amp;gt; /sys/kernel/mm/transparent_hugepage/enabled
echo never &amp;gt; /sys/kernel/mm/transparent_hugepage/defrag
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;La première chose à faire et de mesurer les TLB misses. Ici on a environ 130 millions de TLB misses. Le ratio Miss/Hit est de 1% (ce qui ne semble pas énorme, au premier abord).&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;[~]# perf stat -e dTLB-loads,dTLB-load-misses,iTLB-load-misses,dTLB-store-misses -a -I 1000
# time counts unit events
...
10.007352573 9,426,212,726 dTLB-loads
10.007352573 99,328,930 dTLB-load-misses # 1.04% of all dTLB cache hits
10.007352573 26,021,651 iTLB-load-misses
10.007352573 10,955,696 dTLB-store-misses
...
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Cependant, regardons plus précisément combien nous ont coûté en temps CPU ces TLB misses :&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;[~]# perf stat -e cycles \
&amp;gt; -e cpu/event=0x08,umask=0x10,name=dcycles/ \
&amp;gt; -e cpu/event=0x85,umask=0x10,name=icycles/ \
&amp;gt; -a -I 1000
# time counts unit events
...
12.007998332 61,912,076,685 cycles
12.007998332 5,615,887,228 dcycles
12.007998332 1,049,159,484 icycles
...
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Oui, vous avez bien vu ! Plus de 10% des cycles CPUs sont utilisés pour parcourir la page table.&lt;/p&gt;
&lt;p&gt;Le compteur suivant montre que nous avons 1 million de lectures RAM causées par des TLB misses (sachant que chacunes de ces lectures coûtent 100 ns chacunes) :&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;[~]# perf stat -e cpu/event=0xbc,umask=0x18,name=dreads/ \
&amp;gt; -e cpu/event=0xbc,umask=0x28,name=ireads/ \
&amp;gt; -a -I 1000
# time counts unit events
...
6.003683030 1,087,179 dreads
6.003683030 100,180 ireads
...
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Tous les nombres que je viens de vous montrer sont intéressants, mais ils ne sont pas vraiment &amp;ldquo;exploitables&amp;rdquo;. Les métriques les plus importantes pour un développeur d’application sont les métriques de l’application elle-même. Regardons donc comment la métrique de la latence end-to-end de l’application. Voilà les mesures (en microsecondes) qui ont été récoltées pendant quelques minutes :&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;&amp;#34;max&amp;#34; : 16414.672,
&amp;#34;mean&amp;#34; : 1173.2799067016406,
&amp;#34;min&amp;#34; : 52.112,
&amp;#34;p50&amp;#34; : 696.885,
&amp;#34;p75&amp;#34; : 1353.116,
&amp;#34;p95&amp;#34; : 3769.844,
&amp;#34;p98&amp;#34; : 5453.675,
&amp;#34;p99&amp;#34; : 6857.375,
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="transparent-hugepages-activées"&gt;Transparent Hugepages activées
&lt;/h2&gt;&lt;p&gt;Maintenant on va pouvoir commencer à faire des comparaisons ! Activons les THP :&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;echo always &amp;gt; /sys/kernel/mm/transparent_hugepage/enabled
echo always &amp;gt; /sys/kernel/mm/transparent_hugepage/defrag # consider other options too
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Et lançons la JVM avec les options &lt;code&gt;-XX:+UseTransparentHugePages&lt;/code&gt;, &lt;code&gt;-XX:+UseLargePagesInMetaspace&lt;/code&gt; et &lt;code&gt;-XX:+AlwaysPreTouch&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;La première métrique que nous avions collecté (les TLB misses) ont été divisés par 6, passant de 130 millions à environ 20 millions. Mathématiquement, le ratio miss/hit tombe de 1% à 0,15%. Voici les nombres exacts :&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;[~]# perf stat -e dTLB-loads,dTLB-load-misses,iTLB-load-misses,dTLB-store-misses -a -I 1000
# time counts unit events
1.002351984 10,757,473,962 dTLB-loads
1.002351984 15,743,582 dTLB-load-misses # 0.15% of all dTLB cache hits
1.002351984 4,208,453 iTLB-load-misses
1.002351984 1,235,060 dTLB-store-misses
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Les cycles CPU passés à parcourir la page table ont également diminué d’un facteur 5, d’environ 6,7 milliards à 1,3 milliards. Cette fois ci, nous avons donc utilisé seulement 2% de notre CPU à réaliser du &amp;ldquo;page table walking&amp;rdquo; :&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;[~]# perf stat -e cycles \
&amp;gt; -e cpu/event=0x08,umask=0x10,name=dcycles/ \
&amp;gt; -e cpu/event=0x85,umask=0x10,name=icycles/ \
&amp;gt; -a -I 1000
# time counts unit events
...
8.006641482 55,401,975,112 cycles
8.006641482 1,133,196,162 dcycles
8.006641482 167,646,297 icycles
...
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Et enfin, le nombre de lecture en RAM a diminué de 1 million à 350k&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;[~]# perf stat -e cpu/event=0xbc,umask=0x18,name=dreads/ \
&amp;gt; -e cpu/event=0xbc,umask=0x28,name=ireads/ \
&amp;gt; -a -I 1000
# time counts unit events
...
12.007351895 342,228 dreads
12.007351895 17,242 ireads
...
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Tout ça c’est bien beau, mais, une fois encore, les nombres qui vont le plus nous intéresser, c’est l’effet réel que ça va avoir sur notre application. Voici les chiffres de la latence end-to-end de l’application :&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;&amp;#34;max&amp;#34; : 16028.281,
&amp;#34;mean&amp;#34; : 946.232869010599,
&amp;#34;min&amp;#34; : 41.977000000000004,
&amp;#34;p50&amp;#34; : 589.297,
&amp;#34;p75&amp;#34; : 1080.305,
&amp;#34;p95&amp;#34; : 2966.102,
&amp;#34;p98&amp;#34; : 4288.5830000000005,
&amp;#34;p99&amp;#34; : 5918.753,
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;La différence entre les deux runs sur les 95 percentiles est quasiment de 1 milliseconde ! Voici ce que cela représente visuellement :&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.zwindler.fr/2020/02/grafana.avif"
loading="lazy"
&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Source : &lt;a class="link" href="https://alexandrnikitin.github.io/blog/images/transparent-hugepages-measuring-the-performance-impact/grafana.png" target="_blank" rel="noopener"
&gt;https://alexandrnikitin.github.io/blog/images/transparent-hugepages-measuring-the-performance-impact/grafana.png&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Nous venons donc de mesurer l’amélioration apportée par l’activation des Transparent Hugepages. Cependant, nous savons que l’activation des THP peut avoir un impact sur les performances (à cause de l’overhead de la &amp;ldquo;maintenance&amp;rdquo; que nous avons expliqué plus haut) ainsi que les risques de pic de latence. Nous devons donc également les mesurer. Regardons le thread &lt;code&gt;kernel khugepaged&lt;/code&gt; qui s’occupe de la défragmentation des hugepages. La mesure qui suit a été réalisée sur une durée d’environ 24 heures. Comme vous pouvez le constater, le temps maximum d’exécution est de 6 millisecondes et il y a de nombreuses exécutions qui ont pris moins d’une milliseconde. Si ce processus est en tâche de fond, mais il bloque les pages concernées pendant qu’il travaille dessus. Voici l’histogramme :&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;[~]# ./func_time_stats.stp &amp;#39;kernel.function(&amp;#34;khugepaged_scan_mm_slot&amp;#34;)&amp;#39; 60000 -o khugepaged_scan_mm_slot.log
[~]# tail khugepaged_scan_mm_slot.log
Thu Aug 17 13:38:59 2017 CEST:
min:0us avg:321us max:6382us count:10834
value |-------------------------------------------------- count
0 |@ 164
1 |@ 197
2 |@@@ 466
4 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 6074
8 |@@@@@@ 761
16 |@@ 318
32 | 65
64 | 13
128 | 1
256 | 3
512 |@@@ 463
1024 |@@@@@@@@@@@@@@@@@@ 2211
2048 | 85
4096 | 13
8192 | 0
16384 | 0
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Une autre fonction important du kernel est &lt;code&gt;__aloc_pages_slowpath&lt;/code&gt;. Cette fonction aussi peut provoquer des pics de latence si un block contigue de mémoire n’est pas disponible. Lors de la mesure, l’histogramme est bien meilleur ici. Le temps maximum d’allocation était de 288 microsecondes. Même en le faisant tourner pendant des heures voire même des jours, nous sommes devenus confiant dans le fait que cette fonctionnalité n’allait pas provoquer de longs pics de latence.&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;[~]# ./func_time_stats.stp &amp;#39;kernel.function(&amp;#34;__alloc_pages_slowpath&amp;#34;)&amp;#39; 60000 -o alloc_pages_slowpath.log
[~]# tail alloc_pages_slowpath.log
Tue Aug 15 10:35:03 2017 CEST:
min:0us avg:2us max:288us count:6262185
value |-------------------------------------------------- count
0 |@@@@ 237360
1 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 2308083
2 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 2484688
4 |@@@@@@@@@@@@@@@@@@@@@@ 1136503
8 |@ 72701
16 | 22353
32 | 381
64 | 7
128 | 105
256 | 4
512 | 0
1024 | 0
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Alors comment se fait il que les Transparents Hugepages fonctionnent aussi bien dans ce cas précis ? D’abord, on remarque un amélioration significative de la performance car dans ce cas précis on travaille avec une grande quantité de RAM. De même, on ne remarque pas de pics de latences car il n’y a pas de surcharge en terme de RAM sur le serveur. Il y a beaucoup de RAM (256 Go), la JVM sait tirer partie des THP, pré-alloue la totalité des 200 Go de heap dès le démarrage et ne la redimensionne jamais.&lt;/p&gt;
&lt;h2 id="conclusion"&gt;Conclusion
&lt;/h2&gt;&lt;p&gt;Ne suivez pas aveuglément les recommandation que vous trouvez sur Internet ! Mesurez, mesurez, mesurez encore !&lt;/p&gt;
&lt;p&gt;Les Transparent Hugepages sont une optimisation et qui peut avoir de réelles conséquences positives sur la performance, mais avec des inconvénients et des risques qui peuvent entrainer des conséquences imprévues. Le but de ce post était de donner les clés pour mesurer les gains potentiels et gérer les risques. Le Kernel Linux et ces fonctionnalités évoluent et certains des problèmes des THP ont été adressés dans les dernières versions, comme par exemple l’option &amp;ldquo;defer&amp;rdquo; de la défragmentation, qui permet à l’OS de repasser sur une allocation de taille normale, si jamais il n’est pas possible d’en allouer une large.&lt;/p&gt;
&lt;p&gt;Note de zwindler : Encore merci à l’auteur (&lt;a class="link" href="https://alexandrnikitin.github.io/blog/transparent-hugepages-measuring-the-performance-impact/" target="_blank" rel="noopener"
&gt;Alexandr Nikitin&lt;/a&gt;) pour son article, qui m’a appris beaucoup de choses !&lt;/p&gt;</description></item><item><title>Redis, MongoDB, RabbitMQ, désactiver les Transparent Huge Pages</title><link>https://blog.zwindler.fr/2020/02/10/redis-mongodb-rabbitmq-desactiver-les-transparent-huge-pages/</link><pubDate>Mon, 10 Feb 2020 07:30:00 +0000</pubDate><guid>https://blog.zwindler.fr/2020/02/10/redis-mongodb-rabbitmq-desactiver-les-transparent-huge-pages/</guid><description>&lt;img src="https://blog.zwindler.fr/2020/01/mememe_1aa1a73fcaf242fa2e2642bfd90ccb42-1.webp" alt="Featured image of post Redis, MongoDB, RabbitMQ, désactiver les Transparent Huge Pages" /&gt;&lt;h2 id="transparents-huge-pages"&gt;Transparents Huge Pages
&lt;/h2&gt;&lt;p&gt;Les THP et moi, ça remonte à quelques années (i.e.n un brouillon qui traîne depuis longtemps); Mais j’ai de nouveau eu besoin de toucher aux Transparent Huge Pages il y a peu donc c’est une bonne occasion de m’y remettre.&lt;/p&gt;
&lt;p&gt;&lt;a class="link" href="https://redis.io/topics/admin" target="_blank" rel="noopener"
&gt;Redis&lt;/a&gt;, &lt;a class="link" href="https://docs.mongodb.com/manual/tutorial/transparent-huge-pages/" target="_blank" rel="noopener"
&gt;MongoDB&lt;/a&gt;, RabbitMQ, Kafka&amp;hellip; Tout ces logiciels vous demandent, à l’installation ou dans la documentation, de désactiver ce paramètre système de vos serveurs Linux.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;01-07-2020 03:46:32.730 +0000 WARN ulimit - ulimits: This instance is running on a machine that has kernel transparent huge pages enabled. This can significantly reduce performance and is against best practices. Turn off kernel transparent huge pages using the method that is most appropriate for your Linux distribution.
Même dmesg me dit de le désactiver :'(&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Dans cet article, je vais vous montrer à quoi ça sert, mais surtout comment on va faire pour le désactiver (le plus proprement possible).&lt;/p&gt;
&lt;h2 id="mais-au-fait-cest-quoi-"&gt;Mais au fait, c’est quoi ?
&lt;/h2&gt;&lt;p&gt;Avant de lui couper la chique, le mieux c’est quand même peut-être de savoir de quoi il s’agit avant de respecter les précos des éditeurs.&lt;/p&gt;
&lt;p&gt;Note : Ca me fait penser à &lt;a class="link" href="https://blog.zwindler.fr/2016/10/26/comprendre-configurer-selinux-rhel-7/" &gt;SELinux, la première chose qu’on nous demande de désactiver quand on installe un progiciel sur RHEL et qu’on connaît au final assez mal&amp;hellip;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Pour faire bref, la gestion de la mémoire par le CPU passe par une couche d’abstraction : la mémoire est découpée en pages de taille fixe (par défaut 4ko) et le CPU garde une table de correspondance de ces pages dans la MMU.&lt;/p&gt;
&lt;p&gt;Pour des raisons de performance, il peut être intéressant, sur nos systèmes récents ayant beaucoup de RAM, d’avoir des pages plus grosses pour faciliter le travail du CPU (aka des &amp;ldquo;huge pages&amp;rdquo;). Cependant, il est nécessaire de modifier le code de l’application pour tirer parti des HugePages. Arrive alors une autre couche d’abstraction, les Transparent Huge Pages. Vous avez deviné, pour faire ça de manière transparente !&lt;/p&gt;
&lt;p&gt;Je vous met en bas de l’article quelques liens pour comprendre en détail de quoi on parle.&lt;/p&gt;
&lt;h2 id="oneshot"&gt;Oneshot
&lt;/h2&gt;&lt;p&gt;Maintenant qu’on sait ce que c’est, on peut le désactiver en tout quiétude.&lt;/p&gt;
&lt;p&gt;Déjà, on va commencer par vérifier l’état de notre OS, pour savoir un peu où on en est au niveau des THP. Pour ça, un simple cat de &lt;em&gt;/sys/kernel/mm/transparent_hugepage/enabled&lt;/em&gt; nous donnera l’info :&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;cat /sys/kernel/mm/transparent_hugepage/enabled
[always] madvise never
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Il existe 3 valeurs possibles pour ce paramètre : &lt;em&gt;always&lt;/em&gt;, &lt;em&gt;madvise&lt;/em&gt; et &lt;em&gt;never&lt;/em&gt;. always et never sont simples à comprendre, et pour ce qui est de madvise, il s’agit d’un paramètre intermédiaire qui dit que par défaut, les THP sont désactivées, mais que les applications peuvent utiliser un appel &amp;ldquo;madvise&amp;rdquo; pour allouer des THP dans la zone mémoire réservée pour ça.&lt;/p&gt;
&lt;p&gt;Ici, on va donc vouloir désactiver les THP totalement (donc &lt;em&gt;never&lt;/em&gt;).&lt;/p&gt;
&lt;p&gt;Pour se faire, on peut simplement utiliser la commande suivante :&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;echo never &amp;gt; /sys/kernel/mm/transparent_hugepage/enabled
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Attention cependant, le paramètre ne sera pris en compte que jusqu’au prochain reboot.&lt;/p&gt;
&lt;h2 id="les-méthodes-classiques-pour-désactiver-durablement-les-thp"&gt;Les méthodes classiques pour désactiver durablement les THP
&lt;/h2&gt;&lt;p&gt;A partir de là, on va vouloir le désactiver pour les prochains boots. On va donc devoir indiquer d’une manière ou d’une autre à l’OS qu’il faut désactiver ce paramètre, activé par défaut.&lt;/p&gt;
&lt;p&gt;La plupart des logiciels vous conseillent de faire un service qui ne fait que ça et qui sera lancé au démarrage de votre machine (ex. &lt;a class="link" href="https://www.vertica.com/docs/9.2.x/HTML/Content/Authoring/InstallationGuide/BeforeYouInstall/transparenthugepages.htm" target="_blank" rel="noopener"
&gt;vertica&lt;/a&gt;, &lt;a class="link" href="https://docs.couchbase.com/server/current/install/thp-disable.html" target="_blank" rel="noopener"
&gt;couchbase&lt;/a&gt;, &amp;hellip;).&lt;/p&gt;
&lt;p&gt;Je suis pas fan, je trouve que modifier un paramètre au démarrage ne devrait pas se faire comme ça.&lt;/p&gt;
&lt;p&gt;La façon la plus &amp;ldquo;propre&amp;rdquo; de le faire est probablement de modifier la configuration du bootloader (souvent GRUB). Si vous avez GRUB, c’est assez facile de le faire puisque c’est une option à ajouter dans le grub :&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;cat /etc/default/grub
[...]
GRUB_CMDLINE_LINUX_DEFAULT=&amp;#34;console=tty1 console=ttyS0 earlyprintk=ttyS0 rootdelay=300&amp;#34;
GRUB_CMDLINE_LINUX=&amp;#34;&amp;#34;
[...]
## APRES
cat /etc/default/grub
[...]
GRUB_CMDLINE_LINUX_DEFAULT=&amp;#34;console=tty1 console=ttyS0 earlyprintk=ttyS0 rootdelay=300 transparent_hugepage=never&amp;#34;
GRUB_CMDLINE_LINUX=&amp;#34;&amp;#34;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Cependant, cette méthode nécessite de reconstruire votre fichier grub (avec grub2-mkconfig) donc j’imagine que c’est pour cela que cette méthode n’est pas mise en avant.&lt;/p&gt;
&lt;h2 id="une-méthode-alternative-pour-désactiver-les-transparent-huge-pages"&gt;Une méthode alternative pour désactiver les transparent Huge Pages
&lt;/h2&gt;&lt;p&gt;Si vous ne vous sentez pas de modifier votre bootloader et que vous n’aimez pas, comme moi, l’idée de faire un service pour faire un echo au boot, il reste une dernière possibilité.&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;apt install sysfsutils
echo &amp;#34;kernel/mm/transparent_hugepage/enabled = never&amp;#34; &amp;gt;&amp;gt; /etc/sysfs.conf
echo &amp;#34;never&amp;#34; &amp;gt;&amp;gt; /sys/kernel/mm/transparent_hugepage/enabled
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;L’avantage, c’est que, contrairement à la modif du GRUB, ça va être ultra simple du coup d’automatiser ça avec Ansible. Je vais pouvoir intégrer la modification dans mes playbooks d’installation des logiciels cités en début d’article !&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;---
- hosts: all
become: yes
tasks:
- name: &amp;#34;Install sysfsutils&amp;#34;
apt:
name: &amp;#34;{{item}}&amp;#34;
state: present
loop:
- sysfsutils
- name: &amp;#34;Disable permanently Transparent Huge Pages&amp;#34;
lineinfile:
path: /etc/sysfs.conf
line: kernel/mm/transparent_hugepage/enabled = never
- name: &amp;#34;Disable THP for this boot&amp;#34;
shell: &amp;#34;echo &amp;#39;never&amp;#39; &amp;gt;&amp;gt; /sys/kernel/mm/transparent_hugepage/enabled&amp;#34;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Et voilà :D&lt;/p&gt;
&lt;h2 id="sources"&gt;Sources
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://www.percona.com/blog/2019/03/06/settling-the-myth-of-transparent-hugepages-for-databases/" target="_blank" rel="noopener"
&gt;Settling the Myth of Transparent HugePages for Databases&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://access.redhat.com/solutions/46111" target="_blank" rel="noopener"
&gt;How to use, monitor, and disable transparent hugepages in Red Hat Enterprise Linux 6 and 7?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://stackoverflow.com/questions/51246128/disabling-thp-transparent-hugepages-with-ansible-role" target="_blank" rel="noopener"
&gt;Disabling THP with Ansible&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Erreur multipath « Path not correctly configured for failover »</title><link>https://blog.zwindler.fr/2017/05/24/erreur-multipath-path-not-correctly-configured-for-failover/</link><pubDate>Wed, 24 May 2017 14:15:45 +0000</pubDate><guid>https://blog.zwindler.fr/2017/05/24/erreur-multipath-path-not-correctly-configured-for-failover/</guid><description>&lt;img src="https://blog.zwindler.fr/2017/05/path_failover2.webp" alt="Featured image of post Erreur multipath « Path not correctly configured for failover »" /&gt;&lt;h2 id="path-not-correctly-configured-for-failover"&gt;Path not correctly configured for failover
&lt;/h2&gt;&lt;p&gt;Il y a quelque temps, nous avons du décommissionner une vieille baie HP EVA (qui nous coutait plus cher en maintenance que d’acquérir une baie neuve) et migrer les LUNs vers une baie EMC VNX, elle encore sous maintenance. Cependant, lorsque la migration a été faite, le consultant qui s’est chargé de reconfigurer multipath pour migrer d’une baie à l’autre l’a un peu fait « rapidement ».&lt;/p&gt;
&lt;p&gt;Quelques mois plus tard, lors d’une maintenance classique sur une des baies EMC, de grosses anomalies ont été détectés. Lors de la coupure d’un contrôleur pour mise à jour, certains serveurs hébergeant une partie de nos progiciels, encore sous Redhat 4, se bloquaient au niveau I/O au lieu de basculer sur les chemins encore disponibles. L’occasion rêvée pour refaire un peu de multipath !&lt;/p&gt;
&lt;p&gt;Dans cet article, je vais donc passer en revue quelques unes des erreurs que j’ai pu rencontrer, et comment les corriger.&lt;/p&gt;
&lt;h2 id="liloo-dallas-multipath-"&gt;Liloo Dallas Multipath ?
&lt;/h2&gt;&lt;p&gt;&lt;img src="https://blog.zwindler.fr/2017/05/multipass.avif"
loading="lazy"
&gt;&lt;/p&gt;
&lt;p&gt;D’abord un bref rappel.&lt;/p&gt;
&lt;p&gt;Pour ceux qui ne connaissent pas multipath, il s’agit d’un module de Linux qui permet de gérer les chemins multiples vers une même disque. On l’utilise sur des réseaux de stockage d’entreprises qui disposent de plusieurs niveaux de tolérance aux pannes.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.zwindler.fr/2017/05/multipath01.avif"
loading="lazy"
&gt;&lt;/p&gt;
&lt;p&gt;Chacun des chemins SAN menant à un même disque (LUN A sur le schéma ci dessus) sont indexés côté OS par leur propre &lt;em&gt;special device&lt;/em&gt; du type &lt;strong&gt;/dev/sd[n]&lt;/strong&gt; (4 chemins : sde, sdf, sdg et sdh dans l’exemple).&lt;/p&gt;
&lt;p&gt;On ne peut pas directement les utiliser puisqu’on utiliserait dans ce cas là qu’un seul des chemins disponibles. Et écrire en direct sur 2 chemins menant vers un même disque en même temps serait catastrophique.&lt;/p&gt;
&lt;p&gt;Heureusement, Multipath détecte de lui même (via l’UUID du disque) que les chemins sont en fait un même périphérique et créé pour nous un fichier spécial &lt;strong&gt;/dev/dm-[n]&lt;/strong&gt; qui permet de pointer vers le disque via l’ensemble de ses chemins.&lt;/p&gt;
&lt;h2 id="vérifier-le-plus-évident"&gt;Vérifier le plus évident
&lt;/h2&gt;&lt;p&gt;Initialement, l’anomalie n’était pas visible car les vérifications de l’état de multipath n’avaient été faites qu’avec le niveau de détail standard : les chemins sont bien déclarés, visibles et fonctionnels&amp;hellip; RAS de ce côté.&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;# multipath -l
mpath9 (36006016067302f00e4588d06345ee111)
[size=100 GB][features=&amp;#34;1 queue_if_no_path&amp;#34;][hwhandler=&amp;#34;1 emc&amp;#34;]
\_ round-robin 0 [active]
\_ 0:0:5:3 sdd 8:48 [active]
\_ 1:0:5:3 sdh 8:112 [active]
\_ round-robin 0 [enabled]
\_ 0:0:4:3 sdc 8:32 [active]
\_ 1:0:4:3 sdg 8:96 [active]
[…]
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;De même les modules multipath étaient bien chargés dans le kernel :&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;# lsmod |grep dm
dm_mirror 32585 0
dm_round_robin 5185 1
dm_emc 7745 1
dm_multipath 22865 3 dm_round_robin,dm_emc
dm_mod 76585 7 dm_mirror,dm_multipath
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Cependant, le démon multipathd qui permet de gérer les bascules de chemins est lui hors service&amp;hellip;&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;# service multipathd status
multipathd est arrêté
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;ATTENTION : Le démarrage du démon multipath peut éventuellement provoquer une coupure des chemins, ce qui va planter le serveur et les traitements en cours. Il faut donc bien prendre garde que le serveur ne soit pas utilisé lors de son activation.&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;chkconfig multipathd on
chkconfig --add multipathd
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="doublons-dans-les-user-friendly-device-names"&gt;Doublons dans les user-friendly device names
&lt;/h2&gt;&lt;p&gt;Une fois les problèmes basiques réglés, nous avons remarqué que le consultant en question ne s’était pas trop embêté avec les &lt;em&gt;user-friendly names&lt;/em&gt;. Voici ce que la commande suivante renvoyait :&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;# multipath -v2
remove: mpath9 (dup of mpath2)
mpath9: map in use
remove: mpath23 (dup of mpath2)
mpath23: map in use
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Bien que non bloquant, ceci est clairement peu élégant ;-).&lt;/p&gt;
&lt;p&gt;Comme je l’explique plus haut, multipath agrège les &lt;strong&gt;/dev/sd[n]&lt;/strong&gt; en un seul et unique &lt;strong&gt;/dev/dm-[n]&lt;/strong&gt;. Cependant, il est déconseillé d’utiliser directement le fichier &lt;strong&gt;/dev/dm-[n]&lt;/strong&gt;. En effet, tout comme les &lt;strong&gt;/dev/sd[n]&lt;/strong&gt; (que ce soit dans le cadre de multipath ou pas d’ailleurs), les fichiers &lt;strong&gt;/dev/dm-[n]&lt;/strong&gt; sont susceptibles de changer au cours de la vie du serveur ! De quoi avoir une mauvaise surprise après maintenance&amp;hellip;&lt;/p&gt;
&lt;p&gt;Pour résoudre ce problème, plusieurs solutions sont conseillées. Soit on utilise le WWID du disque qui est garanti unique, soit on utilise le device mapper qui transpose ce &lt;strong&gt;dm-[n]&lt;/strong&gt; un &lt;em&gt;user-friendly name&lt;/em&gt; du type &lt;strong&gt;/dev/mpath[n]&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Dans le cas présent, au gré de la migration, les WWID avaient générés plusieurs &lt;strong&gt;mpath&lt;/strong&gt; pour un même disque et il n’y avait plus de cohérence !&lt;/p&gt;
&lt;p&gt;Pour régler le problème, le plus simple est de couper toutes les applications, puis d’effacer la configuration (pas les données, hein, juste les chemins et la table de correspondance) pour repartir de zéro. On récupère les WWID de chaque disques, puis on supprime tous les chemins courants avec les commandes suivantes :&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;multipath -ll #affiche les chemins et leurs informations
multipath -F #flush de tous les chemins enregistrés
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Une fois les chemins supprimés, il faut modifier le fichier de configuration &lt;strong&gt;/etc/multipath.conf&lt;/strong&gt; pour y ajouter en fin de fichier la déclaration des WWID à associer à des &lt;em&gt;friendly_names&lt;/em&gt; fixés manuellement :&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;[...]
multipaths {
multipath {
wwid &amp;#34;360060160da302f009cd38abe2f5ee111&amp;#34;
alias mpath0
}
multipath {
wwid &amp;#34;36006016067302f00e458ad06345ee111&amp;#34;
alias mpath2
}
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;En enfin, on peut les réenregistrer à l’aide de la commande :&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;multipath -v2
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="mode-alua-4pnr-1-pour-les-luns"&gt;Mode ALUA 4/PNR 1 pour les LUNs
&lt;/h2&gt;&lt;p&gt;Pour autant, la vraie cause de l’anomalie n’a pu être détectée que lorsque le mode de détails supérieur a été utilisé pour afficher les chemins (option -ll). Plusieurs messages d’erreurs relativement explicites se sont affichés, et notamment :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;la mention &lt;em&gt;Path not correctly configured for failover&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;les chemins en &lt;em&gt;« [active][faulty] »&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;multipath -ll
Path not correctly configured for failover
Path not correctly configured for failover
Path not correctly configured for failover
Path not correctly configured for failover
mpath9 (36006016067302f00e4588d06345ee111)
[size=100 GB][features=&amp;#34;1 queue_if_no_path&amp;#34;][hwhandler=&amp;#34;1 emc&amp;#34;]
\_ round-robin 0 [active]
\_ 0:0:5:3 sdd 8:48 [active][faulty]
\_ 1:0:5:3 sdh 8:112 [active][faulty]
\_ round-robin 0 [enabled]
\_ 0:0:4:3 sdc 8:32 [active][faulty]
\_ 1:0:4:3 sdg 8:96 [active][faulty]
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Après consultation de ressources en lignes et du « [Host Connectivity Guide for Linux][3] », il apparait que le mode « ALUA 4 actif actif» n’est pas supporté sur les serveurs Redhat Entreprise Linux 4. Il faut utiliser le mode « PNR 1 actif passif» qui lui est bien certifié.&lt;/p&gt;
&lt;p&gt;Dans notre cas, c’est pourtant bien ce mode « ALUA 4 » qui avait été déclaré côté baie EMC pour les chemins vers l’hôte. A l’inverse, la configuration qui avait été appliquée côté serveur était bien en mode « PNR 1 ». Il y avait donc une incohérence de ce côté-là.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.zwindler.fr/2017/05/multipath02.avif"
loading="lazy"
&gt;&lt;/p&gt;
&lt;h2 id="changer-le-mode-des-luns-sur-une-baie-vnx"&gt;Changer le mode des LUNs sur une baie VNX
&lt;/h2&gt;&lt;p&gt;La modification du type de Failover pour un LUN donné peut se faire depuis la console Unisphere mais ce n’est pas évident à trouver !&lt;/p&gt;
&lt;p&gt;Une fois connecté, il faut choisir une des baies, ouvrir le menu « Hosts » puis « Host List ». Sélectionner le serveur concerné dans la liste, puis ouvrir l’onglet « Initiators » en bas de page.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.zwindler.fr/2017/05/multipath03.avif"
loading="lazy"
&gt;&lt;/p&gt;
&lt;p&gt;Sélectionner un port, puis cliquer sur « Edit », et reconfigurer les 4 chemins.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.zwindler.fr/2017/05/multipath04.avif"
loading="lazy"
&gt;&lt;/p&gt;
&lt;p&gt;Valider, et recommencer l’opération autant de fois que nécessaire.&lt;/p&gt;
&lt;h2 id="le-mot-de-la-fin"&gt;Le mot de la fin
&lt;/h2&gt;&lt;p&gt;Dans notre cas, beaucoup d’erreurs avaient été faites lors de la configuration des LUNs, de la baie de disques et de multipath. Ça donne donc un bon tour d’horizon des premières choses à vérifier si jamais votre multipath sous Linux fonctionne mal.&lt;/p&gt;
&lt;p&gt;Lorsque vous avez comme nous des baies EMC, j’aimerais insister sur le fait que le &lt;a class="link" href="https://web.archive.org/web/20190717113830/https://www.emc.com/collateral/TechnicalDocument/docu5128.pdf" target="_blank" rel="noopener"
&gt;Host Connectivity Guide for Linux (lien mort, j&amp;rsquo;utilise Internet Archive)&lt;/a&gt; est vraiment un document très important, qui vous aidera à correctement tout configurer. N’hésitez pas à le lire en détail !&lt;/p&gt;</description></item><item><title>Administrer des serveurs Windows avec Ansible</title><link>https://blog.zwindler.fr/2016/11/15/administrer-des-serveurs-windows-avec-ansible/</link><pubDate>Tue, 15 Nov 2016 13:00:11 +0000</pubDate><guid>https://blog.zwindler.fr/2016/11/15/administrer-des-serveurs-windows-avec-ansible/</guid><description>&lt;img src="https://blog.zwindler.fr/2016/09/ansible-windows.webp" alt="Featured image of post Administrer des serveurs Windows avec Ansible" /&gt;&lt;h2 id="ansible-sur-windows"&gt;Ansible sur Windows
&lt;/h2&gt;&lt;blockquote&gt;
&lt;p&gt;Depuis que j’ai découvert Ansible, ma vie d’Ops a changée.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Tout doit pouvoir être géré par Ansible. Tous les playbooks doivent être &lt;strong&gt;idempotent&lt;/strong&gt; (je reviendrais la dessus très probablement). Et du coup, ça vaut aussi pour les serveurs Windows qu’il nous reste !&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.zwindler.fr/2016/11/73068978.avif"
loading="lazy"
&gt;&lt;/p&gt;
&lt;p&gt;Il n’existe pas encore de version compatible Windows pour l’exécution locale des playbooks. Cependant, il existe tout de même des modules pour administrer via &lt;em&gt;PowerShell remoting&lt;/em&gt; des serveur Windows.&lt;/p&gt;
&lt;p&gt;La liste des modules pour Windows est disponible &lt;a class="link" href="https://docs.ansible.com/ansible/2.9/modules/list_of_windows_modules.html#windows-modules" target="_blank" rel="noopener"
&gt;sur cette page&lt;/a&gt;. La plupart ne sont pas intégrés au cœur d’Ansible mais font partis des &lt;em&gt;extra-modules&lt;/em&gt;.&lt;/p&gt;
&lt;h2 id="prérequis-côté-serveur"&gt;Prérequis côté serveur
&lt;/h2&gt;&lt;h3 id="configuration-de-base-connexion-distante-avec-des-comptes-locaux"&gt;Configuration de base (connexion distante avec des comptes locaux)
&lt;/h3&gt;&lt;p&gt;Il est nécessaire d’installer un module Python permettant la connexion aux Windows via PowerShell sur le serveur Linux qui servira a exécuter les playbooks.&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;pip install &amp;#34;pywinrm&amp;gt;=0.1.1&amp;#34;
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id="configuration-kerberos-connexion-distante-avec-des-comptes-de-domaine-ad"&gt;Configuration Kerberos (connexion distante avec des comptes de domaine AD)
&lt;/h3&gt;&lt;p&gt;La configuration de base ne permet pas d’utiliser des comptes de domaine. Dans un environnement d’entreprise, la plupart des serveurs Windows sont intégrés à un domaine Active Directory.&lt;/p&gt;
&lt;p&gt;Il est donc intéressant d’installer les clients kerberos qui permettront au serveur Linux avec Ansible de s’authentifier sur un domaine AD.&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;yum -y install python-devel krb5-devel krb5-libs krb5-workstation
pip install kerberos
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;On peut ensuite configurer le fichier &lt;strong&gt;/etc/krb5.conf&lt;/strong&gt; en fonction du contexte. Voici les variables à renseigner :&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;[...]
[realms]
ZWINDLER.INFO = {
kdc = dc01.zwindler.info
kdc = dc02.zwindler.info
kdc = dc03.zwindler.info
}
[domain_realm]
.zwindler.info = ZWINDLER.INFO
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;On peut tester que la configuration fonctionne avec la commande &lt;strong&gt;kinit&lt;/strong&gt;&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;kinit zwindler@ZWINDLER.INFO
Password for zwindler@ZWINDLER.INFO:
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;ATTENTION : Il faut obligatoirement donner le nom du domaine en majuscules, et indiquer le nom complet du domaine et pas le nom Netbios. Ca vaut pour le fichier de configuration krb5.conf ET lors de l’appel de la commande kinit.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;La commande ne doit pas retourner d’erreur et on peut vérifier que tout fonctionne avec la commande &lt;strong&gt;klist&lt;/strong&gt;&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;klist
Default principal: zwindler@ZWINDLER.INFO
Valid starting Expires Service principal
23/08/2016 15:15:33 24/08/2016 01:15:33 krbtgt/ZWINDLER.INFO@ZWINDLER.INFO
renew until 30/08/2016 15:15:30
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id="ajout-dun-serveur-windows"&gt;Ajout d’un serveur Windows
&lt;/h3&gt;&lt;h4 id="méthode-1--compte-local-variables-de-connexion-dans-un-fichier-chiffré"&gt;Méthode 1 : Compte local, variables de connexion dans un fichier chiffré
&lt;/h4&gt;&lt;p&gt;A la différence d’Ansible sous Linux où l’authentification peut se faire sans mot de passe à l’aide de certificats, sous Windows, il sera nécessaire de stocker à un moment donné le mot de passe d’un compte qui pourra se connecter sur les serveurs Windows.&lt;/p&gt;
&lt;p&gt;On ajoute d’abord les serveurs windows dans le fichiers hosts dans un groupe séparé&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;[zwindler_windows_prod]
antivirus
wsus
[zwindler_prod:children]
zwindler_ansible_prod
zwindler_linux_prod
zwindler_windows_prod
[zwindler_windows:children]
zwindler_windows_prod
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;On sécurise l’accès au fichier des variables qui contiendra les comptes d’accès aux machines Windows avec l’utilitaire &lt;strong&gt;ansible-vault&lt;/strong&gt;. Le fichier ne pourra alors être lu/édité qu’avec le mot de passe.&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;ansible-vault create group_vars/zwindler_windows.yml
New Vault password:
cat group_vars/zwindler_windows.yml
$ANSIBLE_VAULT;1.1;AES256
11111111111111111111111111111111111111111111111111111111111111111111111111111111
11111111111111111111111111111111111111111111111111111111111111111111111111111111
11111111111111111111111111111111111111111111111111111111111111111111111111111111
11111111111111111111111111111111111111111111111111111111111111111111111111111111
11111111111111111111111111111111111111111111111111111111111111111111111111111111
11111111111111111111111111111111111111111111111111111111111111111111111111111111
11111111111111111111111111111111111111111111111111111111111111111111111111111111
11111111111111111111111111111111111111111111111111111111111111111111111111111111
11111111111111111111111111111111111111111111111111111111111111111111111111111111
11111111111111111111111111111111111111111111111111111111111111111111111111111111
11111111111111111111111111111111111111111111111111111111111111111111111111111111
11111111111111111111111111111111111111111111111111111111111111111111111111111111
11111111111111111111111111111111111111111111111111111111111111111111111111111111
11111111111111111111111111111111111111111111111111111111111111111111111111111111
11111111111111111111111111111111111111111111111111111111111111111111111111111111
11111111111111111111111111111111111111111111111111111111111111111111111111111111
1111
ansible-vault edit group_vars/zwindler_windows.yml
Vault password:
---
ansible_user: local_admin
ansible_password: xxxxxxxx
ansible_port: 5986
ansible_connection: winrm
#Decommenter si vous utiliser Python 2.7.9+ et des certificats WinRM autosignes (defaut)
#ansible_winrm_server_cert_validation: ignore
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Comme les serveurs qui ont été ajoutés dans le groupe &lt;em&gt;zwindler_windows_prod&lt;/em&gt; héritent des variables définies pour &lt;em&gt;zwindler_windows&lt;/em&gt; dans &lt;em&gt;group_vars/zwindler_windows.yml&lt;/em&gt;, Ansible les utilisera pour s’y connecter.&lt;/p&gt;
&lt;h4 id="méthode-2--utiliser-kinit-pour-la-connexion"&gt;Méthode 2 : utiliser kinit pour la connexion
&lt;/h4&gt;&lt;p&gt;Plutôt que d’utiliser un compte local et stocker le mot de passe dans des variables (de préférence chiffré donc) mais quand même devoir taper le mode de passe du vault à chaque fois, il est possible d’utiliser le binaire &lt;strong&gt;kinit&lt;/strong&gt; pour gérer l’authentification AD via un ticket Kerberos.&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;# kinit domain_admin@ZWINDLER.INFO
Password for domain_admin@ZWINDLER.INFO:
# klist
Ticket cache: KEYRING:persistent:0:krb_ccache_B82OOxI
Default principal: domain_admin@ZWINDLER.INFO
Valid starting Expires Service principal
23/08/2016 16:37:37 24/08/2016 02:37:37 krbtgt/ZWINDLER.INFO@ZWINDLER.INFO
renew until 30/08/2016 16:36:57
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Cependant ce n’est pas suffisant. Pour que l’authentification Kerberos soit tentée par Ansible, il est tout même nécessaire que les variables &lt;strong&gt;ansible_user&lt;/strong&gt;, &lt;strong&gt;ansible_port&lt;/strong&gt; et &lt;strong&gt;ansible_connection&lt;/strong&gt; soient renseignées (bizarrement&amp;hellip;).&lt;/p&gt;
&lt;p&gt;On doit dont créer un fichier de variable similaire à celui de la méthode précédente, mais sans pour autant nécessiter de le chiffrer puisqu’on ne stockera pas le mot de passe.&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;vi group_vars/zwindler_windows.yml
---
ansible_user: auth@by.kerberos
ansible_port: 5986
ansible_connection: winrm
#Decommenter si vous utiliser Python 2.7.9+ et des certificats WinRM autosignes (defaut)
#ansible_winrm_server_cert_validation: ignore
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;A noter, la valeur &lt;strong&gt;ansible_user&lt;/strong&gt; n’est pas du tout utilisée. C’est écrit sur le site d’Ansible :&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Ansible will first attempt Kerberos authentication. This method uses the principal you are authenticated to Kerberos with on the control machine and not ‘ansible_user’.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="prérequis-côté-client"&gt;Prérequis côté client
&lt;/h2&gt;&lt;p&gt;Pour pouvoir se connecter il est également nécessaire de réaliser des modifications sur les serveurs que l’on souhaite administrer avec Ansible.&lt;/p&gt;
&lt;p&gt;La commande &lt;strong&gt;win_ping&lt;/strong&gt; permet de vérifier la connectivité avec les serveurs Windows. Ici la commande échoue car l’exécution de commande PowerShell à distance nécessite l’autorisation explicite sur l’ensemble des serveurs concernés.&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;ansible wsus03 -m win_ping --ask-vault-pass
Vault password:
wsus03 | UNREACHABLE! =&amp;gt; {
&amp;#34;changed&amp;#34;: false,
&amp;#34;msg&amp;#34;: &amp;#34;kerberos: 500 WinRMTransport. [Errno 111] Connection refused, ssl: 500 WinRMTransport. [Errno 111] Connection refused&amp;#34;,
&amp;#34;unreachable&amp;#34;: true
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;De plus, les serveurs dont le pare-feu est activés doivent laisser passer les connexions vers le port 5986 défini dans le fichier &lt;em&gt;group_vars/zwindler_windows.yml&lt;/em&gt;&lt;/p&gt;
&lt;h3 id="powershell-3-pour-windows-2008"&gt;Powershell 3 (pour Windows 2008)
&lt;/h3&gt;&lt;p&gt;Sur les serveurs antérieurs à Windows 2012, seul Powershell 2 est installé et c’est Powershell 3 qu’il faut !&lt;/p&gt;
&lt;p&gt;Ansible fournit un script pour aider à l’installation si la machine a accès à Internet&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;powershell https://raw.githubusercontent.com/cchurch/ansible/devel/examples/scripts/upgrade_to_ps3.ps1
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id="optionnel-ajouter-une-exception-au-pare-feu-pour-le-port-5986"&gt;(Optionnel) ajouter une exception au pare-feu pour le port 5986
&lt;/h3&gt;&lt;p&gt;Cette exception n’est plus nécessaire car le script Ansible qui suit l’ajoute de lui même. Cependant si vous souhaitez gérer cela vous même, voici quoi faire.&lt;/p&gt;
&lt;p&gt;Se connecter sur le serveur, puis lancer un prompt Powershell avec les droits administrateurs&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.zwindler.fr/ansible_windows_firewall1.png"
loading="lazy"
&gt;&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;netsh advfirewall firewall add rule name=&amp;#34;WinRM pour Ansible&amp;#34; dir=in localport=5986 protocol=TCP action=allow
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;img src="https://blog.zwindler.fr/2016/09/ansible_windows_firewall2.avif"
loading="lazy"
&gt;&lt;/p&gt;
&lt;h3 id="autoriser-ansible-à-réaliser-des-actions-à-distance-winrm"&gt;Autoriser Ansible à réaliser des actions à distance (WinRM)
&lt;/h3&gt;&lt;p&gt;Récupérer le script disponible sur la branch « devel » et l’exécuter sur le serveur en question via un prompt Powershell administrateur.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/ansible/ansible-documentation/blob/devel/examples/scripts/ConfigureRemotingForAnsible.ps1" target="_blank" rel="noopener"
&gt;github.com/ansible/ansible-documentation/blob/devel/examples/scripts/ConfigureRemotingForAnsible.ps1&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src="https://blog.zwindler.fr/2016/09/ansible_windows_winrm.avif"
loading="lazy"
&gt;&lt;/p&gt;
&lt;p&gt;Autoriser l’exécution de script Powershell si nécessaire.&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;Set-ExecutionPolicy Unrestricted
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id="tests-et-troubleshooting"&gt;Tests et troubleshooting
&lt;/h3&gt;&lt;pre tabindex="0"&gt;&lt;code&gt;ansible wsus03 -m win_ping --ask-vault-pass
Vault password:
wsus03 | SUCCESS =&amp;gt; {
&amp;#34;changed&amp;#34;: false,
&amp;#34;ping&amp;#34;: &amp;#34;pong&amp;#34;
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Dans le cas où on souhaite réinitialiser les tickets kerberos pour valider le bon fonctionnement, on peut utiliser les commandes &lt;strong&gt;klist&lt;/strong&gt; et &lt;strong&gt;kdestroy&lt;/strong&gt;&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;klist
Ticket cache: KEYRING:persistent:0:krb_ccache_B82OOxI
Default principal: domain_admin@ZWINDLER.INFO
Valid starting Expires Service principal
23/08/2016 16:38:45 24/08/2016 02:37:37 HTTP/wsus03.zwindler.info@ZWINDLER.INFO
renew until 30/08/2016 16:36:57
23/08/2016 16:37:37 24/08/2016 02:37:37 krbtgt/ZWINDLER.INFO@ZWINDLER.INFO
renew until 30/08/2016 16:36:57
kdestroy -A
klist
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Have fun !&lt;/p&gt;
&lt;h2 id="sources"&gt;Sources
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="http://www.it-connect.fr/debutez-avec-ansible-et-gerez-vos-serveurs-windows/" target="_blank" rel="noopener"
&gt;www.it-connect.fr/debutez-avec-ansible-et-gerez-vos-serveurs-windows/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://docs.ansible.com/ansible/2.9/modules/list_of_windows_modules.html#windows-modules" target="_blank" rel="noopener"
&gt;docs.ansible.com/ansible/2.9/modules/list_of_windows_modules.html#windows-modules&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://docs.ansible.com/ansible/devel/os_guide/intro_windows.html" target="_blank" rel="noopener"
&gt;docs.ansible.com/ansible/devel/os_guide/intro_windows.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>[En bref] Agrandissement de swap sous Linux</title><link>https://blog.zwindler.fr/2016/02/06/reminder-agrandissement-de-swap-linux/</link><pubDate>Sat, 06 Feb 2016 11:30:44 +0000</pubDate><guid>https://blog.zwindler.fr/2016/02/06/reminder-agrandissement-de-swap-linux/</guid><description>&lt;img src="https://blog.zwindler.fr/2016/02/RedHatLogo.webp" alt="Featured image of post [En bref] Agrandissement de swap sous Linux" /&gt;&lt;h2 id="agrandir-la-swap-pourquoi-faire-"&gt;Agrandir la swap, pourquoi faire ?
&lt;/h2&gt;&lt;p&gt;Avec la montée en puissance de l’extension à chaud de RAM sur les machines virtuelles et l’explosion des tailles de JVM délirantes (20 Go pour un outil de gestion de projet pour 100 personnes. Allo&amp;hellip;) il est de plus en plus simple de se dire :&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Tiens, le vent souffle aujourd’hui, j’vais rajouter un peu de RAM à mes VMs.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Sauf qu’il arrive d’oublier les bonnes pratiques en vigueur dans votre propre contexte professionnel : 1 fois la RAM, 1,5 fois la RAM, 2 fois la RAM, 0,5 fois la RAM si on a plus de 8Go, 2Go quoiqu’il arrive (rayez les mentions inutiles).&lt;/p&gt;
&lt;p&gt;Ça et les templates, pour qui on ne différencie pas toujours les gros des petits serveurs, par flemme.&lt;/p&gt;
&lt;p&gt;Du coup, je me retrouve régulièrement à nettoyer des serveurs pour qui on a oublié d’agrandir la RAM après une extension. Et du coup, j’aime bien avoir sous la main la procédure pour le faire rapidement.&lt;/p&gt;
&lt;h2 id="les-commandes-pour-le-faire-sous-linux-rhel-6-en-loccurrence"&gt;Les commandes pour le faire sous Linux (RHEL 6 en l’occurrence)
&lt;/h2&gt;&lt;p&gt;Afficher des informations sur la swap&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;swapon -s
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Récupérer/retrouver le device qui porte la swap dans la fstab&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;grep swap /etc/fstab
/dev/VolGroup00/LogVol01 swap swap defaults 0 0
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Vérifier que la swap n’est pas utilisée, ou à défaut, &lt;strong&gt;que toutes les pages swapées peuvent être stockées en mémoire&lt;/strong&gt; sinon &amp;hellip;!&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;free -m
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Désactivation de la swap&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;swapoff -a
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Agrandir le LV (si on a fait du LVM, sinon il faut agrandir ou créer une nouvelle partition ce qui peut être un peu plus casse pied) puis recréer le volume de swap à la nouvelle taille :&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;lvextend -L +4G /dev/VolGroup00/LogVol01
mkswap /dev/VolGroup00/LogVol01
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Réactiver la swap&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;swapon -a
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Vérifier la prise en compte&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;swapon -s
cat /proc/swaps #affiche la même chose mais j&amp;#39;aime bien
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="bonus--techniques-barbares-pour-faire-le-ménage"&gt;Bonus : techniques barbares pour faire le ménage
&lt;/h2&gt;&lt;p&gt;Je me rend le plus souvent compte que les serveurs n’ont pas les bonnes tailles de swap lorsque j’ai une alerte dans ma supervision.&lt;/p&gt;
&lt;h3 id="cycle-en-v--recherche-des-coupables"&gt;Cycle en V : recherche des coupables
&lt;/h3&gt;&lt;p&gt;Souvent, les gros systèmes taillés au plus juste swappent un peu, quelques centaines de Mo de temps en temps, lorsqu’un gros traitement se déclenche et qu’on dépasse la quantité de mémoire totale prévue. Mais parfois cela peut assi être un processus qui perd la boule et qui se met à consommer un max de mémoire (avec la réduction drastique des performances qui vont avec en cas de swap).&lt;/p&gt;
&lt;p&gt;Pour déterminer quel processus consomme le plus de swap sous Linux, on peut utiliser les commandes suivantes :&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;free -m
------total        used        free        shared        buffers        cached
Mem:           3948      3186         761                 0                 17             1593
-/+ buffers/cache:      1575      2372
Swap:           4000              0      4000
&lt;/code&gt;&lt;/pre&gt;&lt;ul&gt;
&lt;li&gt;3948 la quantité totale de RAM du système&lt;/li&gt;
&lt;li&gt;3186 et 761 représentent respectivement les quantités de RAM utilisée et disponible, sans tenir compte de ce qui est utilisable en cache/buffer&lt;/li&gt;
&lt;li&gt;2372 représente la quantité réelle de mémoire disponible (soit pas du tout utilisée, soit dans un cache qui pourra être libéré si nécessaire)&lt;/li&gt;
&lt;li&gt;1575 représente la quantité réellement utilisée par les processus&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Si votre système est récent (procps-ng) l’affichage sera un peu différent car les buffers et le cache ont été regroupés dans une même colonne, sur la même ligne que la mémoire. Et c’est tant mieux car c’est plus clair comme ça, je trouve :&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;free -m
------total        used        free      shared  buff/cache   available
Mem:               993         353       329              37              309           447
Swap:            2079             0       2079
&lt;/code&gt;&lt;/pre&gt;&lt;ul&gt;
&lt;li&gt;993 la quantité totale de RAM du système&lt;/li&gt;
&lt;li&gt;353 représente la quantité réellement utilisée par les processus&lt;/li&gt;
&lt;li&gt;329 représente la quantité de mémoire pas du tout utilisée (ni par des processus, ni par des caches)&lt;/li&gt;
&lt;li&gt;447 représente une estimation de la quantité réelle de mémoire disponible pour d’autres processus avant que le système ne se mette à swaper (soit pas du tout utilisée, soit dans un cache qui pourra être libéré si nécessaire)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Dans certaines versions de top, il est possible d’obtenir un tri par processus de l’utilisation de la swap, notamment avec RHEL/CentOS, jusqu’à version 6 qui utilise &lt;strong&gt;procps&lt;/strong&gt; :&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;top
O #o majuscule
p #p minucule
[touche entrée]
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;La commande top devrait alors lister les processus en fonction de leur utilisation de SWAP&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;PID USER PR VIRT NI SHR SWAP S %CPU %MEM TIME+ RES COMMAND
4390 root 18 2449m 0 2276 2.0g S 0 9.3 185:11.98 367m mrmonitord
4316 root 34 1566m 19 1976 1.1g S 0 10.7 4:15.62 423m yum-updatesd
4385 root 18 1141m 0 1476 1.1g S 0 0.6 423:19.03 23m java
22009 apache 15 385m 0 4708 360m S 0 0.6 0:20.40 25m httpd
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Cependant, cet affichage n’est pas totalement exact et c’est pour cela que cette fonction n’existe pas toujours dans top. C’est notamment vrai pour les dernières versions de Debian/Ubuntu et de RHEL 7 qui utilisent procps**-ng**.&lt;br&gt;
Personnellement je trouve que ça donne un bon aperçu des processus qui sont en train de swapper en cas de recherche d’un coupable. Si vous voulez plus d’information là dessus, je vous conseille de lire la partie « A note about top command » de &lt;a class="link" href="https://www.cyberciti.biz/faq/linux-which-process-is-using-swap/" target="_blank" rel="noopener"
&gt;cet article&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id="faire-un-peu-de-ménage"&gt;Faire un peu de ménage
&lt;/h3&gt;&lt;p&gt;Certains d’entre vous trouveront peut être plus simple de le relancer (quand cela est possible). Ceci pourrait rendre de la mémoire au serveur qui se mettra à arrêter de swapper. Pour autant, la mémoire swappée ne sera pas forcément rendue, et l’alerte en supervision restera présente même si l’incident est terminé&amp;hellip;&lt;/p&gt;
&lt;p&gt;Du coup, voici quelques tips supplémentaires pour faire du ménage dans les caches pour libérer la mémoire réservée mais pas forcément nécessaire :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Libération du pagecache&lt;/li&gt;
&lt;/ul&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;echo 1 &amp;gt; /proc/sys/vm/drop_caches
&lt;/code&gt;&lt;/pre&gt;&lt;ul&gt;
&lt;li&gt;Libération des dentries et des inodes&lt;/li&gt;
&lt;/ul&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;echo 2 &amp;gt; /proc/sys/vm/drop_caches
&lt;/code&gt;&lt;/pre&gt;&lt;ul&gt;
&lt;li&gt;Tout libérer d’un coup&lt;/li&gt;
&lt;/ul&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;echo 3 &amp;gt; /proc/sys/vm/drop_caches
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id="tout-péter"&gt;Tout péter
&lt;/h3&gt;&lt;p&gt;Si vous vous sentez d’humeur guerrière et que vous pensez que tout ce qui est dans la swap peut re-rentrer en RAM, vous pouvez toujours désactiver la swap. Ceci aura pour effet de vider complètement la swap et donc de tout rappatrier en RAM. Il va sans dire que si vous vous êtes trompé, le système se bloquera et vous pourrez appuyer longuement sur le bouton « Power ».&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;swapoff -a #extinction de la swap
swapon -a #relance de la swap
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Vous voilà prévenus ;)&lt;/p&gt;</description></item></channel></rss>