<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Hack on Zwindler's Reflection</title><link>https://blog.zwindler.fr/tags/hack/</link><description>Recent content in Hack on Zwindler's Reflection</description><generator>Hugo -- gohugo.io</generator><language>fr</language><copyright>Licensed under CC BY-SA 4.0</copyright><lastBuildDate>Mon, 17 Nov 2025 18:00:00 +0200</lastBuildDate><atom:link href="https://blog.zwindler.fr/tags/hack/index.xml" rel="self" type="application/rss+xml"/><item><title>Transformer Proxmox VE en node Kubernetes avec LXC et lxcri</title><link>https://blog.zwindler.fr/2025/11/17/transformer-proxmox-ve-en-node-kubernetes-avec-lxc-et-lxcri/</link><pubDate>Mon, 17 Nov 2025 18:00:00 +0200</pubDate><guid>https://blog.zwindler.fr/2025/11/17/transformer-proxmox-ve-en-node-kubernetes-avec-lxc-et-lxcri/</guid><description>&lt;img src="https://blog.zwindler.fr/2025/11/proxmox-k8s.webp" alt="Featured image of post Transformer Proxmox VE en node Kubernetes avec LXC et lxcri" /&gt;&lt;h2 id="il-ne-savait-pas-que-cétait-complètement-stupide-alors-il-la-fait"&gt;Il ne savait pas que c&amp;rsquo;était complètement stupide, alors il l&amp;rsquo;a fait
&lt;/h2&gt;&lt;p&gt;Quel mensonge&amp;hellip; &lt;strong&gt;Bien sûr, je sais très bien que c&amp;rsquo;est débile&lt;/strong&gt;. Raison pour laquelle cette idée est donc irrésistible.&lt;/p&gt;
&lt;p&gt;Si vous suivez le blog, vous savez que j&amp;rsquo;utilise beaucoup Proxmox VE (les articles qui attirent le plus sur le blog sont d&amp;rsquo;ailleurs des articles sur cette technologie de virtualisation).&lt;/p&gt;
&lt;p&gt;Proxmox VE, c&amp;rsquo;est très cool ; on peut faire des VMs (QEMU) avec, mais aussi, si on n&amp;rsquo;a pas de VT-x ou qu&amp;rsquo;on veut des &amp;ldquo;lightweight VMs&amp;rdquo; (terme dont on a abusé à outrance), on peut installer des OS complets dans des containers avec LXC.&lt;/p&gt;
&lt;p&gt;Mais au delà de ces deux solutions, les devs du projet Proxmox VE sont assez rigides (et pas que là dessus). C&amp;rsquo;est d&amp;rsquo;ailleurs pour ça que j&amp;rsquo;ai posté quelques &amp;ldquo;hacks&amp;rdquo; pour contourner les limitations de Proxmox, notamment &lt;a class="link" href="https://blog.zwindler.fr/2022/11/07/containers-docker-dans-proxmox-avec-lxc/" target="_blank" rel="noopener"
&gt;cet article où j&amp;rsquo;explique comment lancer des containers Docker (via LXC) dans Proxmox VE (normalement pas possible)&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Et si on allait encore plus loin dans le hack idiot ?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Et si, non seulement on exécutait des containers OCI dans Proxmox VE, mais qu&amp;rsquo;EN PLUS, on transformait nos hôtes Proxmox VE en ✨️ &lt;strong&gt;Nodes Kubernetes&lt;/strong&gt; ✨️ ???&lt;/p&gt;
&lt;h2 id="on-sy-prend-comment-"&gt;On s&amp;rsquo;y prend comment ?
&lt;/h2&gt;&lt;p&gt;Le but n&amp;rsquo;est évidemment pas d&amp;rsquo;installer Kubernetes à côté de Proxmox VE, mais réutiliser le plus de choses possibles. Typiquement, je vais réutiliser la techno de &amp;ldquo;virtu&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;Proxmox VE supportant 2 technos de virtualisation différentes (qemu et LXC), il faut choisir. Et comme j&amp;rsquo;aime bien LXC et que j&amp;rsquo;ai déjà expérimenté sur le hack Docker =&amp;gt; LXC sur Proxmox VE, &lt;strong&gt;la question était vite répondue&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Toute la difficulté de l&amp;rsquo;exercice est de trouver comment rendre LXC &amp;ldquo;CRI-compatible&amp;rdquo;. Et on a de la chance, Linux Containers, la fondation qui chapeaute LXC et Incus (ex LXD, &amp;ldquo;refermé&amp;rdquo; par Canonical), a écrit il y a quelques années un CRI pour LXC appelé &lt;a class="link" href="https://github.com/lxc/lxcri" target="_blank" rel="noopener"
&gt;lxcri&lt;/a&gt;. Et bien sûr, comme c&amp;rsquo;est un projet à l&amp;rsquo;utilité discutable, le truc n&amp;rsquo;est plus maintenu depuis 2021.&lt;/p&gt;
&lt;p&gt;J&amp;rsquo;avais d&amp;rsquo;ailleurs essayé de l&amp;rsquo;utiliser, passé pas mal de temps dessus en février 2024 (j&amp;rsquo;ai essuyé bug sur bug, suis passé par des forks, &amp;hellip;) pour échouer lamentablement sur un problème de compatibilité avec ma version de LXC (5+ sous Proxmox 8, 6 en Proxmox 9), entre autres bugs.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;lxcri is a wrapper around LXC which can be used as a drop-in container runtime replacement for use by CRI-O.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;On va donc quand même avoir besoin de 3 trucs en plus sur notre serveur Proxmox pour que mon idée débile fonctionne :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;lxcri&lt;/strong&gt; comme container runtime de base niveau&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;cri-o&lt;/strong&gt; comme container runtime de haut niveau&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;kubelet&lt;/strong&gt; pour piloter le runtime et communiquer avec le control plane&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="cest-parti"&gt;C&amp;rsquo;est parti
&lt;/h2&gt;&lt;p&gt;OK. lxcri s&amp;rsquo;appuie donc sur &lt;a class="link" href="https://cri-o.io/" target="_blank" rel="noopener"
&gt;cri-o&lt;/a&gt;, le container runtime de Red Hat. On commence donc par installer cri-o :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/cri-o/cri-o/blob/main/install.md" target="_blank" rel="noopener"
&gt;https://github.com/cri-o/cri-o/blob/main/install.md&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Note : mon serveur Proxmox VE 8 de l&amp;rsquo;époque utilisait Debian 12 comme OS de base. On devrait donc se baser là-dessus pour la variable $OS (comme l&amp;rsquo;indique la doc). Cependant, à l&amp;rsquo;heure où j&amp;rsquo;ai testé la première fois, les dépôts de CRI-O étaient en cours de migration, avec une documentation pas à jour et des releases manquantes. Le répo &lt;a class="link" href="https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable:/cri-o/" target="_blank" rel="noopener"
&gt;download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable:/cri-o&lt;/a&gt; n&amp;rsquo;avait pas le PATH Debian_12, ni la version 1.29 de Kubernetes&amp;hellip; &lt;strong&gt;J&amp;rsquo;avais BIEN ragé&lt;/strong&gt;.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/cri-o/cri-o/issues/7657" target="_blank" rel="noopener"
&gt;https://github.com/cri-o/cri-o/issues/7657&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://kubernetes.io/blog/2023/10/10/cri-o-community-package-infrastructure/" target="_blank" rel="noopener"
&gt;https://kubernetes.io/blog/2023/10/10/cri-o-community-package-infrastructure/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;On ne devrait plus avoir de soucis maintenant :&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;&lt;span class="nb"&gt;export&lt;/span&gt; &lt;span class="nv"&gt;KUBERNETES_VERSION&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;v1.32
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;export&lt;/span&gt; &lt;span class="nv"&gt;CRIO_VERSION&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;v1.32
&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="c1"&gt;# créer un répertoire pour les keyrings (il n&amp;#39;existe pas toujours sur une install fraiche)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo mkdir -p /usr/share/keyrings
&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="c1"&gt;# répo de kubernetes&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;curl -fsSL https://pkgs.k8s.io/core:/stable:/&lt;span class="nv"&gt;$KUBERNETES_VERSION&lt;/span&gt;/deb/Release.key &lt;span class="p"&gt;|&lt;/span&gt; sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg
&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="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/&lt;/span&gt;&lt;span class="nv"&gt;$KUBERNETES_VERSION&lt;/span&gt;&lt;span class="s2"&gt;/deb/ /&amp;#34;&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; sudo tee /etc/apt/sources.list.d/kubernetes.list
&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="c1"&gt;# répo de crio&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;curl -fsSL https://download.opensuse.org/repositories/isv:/cri-o:/stable:/&lt;span class="nv"&gt;$CRIO_VERSION&lt;/span&gt;/deb/Release.key &lt;span class="p"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; sudo gpg --dearmor -o /etc/apt/keyrings/cri-o-apt-keyring.gpg
&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="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;deb [signed-by=/etc/apt/keyrings/cri-o-apt-keyring.gpg] https://download.opensuse.org/repositories/isv:/cri-o:/stable:/&lt;/span&gt;&lt;span class="nv"&gt;$CRIO_VERSION&lt;/span&gt;&lt;span class="s2"&gt;/deb/ /&amp;#34;&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; sudo tee /etc/apt/sources.list.d/cri-o.list
&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;sudo apt update
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo apt install cri-o
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;A partir de là, on a cri-o. On pourrait le configurer mais si on fait ça, il utilisera runc et on n&amp;rsquo;utiliserait pas LXC en tant que runtime.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Ce n&amp;rsquo;est pas le but de ce hack !&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;C&amp;rsquo;est donc à ce moment là qu&amp;rsquo;on rebascule sur la documentation de lxcri :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/lxc/lxcri/blob/main/doc/setup.md" target="_blank" rel="noopener"
&gt;github.com/lxc/lxcri&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="ya-pas-de-release"&gt;Ya pas de release
&lt;/h2&gt;&lt;p&gt;Et oui&amp;hellip; il faut préalablement &lt;strong&gt;builder&lt;/strong&gt; le binaire &lt;code&gt;lxcri&lt;/code&gt; et le déposer dans le /usr/local de notre serveur Proxmox VE. Il n&amp;rsquo;y a pas de binaire précompilé dans le projet, &lt;a class="link" href="https://github.com/lxc/lxcri/issues/57" target="_blank" rel="noopener"
&gt;c&amp;rsquo;est une issue ouverte juste avant qu&amp;rsquo;il ne soit abandonné 😬😬&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Et pour que ce soit encore plus fun, le processus de build passe par un Dockerfile, ce qui est rigolo puisqu&amp;rsquo;on n&amp;rsquo;a pas Docker sur notre node Proxmox&amp;hellip;&lt;/p&gt;
&lt;p&gt;J&amp;rsquo;ai donc essayé de &lt;a class="link" href="https://github.com/lxc/lxcri/blob/main/README.md" target="_blank" rel="noopener"
&gt;builder lxcri&lt;/a&gt; depuis une machine avec Docker, en suivant la commande indiquée sur le GitHub. Patatra. (Déjà, il manque un &amp;ldquo;.&amp;rdquo; en fin de commande &lt;code&gt;docker build&lt;/code&gt; dans la doc) ça fail misérablement à la compilation&amp;hellip;&lt;/p&gt;
&lt;p&gt;Note : je n&amp;rsquo;ai plus l&amp;rsquo;erreur en question, probablement un problème de dépendances. C&amp;rsquo;est relou parce qu&amp;rsquo;on va devoir faire plein de choses à la main&amp;hellip; Mais ne vous embêtez pas à &lt;code&gt;git clone&lt;/code&gt;, on va partir sur un fork (d&amp;rsquo;un fork).&lt;/p&gt;
&lt;p&gt;En allant jeter un œil au Dockerfile, on se rend vite compte qu&amp;rsquo;on ne fait que lancer un script (install.sh)&amp;hellip;&lt;/p&gt;
&lt;p&gt;Quand on appelle Docker avec le buildarg &lt;code&gt;installcmd=install_runtime&lt;/code&gt;, on lance la fonction &lt;code&gt;install_runtime&lt;/code&gt;, qui appelle &lt;code&gt;install_runtime_noclean&lt;/code&gt;, qui lance &lt;code&gt;add_lxc&lt;/code&gt; puis &lt;code&gt;add_lxcri&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Je veux juste compiler &lt;strong&gt;lxc&lt;/strong&gt; (pour les bindings) et &lt;strong&gt;lxcri&lt;/strong&gt;. Je vais donc le faire à la main. Pour ça, il faut golang 1.16 (ça date&amp;hellip;).&lt;/p&gt;
&lt;p&gt;Il y a pas mal de code pété un peu partout et plusieurs issues ouvertes dans lesquelles les mainteneurs conseillent de partir sur un fork :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/drachenfels-de/lxcri" target="_blank" rel="noopener"
&gt;https://github.com/drachenfels-de/lxcri&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;J&amp;rsquo;ai passé pas mal de temps à le débugger, et au final j&amp;rsquo;ai fait mon propre fork (&lt;a class="link" href="https://github.com/zwindler/lxcri%29" target="_blank" rel="noopener"
&gt;https://github.com/zwindler/lxcri)&lt;/a&gt;, qui nécessite golang 1.22+ et qui ajoute un gros paquet de fixes.&lt;/p&gt;
&lt;h2 id="prérequis-pour-builder-lxcri"&gt;Prérequis pour builder lxcri
&lt;/h2&gt;&lt;p&gt;On va installer un paquet de trucs :&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;sudo apt update
sudo apt install curl git meson pkg-config cmake libdbus-1-dev docbook2x
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;On installe Golang si on ne l&amp;rsquo;a pas (peu de chance que vous ayez Golang sur un node Proxmox VE) :&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;wget https://go.dev/dl/go1.25.4.linux-amd64.tar.gz
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo rm -rf /usr/local/go &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; sudo tar -C /usr/local -xzf go1.25.4.linux-amd64.tar.gz
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;export&lt;/span&gt; &lt;span class="nv"&gt;PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$PATH&lt;/span&gt;:/usr/local/go/bin
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;go version
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; go version go1.25.4 linux/amd64
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Je vais aussi devoir &lt;strong&gt;récupérer et compiler lxc&lt;/strong&gt;. Pendant un moment, j&amp;rsquo;étais bloqué sur la version 4.0.12 (très précisément) car la 4.0.6 qu&amp;rsquo;on trouve sur Debian 11 ne fonctionne &lt;strong&gt;pas&lt;/strong&gt; avec le code de lxcri (j&amp;rsquo;ai mangé plein de bugs).&lt;/p&gt;
&lt;p&gt;Mais la bonne nouvelle, c&amp;rsquo;est que comme je suis un try-harder de l&amp;rsquo;espace, à force de fixes sur mon fork, celui-ci fonctionne avec la dernière version de lxc (6.x), ce qui tombe bien parce que c&amp;rsquo;est la version sur mon Proxmox VE 9 à jour.&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;git clone https://github.com/lxc/lxc
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; lxc
&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;meson setup -Dprefix&lt;span class="o"&gt;=&lt;/span&gt;/usr -Dsystemd-unitdir&lt;span class="o"&gt;=&lt;/span&gt;PATH build
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Build targets in project: &lt;span class="m"&gt;30&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; lxc 6.0.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; User defined options
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; prefix : /usr
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; systemd-unitdir: PATH
&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; Found ninja-1.12.1 at /usr/bin/ninja
&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;meson compile -C build
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; INFO: autodetecting backend as ninja
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; INFO: calculating backend &lt;span class="nb"&gt;command&lt;/span&gt; to run: /usr/bin/ninja -C /root/lxc/build
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ninja: Entering directory &lt;span class="sb"&gt;`&lt;/span&gt;/root/lxc/build&lt;span class="err"&gt;&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;[&lt;/span&gt;544/544&lt;span class="o"&gt;]&lt;/span&gt; Linking target src/lxc/tools/lxc-monitor
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Ça a buildé plein de trucs, c&amp;rsquo;est cool. Mais les fichiers qui m&amp;rsquo;intéressent sont ici :&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;find . -name &lt;span class="s2"&gt;&amp;#34;lxc.pc&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;./build/meson-private/lxc.pc
&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;ls build/*lxc*
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;build/liblxc.so build/liblxc.so.1 build/liblxc.so.1.8.0 build/lxc.spec
&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;build/liblxc.so.1.8.0.p:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;liblxc.so.1.8.0.symbols
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Je mets ça aux bons endroits dans mon Proxmox VE avec un :&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;sudo make install
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo ldconfig
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="builder-comme-jamais"&gt;Builder comme jamais
&lt;/h2&gt;&lt;p&gt;Ok, c&amp;rsquo;est parti pour jouer &lt;strong&gt;avec mon fork&lt;/strong&gt; :&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;git clone https://github.com/zwindler/lxcri.git lxcri.zwindler
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; lxcri.zwindler
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&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;make build
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; go build -ldflags &lt;span class="s1"&gt;&amp;#39;-X main.version=8805687-dirty -X github.com/lxc/lxcri.defaultLibexecDir=/usr/local/libexec/lxcri&amp;#39;&lt;/span&gt; -o lxcri ./cmd/lxcri
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; cc -Werror -Wpedantic -o lxcri-start cmd/lxcri-start/lxcri-start.c &lt;span class="k"&gt;$(&lt;/span&gt;pkg-config --libs --cflags lxc&lt;span class="k"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;CGO_ENABLED&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt; go build -o lxcri-init ./cmd/lxcri-init
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# this is paranoia - but ensure it is statically compiled&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ! ldd lxcri-init 2&amp;gt;/dev/null
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; go build -o lxcri-hook ./cmd/lxcri-hook
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; go build -o lxcri-hook-builtin ./cmd/lxcri-hook-builtin
&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;ls -alrt
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; total &lt;span class="m"&gt;15288&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;[&lt;/span&gt;...&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -rwxr-xr-x &lt;span class="m"&gt;1&lt;/span&gt; debian debian &lt;span class="m"&gt;7108288&lt;/span&gt; Nov &lt;span class="m"&gt;16&lt;/span&gt; 20:06 lxcri
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -rwxr-xr-x &lt;span class="m"&gt;1&lt;/span&gt; debian debian &lt;span class="m"&gt;17520&lt;/span&gt; Nov &lt;span class="m"&gt;16&lt;/span&gt; 20:06 lxcri-start
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -rwxr-xr-x &lt;span class="m"&gt;1&lt;/span&gt; debian debian &lt;span class="m"&gt;2942584&lt;/span&gt; Nov &lt;span class="m"&gt;16&lt;/span&gt; 20:06 lxcri-init
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -rwxr-xr-x &lt;span class="m"&gt;1&lt;/span&gt; debian debian &lt;span class="m"&gt;2834743&lt;/span&gt; Nov &lt;span class="m"&gt;16&lt;/span&gt; 20:06 lxcri-hook
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -rwxr-xr-x &lt;span class="m"&gt;1&lt;/span&gt; debian debian &lt;span class="m"&gt;2519097&lt;/span&gt; Nov &lt;span class="m"&gt;16&lt;/span&gt; 20:06 lxcri-hook-builtin
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Si on était sur une machine de dev, on pourrait envoyer les binaires sur le serveur Proxmox VE (lxcri dans /usr/local/bin, le reste dans /usr/local/libexec/lxcri).&lt;/p&gt;
&lt;p&gt;Dans mon cas, je suis directement sur la machine qui build et qui run, je fais donc :&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;$ sudo make install
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; mkdir -p /usr/local/bin
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; cp -v lxcri /usr/local/bin
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s1"&gt;&amp;#39;lxcri&amp;#39;&lt;/span&gt; -&amp;gt; &lt;span class="s1"&gt;&amp;#39;/usr/local/bin/lxcri&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; mkdir -p /usr/local/libexec/lxcri
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; cp -v lxcri-start lxcri-init lxcri-hook lxcri-hook-builtin /usr/local/libexec/lxcri
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s1"&gt;&amp;#39;lxcri-start&amp;#39;&lt;/span&gt; -&amp;gt; &lt;span class="s1"&gt;&amp;#39;/usr/local/libexec/lxcri/lxcri-start&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s1"&gt;&amp;#39;lxcri-init&amp;#39;&lt;/span&gt; -&amp;gt; &lt;span class="s1"&gt;&amp;#39;/usr/local/libexec/lxcri/lxcri-init&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s1"&gt;&amp;#39;lxcri-hook&amp;#39;&lt;/span&gt; -&amp;gt; &lt;span class="s1"&gt;&amp;#39;/usr/local/libexec/lxcri/lxcri-hook&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s1"&gt;&amp;#39;lxcri-hook-builtin&amp;#39;&lt;/span&gt; -&amp;gt; &lt;span class="s1"&gt;&amp;#39;/usr/local/libexec/lxcri/lxcri-hook-builtin&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;et on peut continuer :&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;$ /usr/local/bin/lxcri &lt;span class="nb"&gt;help&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; lxcri - lxcri is a OCI compliant runtime wrapper &lt;span class="k"&gt;for&lt;/span&gt; lxc
&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;USAGE:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; lxcri &lt;span class="o"&gt;[&lt;/span&gt;global options&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="nb"&gt;command&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;command&lt;/span&gt; options&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;arguments...&lt;span class="o"&gt;]&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;VERSION:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="m"&gt;8805687&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;[&lt;/span&gt;...&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="on-reprend-crio"&gt;On reprend crio
&lt;/h2&gt;&lt;p&gt;Ok, on a buildé lxcri et on a toutes les dépendances pour l&amp;rsquo;utiliser. On peut donc repartir sur la doc officielle de lxcri &amp;ldquo;&lt;a class="link" href="https://github.com/lxc/lxcri/blob/main/doc/setup.md" target="_blank" rel="noopener"
&gt;setup.md&lt;/a&gt;&amp;rdquo; dans l&amp;rsquo;idée de configurer CRI-O, pour qu&amp;rsquo;il n&amp;rsquo;utilise pas runc, &lt;strong&gt;uniquement lxcri&lt;/strong&gt;.&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;sudo tee /etc/crio/crio.conf.d/10-crio.conf &amp;gt; /dev/null &lt;span class="s"&gt;&amp;lt;&amp;lt;&amp;#39;EOF&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;[crio.image]
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;signature_policy = &amp;#34;/etc/crio/policy.json&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;[crio.runtime]
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;default_runtime = &amp;#34;lxcri&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;[crio.runtime.runtimes.lxcri]
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;runtime_path = &amp;#34;/usr/local/bin/lxcri&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;runtime_type = &amp;#34;oci&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;runtime_root = &amp;#34;/var/lib/lxc&amp;#34; #proxmox lxc folder
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;inherit_default_runtime = false
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;runtime_config_path = &amp;#34;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;container_min_memory = &amp;#34;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;monitor_path = &amp;#34;/usr/libexec/crio/conmon&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;monitor_cgroup = &amp;#34;system.slice&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;monitor_exec_cgroup = &amp;#34;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;privileged_without_host_devices = false
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;EOF&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;A noter, la doc d&amp;rsquo;installation &lt;code&gt;setup.md&lt;/code&gt; nous dit générer une conf propre avec le binaire crio et la commande config, mais ça ne marche pas vraiment et on se retrouve à lancer runc ou crun sans le vouloir. J&amp;rsquo;écrase tout, c&amp;rsquo;est plus simple.&lt;/p&gt;
&lt;p&gt;Et maintenant, on peut lancer crio :&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;sudo systemctl &lt;span class="nb"&gt;enable&lt;/span&gt; crio &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; sudo systemctl start crio
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;A partir de là, on a un serveur disposant d&amp;rsquo;un CRI &lt;em&gt;a priori&lt;/em&gt; fonctionnel.&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;systemctl status crio
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;● crio.service - Container Runtime Interface &lt;span class="k"&gt;for&lt;/span&gt; OCI &lt;span class="o"&gt;(&lt;/span&gt;CRI-O&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Loaded: loaded &lt;span class="o"&gt;(&lt;/span&gt;/lib/systemd/system/crio.service&lt;span class="p"&gt;;&lt;/span&gt; enabled&lt;span class="p"&gt;;&lt;/span&gt; vendor preset: enabled&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Active: active &lt;span class="o"&gt;(&lt;/span&gt;running&lt;span class="o"&gt;)&lt;/span&gt; since Mon 2025-11-17 12:02:37 UTC&lt;span class="p"&gt;;&lt;/span&gt; 12s ago
&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;journalctl -u crio
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Nov &lt;span class="m"&gt;17&lt;/span&gt; 20:29:43 instance-2025-11-16-15-31-55 systemd&lt;span class="o"&gt;[&lt;/span&gt;1&lt;span class="o"&gt;]&lt;/span&gt;: Starting Container Runtime Interface &lt;span class="k"&gt;for&lt;/span&gt; OCI &lt;span class="o"&gt;(&lt;/span&gt;CRI-O&lt;span class="o"&gt;)&lt;/span&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;[&lt;/span&gt;...&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Nov &lt;span class="m"&gt;17&lt;/span&gt; 20:29:43 instance-2025-11-16-15-31-55 crio&lt;span class="o"&gt;[&lt;/span&gt;11906&lt;span class="o"&gt;]&lt;/span&gt;: &lt;span class="nv"&gt;time&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;2025-11-17T20:29:43.61758425Z&amp;#34;&lt;/span&gt; &lt;span class="nv"&gt;level&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;info &lt;span class="nv"&gt;msg&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Using runtime handler lxcri version 8805687&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Yeeees :D&lt;/p&gt;
&lt;p&gt;On peut donc installer kubelet, puis l&amp;rsquo;ajouter à un cluster Kubernetes existant&lt;/p&gt;
&lt;h2 id="fast-forward"&gt;Fast forward
&lt;/h2&gt;&lt;p&gt;J&amp;rsquo;avais la flemme de monter un cluster propre avec &lt;a class="link" href="https://blog.zwindler.fr/2023/12/17/kubeadmcfg-introduction-api-kubeadm/" target="_blank" rel="noopener"
&gt;kubeadm ou autre, et d&amp;rsquo;enrôler ensuite un node à la main avec le token+sha&lt;/a&gt;. J&amp;rsquo;aurais aussi pu rejouer avec mon PoC rigolo des &lt;a class="link" href="https://blog.zwindler.fr/2025/07/20/kubernetes-sur-clever-cloud-linux/" target="_blank" rel="noopener"
&gt;workers &amp;ldquo;linux&amp;rdquo; de Clever Cloud pour créer un control plane&lt;/a&gt; chez Clever, puis enrôler à la main avec le node bootstrap token (j&amp;rsquo;ai fait les choses plutôt bien dans ce PoC).&lt;/p&gt;
&lt;p&gt;J&amp;rsquo;ai donc rejoué à l&amp;rsquo;arrache avec mon projet &lt;a class="link" href="https://github.com/zwindler/demystifions-kubernetes/tree/main" target="_blank" rel="noopener"
&gt;demystifions-kubernetes&lt;/a&gt;, qui permet de monter un cluster mono node à la main en lançant juste des binaires.&lt;/p&gt;
&lt;p&gt;Une fois le control plane bootstrapé (etcd, api-server, controller-manager, scheduler), on s&amp;rsquo;arrête AVANT la partie containerd (on a déjà configuré CRI-O) et on lance le kubelet à la main :&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;sudo bin/kubelet --kubeconfig admin.conf --container-runtime-endpoint --container-runtime-endpoint=unix:///var/run/crio/crio.sock --fail-swap-on=false --cgroup-driver=&amp;#34;systemd&amp;#34;
[...]
I1117 13:41:58.741561 88434 kubelet_node_status.go:78] &amp;#34;Successfully registered node&amp;#34; node=&amp;#34;instance-2025-11-16-15-31-55&amp;#34;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;On progresse ! Essayons de voir l&amp;rsquo;état de santé du cluster et de déployer un pod :&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;$ &lt;span class="nb"&gt;export&lt;/span&gt; &lt;span class="nv"&gt;KUBECONFIG&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;admin.conf
&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; instance-2025-11-16-15-31-55 Ready &amp;lt;none&amp;gt; 13m v1.34.2
&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 create deployment web --image&lt;span class="o"&gt;=&lt;/span&gt;zwindler/vhelloworld
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; deployment.apps/web created
&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&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get pods
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; NAME READY STATUS RESTARTS AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; web-6c8cc48c68-cdbtj 1/1 Running &lt;span class="m"&gt;0&lt;/span&gt; 4m17s
&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 logs web-6c8cc48c68-cdbtj
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;[&lt;/span&gt;Vweb&lt;span class="o"&gt;]&lt;/span&gt; Running app on http://localhost:8081/
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;[&lt;/span&gt;Vweb&lt;span class="o"&gt;]&lt;/span&gt; We have &lt;span class="m"&gt;3&lt;/span&gt; workers
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;blockquote&gt;
&lt;p&gt;Great success!&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="conclusion"&gt;Conclusion
&lt;/h2&gt;&lt;p&gt;A partir de là, CRI-O partage le moteur LXC de Proxmox VE de manière fonctionnelle.&lt;/p&gt;
&lt;p&gt;Pour s&amp;rsquo;en convaincre, on peut lancer la commande lxc-ls, qui nous affichera un mix de &amp;ldquo;vrais&amp;rdquo; containers LXC (créés avec Proxmox, les 151 et 200) et de containers de pods (les STOPPED sont les init containers de cilium) :&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;$ lxc-ls -f
NAME STATE AUTOSTART GROUPS IPV4 IPV6 UNPRIVILEGED
151 STOPPED 0 - - - true
200 STOPPED 0 - - - true
3045d1f3abcc069b1009acc869a27b09cf9531d0701a3f9d5a760213d57c7b20 STOPPED 0 - - - false
78057100e5d0613944c2be859dfd09f790eeba88bceebea0e04970841c9bd950 RUNNING 0 - 10.0.0.90 - false
8e5506beea9a50214c46f31fa7fa6d04397963cb912aa397261359865d40a0cd RUNNING 0 - 10.0.0.167, 10.244.0.1, 203.0.113.42, 192.168.1.10 2001:db8::1 false
abdcd5be0a27417aa9e11cc2b27882bc86a63d94f547f909332ca7470a5e075a STOPPED 0 - - - false
aeaed9c2f56328bb6196ede4a78f06c4bb2d3edf5dca7912cf38407b9bf6610a STOPPED 0 - - - false
ed9aaf5a0fd4b11be121296290472d6d71d9016e4c6bb0d05fb2e4a7f4b7a85d RUNNING 0 - 10.0.0.167, 10.244.0.1, 203.0.113.42, 192.168.1.10 2001:db8::1 false
edb9d42e35a4029cfec5bed5597746bdf67fbe438f21446230252265ed1c849d STOPPED 0 - - - false
$ ps -ef |grep ed9aaf5a0fd4b11be121296290472d6d71d9016e4c6bb0d05fb2e4a7f4b7a85d
root 2674943 1 0 22:32 ? 00:00:00 /usr/libexec/crio/conmon -b /run/containers/storage/overlay-containers/ed9aaf5a0fd4b11be121296290472d6d71d9016e4c6bb0d05fb2e4a7f4b7a85d/userdata -c ed9aaf5a0fd4b11be121296290472d6d71d9016e4c6bb0d05fb2e4a7f4b7a85d --exit-dir /var/run/crio/exits -l /var/log/pods/kube-system_cilium-operator-56d6cd6767-dps78_6082ea2d-331e-4262-b8b3-d3f88eb4e446/cilium-operator/1.log --log-level info -n k8s_cilium-operator_cilium-operator-56d6cd6767-dps78_kube-system_6082ea2d-331e-4262-b8b3-d3f88eb4e446_1 -P /run/containers/storage/overlay-containers/ed9aaf5a0fd4b11be121296290472d6d71d9016e4c6bb0d05fb2e4a7f4b7a85d/userdata/conmon-pidfile -p /run/containers/storage/overlay-containers/ed9aaf5a0fd4b11be121296290472d6d71d9016e4c6bb0d05fb2e4a7f4b7a85d/userdata/pidfile --persist-dir /var/lib/containers/storage/overlay-containers/ed9aaf5a0fd4b11be121296290472d6d71d9016e4c6bb0d05fb2e4a7f4b7a85d/userdata -r /usr/local/bin/lxcri --runtime-arg --root=/var/lib/lxc --socket-dir-path /var/run/crio --syslog -u ed9aaf5a0fd4b11be121296290472d6d71d9016e4c6bb0d05fb2e4a7f4b7a85d -s
root 2674951 2674943 0 22:32 ? 00:00:00 /usr/local/libexec/lxcri/lxcri-start ed9aaf5a0fd4b11be121296290472d6d71d9016e4c6bb0d05fb2e4a7f4b7a85d /var/lib/lxc /var/lib/lxc/ed9aaf5a0fd4b11be121296290472d6d71d9016e4c6bb0d05fb2e4a7f4b7a85d/config
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Rien ne nous empêcherait ensuite de pousser le vice, et de faire un petit script qui récupère toutes les informations des containers, et crée les fichiers &lt;code&gt;/etc/pve/lxc/xxx.conf&lt;/code&gt; associés de manière à les afficher dans l&amp;rsquo;UI, comme je l&amp;rsquo;avais fait dans l&amp;rsquo;article :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://blog.zwindler.fr/2022/11/07/containers-docker-dans-proxmox-avec-lxc/" target="_blank" rel="noopener"
&gt;Lancer des containers Docker avec Proxmox VE (et LXC)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;En théorie, si cette étape avait du sens, je pourrais créer les releases moi-même sur mon fork pour faciliter l&amp;rsquo;installation.&lt;/p&gt;
&lt;p&gt;Enfin, je pourrais essayer de contribuer mes modifications pour que tout soit mergé sur le projet principal, à ceci près que &lt;a class="link" href="https://github.com/lxc/lxcri/issues/67#issuecomment-2055724867" target="_blank" rel="noopener"
&gt;les mainteneurs refusent les PRs car le projet n&amp;rsquo;est plus maintenu&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Mais j&amp;rsquo;avoue qu&amp;rsquo;après probablement une quinzaine d&amp;rsquo;heures de debug, de Golang, de compilation C, réparties sur 2 ans, j&amp;rsquo;ai un peu été au bout de ma patience pour cette &amp;ldquo;blague&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;OK, c&amp;rsquo;était débile, maintenant que j&amp;rsquo;ai réussi, dodo X_X.&lt;/p&gt;</description></item><item><title>QNAP débranche LXC sur les NAS ARM : comment contourner ?</title><link>https://blog.zwindler.fr/2022/06/13/qnap-debranche-lxc-workaround/</link><pubDate>Mon, 13 Jun 2022 08:00:00 +0200</pubDate><guid>https://blog.zwindler.fr/2022/06/13/qnap-debranche-lxc-workaround/</guid><description>&lt;img src="https://blog.zwindler.fr/2018/01/qnap22.webp" alt="Featured image of post QNAP débranche LXC sur les NAS ARM : comment contourner ?" /&gt;&lt;p&gt;Si vous le suivez sur Twitter ou Masto, vous m&amp;rsquo;avez très probablement lu râler contre la sortie &lt;del&gt;de QTS 5&lt;/del&gt; Container Station v2.4.0.2316, l&amp;rsquo;été dernier.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://preview.redd.it/6bouewrhnze71.png?width=1283&amp;amp;format=png&amp;amp;auto=webp&amp;amp;s=11aacee53bf931b47d1534cc1478b47aa7239701"
loading="lazy"
&gt;&lt;/p&gt;
&lt;p&gt;Ou plus particulièrement, contre une décision prise lors de ce passage : enlever LXC pour l&amp;rsquo;administration des containers, au profit de LXD. LXD étant juste une couche d&amp;rsquo;administration, LXC est toujours présent et fonctionnel, juste caché.&lt;/p&gt;
&lt;p&gt;Pourquoi je râle ?&lt;/p&gt;
&lt;p&gt;J&amp;rsquo;ai un &lt;a class="link" href="https://blog.zwindler.fr/2018/01/23/stockage-pour-un-admin-geek-qnap-ts431p2-ou-synology-ds418j" &gt;NAS QNAP TS431P2 depuis 2018 dont je suis pleinement satisfait&lt;/a&gt;, et qui m&amp;rsquo;a permis de passer moins de temps à administrer et ajouter des fonctionnalités à mon NAS ZFS maison, monté initialement en 2011 (merci &lt;em&gt;Dworak_of_sky&lt;/em&gt; pour les souvenirs).&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://blog.zwindler.fr/2011/06/29/nasmediacenter-do-it-yourself-or-not/" &gt;NAS/MediaCenter : Do It (the hardware part) Yourself!&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://blog.zwindler.fr/2011/08/04/nasmediacenter-do-it-the-software-part-yourself/" &gt;NAS/MediaCenter : Do It (the software part) Yourself!&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Sauf&lt;/strong&gt; que mon QNAP est un NAS milieu de gamme, fonctionnant avec &lt;em&gt;un processeur ARM&lt;/em&gt; et pas x86 ! Et ces charmantes personnes (grrrr) de chez QNAP &lt;strong&gt;n&amp;rsquo;ont pas porté LXD sur les NAS ARM&lt;/strong&gt; (segmentation artificielle de l&amp;rsquo;offre ? Flemme ?).&lt;/p&gt;
&lt;p&gt;Nous, propriétaires de NAS QNAP ARM, nous retrouvons donc sans solution puisque LXC est désactivé et LXD pas disponible.&lt;/p&gt;
&lt;p&gt;Une fonction hyper pratique pour héberger de petits services à bas coût (autant en performance qu&amp;rsquo;en prix) disparaît. C&amp;rsquo;était un réel différenciant pour ce modèle et je me sens vraiment trahi (ou alors c&amp;rsquo;est ma faute, car je n&amp;rsquo;aurais pas dû leur faire confiance ?).&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.zwindler.fr/2022/06/trahison.avif"
loading="lazy"
&gt;&lt;/p&gt;
&lt;p&gt;Je ne suis pas près de recommander QNAP comme j&amp;rsquo;ai pu le faire par le passé. #PasContent&lt;/p&gt;
&lt;h2 id="nuance"&gt;Nuance
&lt;/h2&gt;&lt;p&gt;HEUREUSEMENT, les containers LXC ne se sont pas mis à ne plus marcher du jour au lendemain.&lt;/p&gt;
&lt;p&gt;Enfin, encore heureux ! Je n&amp;rsquo;ose imaginer les dégâts en prod !&lt;/p&gt;
&lt;p&gt;C&amp;rsquo;est d&amp;rsquo;autant plus vicelard que le message d&amp;rsquo;information pour expliquer qu&amp;rsquo;il n&amp;rsquo;y a plus LXC indique que c&amp;rsquo;est pas grave puisque vous avez LXD à la place. Aucune mention du fait qu&amp;rsquo;en fait, sous ARM, non&amp;hellip;&lt;/p&gt;
&lt;p&gt;Il est toujours possible (&lt;strong&gt;pour l&amp;rsquo;instant&lt;/strong&gt;) de démarrer, arrêter, utiliser et supprimer les containers existants. Mais il n&amp;rsquo;est plus possible d&amp;rsquo;en créer de nouveaux.&lt;/p&gt;
&lt;p&gt;Ça veut donc dire que tout est encore présent pour faire fonctionner la fonctionnalité, ce n&amp;rsquo;est &amp;ldquo;juste&amp;rdquo; plus disponible en UI.&lt;/p&gt;
&lt;h2 id="en-avoir-le-coeur-net"&gt;En avoir le coeur net
&lt;/h2&gt;&lt;p&gt;En farfouillant, je me suis aussi rendu compte qu&amp;rsquo;il était toujours possible d&amp;rsquo;&lt;strong&gt;exporter&lt;/strong&gt; des containers existants et d&amp;rsquo;&lt;strong&gt;importer&lt;/strong&gt; les exports.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.zwindler.fr/2022/06/qnap_export.avif"
loading="lazy"
&gt;
&lt;img src="https://blog.zwindler.fr/2022/06/qnap_import.avif"
loading="lazy"
&gt;&lt;/p&gt;
&lt;p&gt;On peut donc contourner la limitation arbitraire de QNAP via des export / import. J&amp;rsquo;ai l&amp;rsquo;habitude de ce genre de bidouilles, &lt;a class="link" href="https://blog.zwindler.fr/2011/03/20/copier-une-vm-windows-xp-sous-esxi-sans-vcenter/" target="_blank" rel="noopener"
&gt;puisque je faisais déjà ça il y a plus de 10 ans avec les hyperviseurs VMware en licence gratuite&lt;/a&gt;&amp;hellip;&lt;/p&gt;
&lt;p&gt;A l&amp;rsquo;usage, ça fonctionne mais c&amp;rsquo;est pas satisfaisant. D&amp;rsquo;abord parce que si on a pas, ou plus, de containers sur le NAS, on ne peut pas le faire trivialement.&lt;/p&gt;
&lt;p&gt;Ensuite, parce que le processus et long (l&amp;rsquo;export et l&amp;rsquo;import) et pénible (plusieurs étapes).&lt;/p&gt;
&lt;p&gt;Enfin, parce que les images LXC mises à disposition par QNAP étaient antédiluviennes !&lt;/p&gt;
&lt;p&gt;Ubuntu 14.04 !!! Sauf si vous avez pris le temps de faire le processus d&amp;rsquo;upgrade complet de 14.04 à 20.04 ou 22.04 (et vous devriez), il est probable que vous n&amp;rsquo;ayez pas envie de repartir de ces vieux machins.&lt;/p&gt;
&lt;h2 id="faites-mieux"&gt;&amp;ldquo;Faites mieux&amp;rdquo;
&lt;/h2&gt;&lt;p&gt;Si vous êtes admin, vous avez probablement déjà activé SSH pour vous connecter directement à l&amp;rsquo;OS de votre NAS. (&lt;a class="link" href="https://www.qnap.com/fr-fr/how-to/knowledge-base/article/how-to-access-qnap-nas-by-ssh" target="_blank" rel="noopener"
&gt;Et sinon vous pouvez aller ici pour l&amp;rsquo;activer&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;Une fois connecté, on peut sortir du menu TUI et bidouiller l&amp;rsquo;OS comme on en a envie.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.zwindler.fr/2022/06/qnap_ssh_admin.avif"
loading="lazy"
&gt;&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;[~] # id
uid=0(admin) gid=0(administrators)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Je n&amp;rsquo;ai pas fait beaucoup d&amp;rsquo;administration LXC/LXD directement, car j&amp;rsquo;avais toujours une interface à ma disposition pour me &amp;ldquo;cacher&amp;rdquo; la façon dont ça fonctionne vraiment, que ce soit dans le cas de QNAP ou de &lt;a class="link" href="https://blog.zwindler.fr/recherche/?keyword=lxc" target="_blank" rel="noopener"
&gt;Proxmox VE (que j&amp;rsquo;utilise beaucoup pour ça)&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;En lisant rapidement &lt;a class="link" href="https://doc.ubuntu-fr.org/lxc" target="_blank" rel="noopener"
&gt;la doc sur ubuntu-fr&lt;/a&gt;, j&amp;rsquo;ai compris qu&amp;rsquo;il existait en fait chez Canonical un genre de dépôt d&amp;rsquo;images officielles de pleins d&amp;rsquo;OS, notamment compatible &lt;strong&gt;armhf&lt;/strong&gt;.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://images.lxd.canonical.com/" target="_blank" rel="noopener"
&gt;images.lxd.canonical.com/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="http://images.linuxcontainers.org//meta/1.0/index-system" target="_blank" rel="noopener"
&gt;images.linuxcontainers.org//meta/1.0/index-system&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Avec LXC, on peut accéder directement à ces images en ligne de commande avec &lt;code&gt;lxc-download&lt;/code&gt;. Pas de bol, la commande n&amp;rsquo;est pas dispo sur QTS :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-console" data-lang="console"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt;[~] # lxc-download
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt;-sh: lxc-download: command not found
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;(En fait elle n&amp;rsquo;est juste pas dans le PATH, mais je ne le savais pas à ce moment-là)&lt;/p&gt;
&lt;p&gt;Sauf qu&amp;rsquo;on peut aussi appeler directement la commande pour créer des containers &lt;code&gt;lxc-create&lt;/code&gt; avec un flag &amp;ldquo;download&amp;rdquo;. Et ça tombe bien parce que &lt;code&gt;lxc-create&lt;/code&gt; est disponible. Mais la joie sera de courte durée&amp;hellip;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-console" data-lang="console"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt;lxc-create -t download -n container_jammy -- -d ubuntu -r jammy -a armhf
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt;/usr/local/container-station/lxc/share/lxc/templates/lxc-download: line 237: getopt: command not found
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="hack"&gt;Hack&amp;hellip;
&lt;/h2&gt;&lt;p&gt;Note : si vous trouviez que ce qu&amp;rsquo;on était en train de faire n&amp;rsquo;était déjà pas très propre, je tiens à vous prévenir, la suite est vraiment immonde&amp;hellip; Pas merci QNAP de me forcer à faire ça !&lt;/p&gt;
&lt;p&gt;Le script &lt;code&gt;/usr/local/container-station/lxc/share/lxc/templates/lxc-download&lt;/code&gt; est moisi. Il manque la moitié des binaires dans la busybox.&lt;/p&gt;
&lt;p&gt;Pire encore, la procédure que je donne ici semble être écrasée à chaque mise à jour de l&amp;rsquo;application &lt;strong&gt;Container Station&lt;/strong&gt;. Mais, ça fonctionne&amp;hellip;&lt;/p&gt;
&lt;p&gt;La première chose qu&amp;rsquo;on va faire, c&amp;rsquo;est faire une sauvegarde du script &lt;code&gt;lxc-download&lt;/code&gt; par sécurité.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-console" data-lang="console"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt;cp /usr/local/container-station/lxc/share/lxc/templates/lxc-download{,.old}
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Le premier message d&amp;rsquo;erreur qu&amp;rsquo;on a &lt;code&gt;getopt: command not found&lt;/code&gt; indique juste que de nombreux binaires &amp;ldquo;classiques&amp;rdquo; ne sont pas disponibles directement dans le shell de QTS.&lt;/p&gt;
&lt;p&gt;Sauf qu&amp;rsquo;en fait, ils sont là, ces binaires. Pas besoin de les télécharger ou de les compiler. Ils ne sont juste &amp;ldquo;pas visibles&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;QTS tourne, comme beaucoup de serveurs Linux minimalistes, avec &lt;a class="link" href="https://fr.wikipedia.org/wiki/BusyBox" target="_blank" rel="noopener"
&gt;l&amp;rsquo;aide de Busybox&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;On peut donc &amp;ldquo;magiquement activer&amp;rdquo; les binaires qui nous manquent simplement avec des liens symboliques.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-console" data-lang="console"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt;for binary in getopt xz seq; do
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt; ln -s /share/CACHEDEV1_DATA/.qpkg/container-station/bin/busybox /share/CACHEDEV1_DATA/.qpkg/container-station/bin/${binary}
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt;done
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt;getopt
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt;getopt: missing optstring argument
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="-and-slash"&gt;&amp;hellip; and slash!
&lt;/h2&gt;&lt;blockquote&gt;
&lt;p&gt;C&amp;rsquo;est bon, mais pas suffisant.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;La version du binaire &lt;code&gt;mktemp&lt;/code&gt; de busybox n&amp;rsquo;est malheureusement PAS compatible avec le script &lt;code&gt;lxc-download&lt;/code&gt;. On va devoir le modifier à la main&amp;hellip;&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;Usage: mktemp [-dq] TEMPLATE
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Le passage problématique se situe autour des lignes 320-325&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;&lt;span class="m"&gt;320&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; ! &lt;span class="nb"&gt;command&lt;/span&gt; -V mktemp &amp;gt;/dev/null 2&amp;gt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;1&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="m"&gt;321&lt;/span&gt; &lt;span class="nv"&gt;DOWNLOAD_TEMP&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;DOWNLOAD_TEMP&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/tmp/lxc-download.&lt;/span&gt;&lt;span class="nv"&gt;$$&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="m"&gt;322&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="m"&gt;323&lt;/span&gt; &lt;span class="nv"&gt;DOWNLOAD_TEMP&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;DOWNLOAD_TEMP&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;mktemp -d&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="m"&gt;324&lt;/span&gt; &lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;En vrai, &lt;code&gt;mktemp&lt;/code&gt; s&amp;rsquo;attend à avoir le path complet, accompagné d&amp;rsquo;un pattern à base de XXXXXX. &lt;code&gt;mktemp&lt;/code&gt; remplace ensuite les caractères XXXXXX par un nombre aléatoire en s&amp;rsquo;assurant que le dossier n&amp;rsquo;existe pas déjà, puis le créé. Par exemple&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;mktemp /tmp/mydirXXXXX
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Mode bourrin, j&amp;rsquo;ai remplacé la ligne par :&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;&lt;span class="m"&gt;323&lt;/span&gt; &lt;span class="nv"&gt;DOWNLOAD_TEMP&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;DOWNLOAD_TEMP&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/tmpdir&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; mkdir -p &lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;DOWNLOAD_TEMP&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;De toute façon, il est supprimé à la fin de l&amp;rsquo;exécution du script, ce dossier (fonction cleanup dans le shell).&lt;/p&gt;
&lt;h2 id="gpg"&gt;GPG
&lt;/h2&gt;&lt;p&gt;On progresse !&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-console" data-lang="console"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt;[~] # lxc-create -t download -n container_jammy -- -d ubuntu -r jammy -a armhf
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt;Setting up the GPG keyring
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt;chmod: /var/lib/lxc/container_jammy/tmpdir/gpg: No such file or directory
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt;Error creating container container_jammy
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;En creusant un peu, la vraie erreur est que je n&amp;rsquo;ai pas le binaire &lt;code&gt;gpgkeys_curl&lt;/code&gt; à l&amp;rsquo;endroit attendu :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-console" data-lang="console"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt;gpg: unable to execute program `/opt/cross-project/arm/linaro/arm-linux-gnueabihf/libc/libexec/gnupg/gpgkeys_curl&amp;#39;: No such file or directory
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Voilà un autre point que je n&amp;rsquo;ai pas réussi à corriger correctement.&lt;/p&gt;
&lt;p&gt;Le plus simple est de simplement ignorer la validation avec &lt;code&gt;--no-validate&lt;/code&gt; mais si vous avez une piste, je suis preneur.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-console" data-lang="console"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt;lxc-create -t download -n container_jammy -- -d ubuntu -r jammy -a armhf --no-validate
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="des-dossiers-qui-disparaissent-tout-seul-"&gt;Des dossiers qui disparaissent tout seul ???
&lt;/h2&gt;&lt;p&gt;Dernier mystère&amp;hellip;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-console" data-lang="console"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt;Downloading the image index
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt;ERROR: Failed to download http://images.linuxcontainers.org//meta/1.0/index-system
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;L&amp;rsquo;erreur n&amp;rsquo;est pas du tout un problème d&amp;rsquo;accès à l&amp;rsquo;URL pour télécharger l&amp;rsquo;index des systèmes disponibles sur &lt;code&gt;images.linuxcontainers.org&lt;/code&gt; (code 302, page redirigée sur &lt;code&gt;uk.lxd.images.canonical.com&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;En réalité, si active les messages d&amp;rsquo;erreurs lors du &lt;code&gt;wget&lt;/code&gt; dans le script, l&amp;rsquo;erreur est que le dossier &lt;code&gt;/var/lib/lxc/container_jammy/tmpdir/&lt;/code&gt; n&amp;rsquo;existe pas !&lt;/p&gt;
&lt;p&gt;Pourtant, ça devrait être corrigé, suite à la modif qu&amp;rsquo;on a faite ligne 323 (voir plus haut)&amp;hellip; trop bizarre :/&lt;/p&gt;
&lt;p&gt;J&amp;rsquo;en ai eu un peu marre de creuser et au bout d&amp;rsquo;un moment, j&amp;rsquo;ai juste fait :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-console" data-lang="console"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt;export CONTAINER_NAME=jammy
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt;mkdir -p /var/lib/lxc/${CONTAINER_NAME}/tmpdir/
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt;mkdir -p /var/lib/lxc/${CONTAINER_NAME}/rootfs/
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt;lxc-create -t download -n ${CONTAINER_NAME} -- -d ubuntu -r jammy -a armhf --no-validate
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Et croyez-le ou non, mais ça marche ! Le container existe (il n&amp;rsquo;est juste pas visible dans la console pour l&amp;rsquo;instant)&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-console" data-lang="console"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt;[...]
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt;You just created an Ubuntu jammy armhf (20220611_07:42) container.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;On a plus qu&amp;rsquo;à redémarrer Container Station, il apparaît&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.zwindler.fr/2022/06/qnap_lxc_jammy.avif"
loading="lazy"
&gt;&lt;/p&gt;
&lt;h2 id="conclusion"&gt;Conclusion
&lt;/h2&gt;&lt;p&gt;Si jamais quelqu&amp;rsquo;un de chez QNAP lit ce blogpost&amp;hellip; Arrêtez de vous fiche de nous et :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;mettez nous LXD dans nos NAS ARM&lt;/li&gt;
&lt;li&gt;OU si c&amp;rsquo;est trop de boulot (je peux l&amp;rsquo;entendre), remettre LXC en attendant.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Ce genre de hack est indigne et j&amp;rsquo;ai perdu plusieurs heures pour corriger votre m***e. J&amp;rsquo;ai payé pour un NAS compatible LXC, ce n&amp;rsquo;est pas pour que vous retiriez la fonctionnalité 1 an après.&lt;/p&gt;
&lt;p&gt;Ce genre de pratiques est vraiment dégueulasse et je n&amp;rsquo;hésiterais pas à dire tout le mal que je pense de cette décision.&lt;/p&gt;
&lt;h2 id="sources"&gt;Sources
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://forum.qnap.com/viewtopic.php?t=159613" target="_blank" rel="noopener"
&gt;Un post sur le Forum QNAP qui m&amp;rsquo;a un peu guidé vers la solution&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://www.reddit.com/r/qnap/comments/owkr63/qnap_container_station_loss_of_functionality/" target="_blank" rel="noopener"
&gt;Un fil de discussion Reddit qui en parle&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Retrouvez-moi à Devoxx France 2022</title><link>https://blog.zwindler.fr/2022/04/18/retrouvez-moi-a-devoxx-2022/</link><pubDate>Mon, 18 Apr 2022 12:00:00 +0000</pubDate><guid>https://blog.zwindler.fr/2022/04/18/retrouvez-moi-a-devoxx-2022/</guid><description>&lt;img src="https://blog.zwindler.fr/2022/04/devoxx.webp" alt="Featured image of post Retrouvez-moi à Devoxx France 2022" /&gt;&lt;h2 id="jai-10-ans-"&gt;J&amp;rsquo;ai 10 ans 🎶
&lt;/h2&gt;&lt;p&gt;&lt;a class="link" href="https://www.devoxx.fr/" target="_blank" rel="noopener"
&gt;Devoxx France&lt;/a&gt; revient après deux ans de Covid (chaotique pour tout le monde) en présentiel total. Et ce n&amp;rsquo;est pas n&amp;rsquo;importe quelle édition de Devoxx, c&amp;rsquo;est l&amp;rsquo;année des 10 ans !&lt;/p&gt;
&lt;p&gt;Pour ceux qui ne sont pas familiers de cette conférence, Devoxx c&amp;rsquo;est :&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Conférence pour développeurs organisée par Quantixx au Palais des Congrès, à Paris. 60 exposants pendant 3 jours. 3000 visiteurs. 260 orateurs, 220 présentations, ateliers et plénières.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Et cette fois-ci, je serai présent sur les 3 jours, en particulier le jeudi puisque je donnerai mon talk &amp;ldquo;Ciel, mon Kubernetes mine des bitcoins&amp;rdquo; (&lt;a class="link" href="https://blog.zwindler.fr/talks/2022-ciel-kubernetes-mine-bitcoins/index.html" target="_blank" rel="noopener"
&gt;slides ici, comme d&amp;rsquo;habitude&lt;/a&gt;). &lt;strong&gt;Je donnerai la conférence le jeudi à 14:30 en salle 243&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;J&amp;rsquo;en parle dans mon billet sur &lt;a class="link" href="https://blog.zwindler.fr/2022/03/30/combien-temps-pour-preparer-conf/" target="_blank" rel="noopener"
&gt;le temps que je mets à préparer une conférence&lt;/a&gt;, être sélectionné à des conférences, c&amp;rsquo;est compliqué, mais à Devoxx encore plus. Il y a beaucoup de speakers expérimentés et de nombreux talks passionnants en simultanée.&lt;/p&gt;
&lt;p&gt;Je suis donc particulièrement content de faire partie des heureux élus :). Une superbe occasion de revoir (ou rencontrer IRL) des copains des Internets et des anciens collègues (va même falloir faire une liste je crois 😅).&lt;/p&gt;
&lt;h2 id="comment-on-fait-pour-venir-"&gt;Comment on fait pour venir ?
&lt;/h2&gt;&lt;p&gt;Evidemment, il est trop tard pour prendre un billet pour les conférences (ça part en quelques heures), mais cette année il est possible d&amp;rsquo;accéder au salon et aux stands d&amp;rsquo;exposants gratuitement, et même d&amp;rsquo;accéder à certaines conférences, le jeudi soir.&lt;/p&gt;
&lt;p&gt;Seule condition, avoir un billet (gratuit du coup je le répète) pour avoir accès aux stands ou aux BOF (événement terminé).&lt;/p&gt;
&lt;p&gt;Dans tous les cas, que vous ayez un billet conférence, speaker ou &amp;ldquo;salon&amp;rdquo;, n&amp;rsquo;hésitez pas à me pinger sur &lt;a class="link" href="https://bsky.app/profile/zwindler.fr" target="_blank" rel="noopener"
&gt;Bluesky&lt;/a&gt;, Mastodon (@zwindler@framapiaf.org) ou &lt;a class="link" href="https://www.linkedin.com/in/denis-germain/" target="_blank" rel="noopener"
&gt;LinkedIn&lt;/a&gt; si vous voulez me faire un coucou 👋, ça sera avec grand plaisir !&lt;/p&gt;
&lt;h2 id="le-pitch-de-mon-talk"&gt;Le pitch de mon talk
&lt;/h2&gt;&lt;blockquote&gt;
&lt;p&gt;A tort ou à raison, Kubernetes s’est imposé, ces 4 dernières années, comme un des nouveaux standards dans la gestion des architectures microservices modernes.&lt;/p&gt;
&lt;p&gt;Cependant cet outil, riche plus que complexe, amène son lot de pièges dans lesquels les débutants ne manqueront pas de tomber… Et ce n’est pas l’apparente facilité apportée par les offres Kubernetes as a Service qui va arranger les choses !&lt;/p&gt;
&lt;p&gt;Après un rapide tour de l’actualité sécurité autour de Kubernetes, je vous donnerai les clés pour éviter de vous faire voler (trop facilement) vos cycles CPU.&lt;/p&gt;
&lt;/blockquote&gt;</description></item><item><title>Android Auto sur R-LINK 1 - Chérie, j'ai briqué la voiture...</title><link>https://blog.zwindler.fr/2022/04/08/androidauto-rlink1-cherie-jai-brique-la-voiture/</link><pubDate>Fri, 08 Apr 2022 16:00:00 +0000</pubDate><guid>https://blog.zwindler.fr/2022/04/08/androidauto-rlink1-cherie-jai-brique-la-voiture/</guid><description>&lt;img src="https://blog.zwindler.fr/2022/04/androidauto_ok.webp" alt="Featured image of post Android Auto sur R-LINK 1 - Chérie, j'ai briqué la voiture..." /&gt;&lt;h2 id="chérie-jai-briqué-la-voiture"&gt;Chérie, j&amp;rsquo;ai briqué la voiture
&lt;/h2&gt;&lt;p&gt;Qui n&amp;rsquo;a jamais eu envie de casser sa voiture en allant trifouiller dans les paramètres de l&amp;rsquo;ordinateur de bord ? Probablement personne, en fait&amp;hellip;&lt;/p&gt;
&lt;p&gt;Mais rassurez-vous, j&amp;rsquo;ai mis le titre pour la ref à &amp;ldquo;&lt;a class="link" href="https://fr.wikipedia.org/wiki/Ch%C3%A9rie,_j%27ai_r%C3%A9tr%C3%A9ci_les_gosses" target="_blank" rel="noopener"
&gt;chérie, j&amp;rsquo;ai rétréci les gosses&lt;/a&gt;&amp;rdquo;, film de mon enfance. &lt;em&gt;Aucun véhicule motorisé n&amp;rsquo;a été blessé lors de la réalisation de cet article&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Note de service : je vous conseille de NE PAS reproduire ça et je vous enverrai paitre si vous m&amp;rsquo;accusez d&amp;rsquo;avoir cassé votre RLINK suite à une mauvaise manipulation.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;D&amp;rsquo;abord un peu de contexte. Mon véhicule principal (même si je ne l&amp;rsquo;utilise pratiquement plus), date de 2014. A l&amp;rsquo;époque, Renault équipait ses nouveaux véhicules d&amp;rsquo;une tablette Android depuis 2012, modifiée avec une interface maison qu&amp;rsquo;ils appellent le RLINK (version 1 à l&amp;rsquo;époque), en partenariat avec Tomtom.&lt;/p&gt;
&lt;p&gt;Cette tablette est une vraie m***e. Buguée (l&amp;rsquo;autoradio se bloque même moteur coupé/voiture verrouillée, son à fond&amp;hellip; sympa pour la batterie), compatible avec à peu près aucune application (encore moins qui seraient utiles), cartographie payante (très chère), en retard de près de plus de 6 mois au moment où vous l&amp;rsquo;achetez et plus compatible avec la carte SD initiale car trop grande&amp;hellip;&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.zwindler.fr/2022/04/europe.avif"
loading="lazy"
&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;90€ pour une carte pas à jour, que je peux pas faire rentrer sur ma SD sur un système de navigation bugué : l&amp;rsquo;affaire du siècle !&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="android-auto-à-la-rescousse"&gt;Android Auto à la rescousse
&lt;/h2&gt;&lt;p&gt;A peu près au même moment, Google a annoncé en 2014-2015 la sortie du système Android Auto : vous connectez votre smartphone en USB à une tablette Android compatible, et hop, c&amp;rsquo;est les applications de votre smartphone que vous retrouvez à l&amp;rsquo;écran.&lt;/p&gt;
&lt;p&gt;Waze, Deezer, etc. Tout ce dont j&amp;rsquo;ai besoin pour de longs trajets !&lt;/p&gt;
&lt;p&gt;Sauf que la spec pour sélectionner les appareils compatibles avec le système Android Auto est sortie vraisemblablement un peu trop tard pour que Renault puisse rendre le système RLINK certifié compatible par Google&amp;hellip;&lt;/p&gt;
&lt;h2 id="quà-cela-ne-tienne"&gt;Qu&amp;rsquo;à cela ne tienne
&lt;/h2&gt;&lt;p&gt;Alors, si encore c&amp;rsquo;était vraiment pas conçu pour et qu&amp;rsquo;on ne pouvait pas du tout l&amp;rsquo;avoir pour de bonnes raisons techniques, j&amp;rsquo;en aurais fait mon deuil et j&amp;rsquo;aurais payé des cartographies comme tous les autres automobilistes captifs de leur constructeur&amp;hellip;&lt;/p&gt;
&lt;p&gt;Sauf qu&amp;rsquo;assez vite, je suis tombé sur des posts de gens qui avaient réussi à &amp;ldquo;activer&amp;rdquo; Waze sur leur RLINK-1.&lt;/p&gt;
&lt;p&gt;Et je dis bien &amp;ldquo;activer&amp;rdquo;. Car la fonctionnalité est intégrée à la tablette, il y a &amp;ldquo;juste&amp;rdquo; un booléen à passer à true pour que ça fonctionne&amp;hellip; de quoi piquer ma curiosité.&lt;/p&gt;
&lt;p&gt;Bon&amp;hellip; en vrai, il a fallu que je m&amp;rsquo;y reprenne plusieurs fois avant de réussir à le faire marcher, car il y a pas mal d&amp;rsquo;étapes et d&amp;rsquo;embûches. Il existe depuis 2018 un tutoriel pour y parvenir, disponible sur le site &lt;a class="link" href="http://www.gps-carminat.com/v3/r-link/activer-android-auto-waze-sur-r-link-1/" target="_blank" rel="noopener"
&gt;gps-carminat.com&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Le but de cet article n&amp;rsquo;est pas de faire une redite des informations présentes sur ce site. Mais comme souvent, les tutos qu&amp;rsquo;on trouve sur le net ne sont pas toujours hypers clairs, pas toujours très jours, omettent des choses&amp;hellip; Et je sais pas vous mais je trouve quand même marrant (et dangereux) de toucher au soft de sa voiture donc je vous propose de vous montrer ce que j&amp;rsquo;ai fait pour arriver à mes fins.&lt;/p&gt;
&lt;h2 id="myrenault-ou-les-limbes-dun-logiciel-à-labandon"&gt;MyRenault ou les limbes d&amp;rsquo;un logiciel à l&amp;rsquo;abandon
&lt;/h2&gt;&lt;p&gt;Le premier prérequis avant de commencer à imaginer débloquer Android Auto sur un RLINK est d&amp;rsquo;abord de le mettre à jour (&amp;gt;11.343). Et c&amp;rsquo;est presque le plus difficile aujourd&amp;rsquo;hui, tant ce système est abandonné depuis des années par Renault&amp;hellip;&lt;/p&gt;
&lt;p&gt;Liens cassés, navigation pétée quelque-soit le navigateur, UI de l&amp;rsquo;enfer avec des liens cachés qui envoient vers des liens de liens&amp;hellip; Ca a l&amp;rsquo;air réparé aujourd&amp;rsquo;hui, mais ça n&amp;rsquo;a pas marché pendant plusieurs mois, me renvoyant systématiquement des erreurs&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;a class="link" href="https://www.renault.fr/?error=9" target="_blank" rel="noopener"
&gt;https://www.renault.fr/?error=9&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;img src="https://blog.zwindler.fr/2022/04/rlink.appli.avif"
loading="lazy"
&gt;&lt;/p&gt;
&lt;p&gt;En théorie, il faut se rendre sur &lt;a class="link" href="https://myr.renault.fr/r-link-store.html" target="_blank" rel="noopener"
&gt;myr.renault.fr, puis ouvrir le r-link-store&lt;/a&gt; une fois qu&amp;rsquo;on a sélectionné son véhicule.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.zwindler.fr/2022/04/comment_proc%c3%a9der.avif"
loading="lazy"
&gt;&lt;/p&gt;
&lt;p&gt;Là, on peut télécharger le RLINK Toolbox (un soft qui ne marche que sous Windows et MacOS) et suivre les instructions pour mettre à jour la tablette (via la carde SD que vous aurez probablement récupéré dans la voiture).&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://fr.rlinkstore.com/installation" target="_blank" rel="noopener"
&gt;fr.rlinkstore.com/installation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Le processus de mise à jour est pénible de mémoire mais ça fonctionne la plupart du temps (c&amp;rsquo;est juste très long et il faut un lecteur de carte SD). Une fois à jour, votre RLINK devrait ressembler à ça (ici j&amp;rsquo;ai la 11.346)&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.zwindler.fr/2022/04/rlink_up_to_date.avif"
loading="lazy"
&gt;&lt;/p&gt;
&lt;h2 id="matériel"&gt;Matériel
&lt;/h2&gt;&lt;p&gt;Pour hacker une voiture, il ne faut pas seulement du logiciel. Il va nous falloir du matériel et on va devoir mettre les mains dans le cambouis.&lt;/p&gt;
&lt;p&gt;Normalement, pour accéder à l&amp;rsquo;ordinateur de bord de la voiture, il existe une interface universelle appelée &lt;a class="link" href="https://fr.wikipedia.org/wiki/Diagnostic_embarqu%C3%A9_%28automobile%29" target="_blank" rel="noopener"
&gt;OBD-II&lt;/a&gt;. Vous connaissez surement ça sans le savoir, c&amp;rsquo;est ni plus ni moins que le port que votre garagiste branche quand &amp;ldquo;il branche la valise&amp;rdquo;, qui est un PC+écran et une interface OBD-2.&lt;/p&gt;
&lt;p&gt;Pendant longtemps, ce système était couteux et réservé aux pros car cher. Cependant, il existe maintenant depuis des années de boitiers USB, WIFI ou bluetooth qui permettent de faire l&amp;rsquo;interface avec la voiture. N&amp;rsquo;importe quel ordinateur devient donc une &amp;ldquo;valise de garagiste&amp;rdquo;, pour environ 20€.&lt;/p&gt;
&lt;p&gt;J&amp;rsquo;ai pris comme conseillé dans le tuto une sonde ELM (celle en WIFI, car l&amp;rsquo;USB n&amp;rsquo;était plus dispo) et une rallonge OBD.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.zwindler.fr/2022/04/20210217_155052.avif"
loading="lazy"
&gt;&lt;/p&gt;
&lt;p&gt;Note : pas de bol pour moi, la sonde WIFI n&amp;rsquo;a jamais marché et j&amp;rsquo;ai abandonné pendant plusieurs mois alors qu&amp;rsquo;il fallait juste en prendre une autre&amp;hellip; J&amp;rsquo;ai insisté récemment, en en prenant une autre, en USB, pas spécialement conseillée mais qui a très bien fonctionné.&lt;/p&gt;
&lt;p&gt;Comme chez Renault ce sont de petits blagueurs, on va aussi devoir modifier le cablâge de notre sonde (d&amp;rsquo;où la rallonge), car pour accéder au système OBD du RLINK, il faut changer de place certains fils !!!&lt;/p&gt;
&lt;p&gt;C&amp;rsquo;est très bien expliqué sur le tuto de gps-carminat :&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.zwindler.fr/2022/04/rallonge_obd.avif"
loading="lazy"
&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="http://www.gps-carminat.com/v3/r-link/activer-android-auto-waze-sur-r-link-1" target="_blank" rel="noopener"
&gt;www.gps-carminat.com/v3/r-link/activer-android-auto-waze-sur-r-link-1&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Grosso modo, ça donne ça :&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.zwindler.fr/2022/04/20210217_163410.avif"
loading="lazy"
&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.zwindler.fr/2022/04/20210217_164148.avif"
loading="lazy"
&gt;&lt;/p&gt;
&lt;h2 id="installer-ddt4all"&gt;Installer DDT4ALL
&lt;/h2&gt;&lt;p&gt;Le gros de modifs vont être réalisées à l&amp;rsquo;aide de l&amp;rsquo;outil DDT4ALL que Cédric PAILLE a gentiment opensourcé. Je lui ai fait un petit don et si ce soft vous ait utile je vous invite à faire de même.&lt;/p&gt;
&lt;p&gt;Sous Linux, il suffit de cloner le projet et d&amp;rsquo;installer quelques packages pip3&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;git clone https://github.com/cedricp/ddt4all.git &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;cd&lt;/span&gt; ddt4all
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pip3 install PyQt5
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pip3 install PyQtWebEngine
&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;python ddt4all.py
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Sous Windows, il y a un &lt;a class="link" href="https://github.com/cedricp/ddt4all/releases" target="_blank" rel="noopener"
&gt;installer de l&amp;rsquo;outil&lt;/a&gt;, compatible depuis novembre 2020 avec Windows 10 et Python 3 (ce qui n&amp;rsquo;était pas le cas lors de mes premiers tests)&lt;/p&gt;
&lt;p&gt;Dans les deux cas, on obtient une interface graphique pour modifier notre véhicule (hinhinhin).&lt;/p&gt;
&lt;h2 id="trouver-une-base-ddt2000"&gt;Trouver une base DDT2000
&lt;/h2&gt;&lt;p&gt;Vu que le tuto de gps-carminat ne propose pas de téléchargement pour cette partie ni même de liens pour la trouver&amp;hellip; je me demande si posséder ou partager cette base est totalement légal&amp;hellip;&lt;/p&gt;
&lt;p&gt;Enfin&amp;hellip; en insistant un peu on finit par trouver un fichier &lt;code&gt;DDT2000data.zip&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Cette partie n&amp;rsquo;est pas super claire dans le tuto. Il faut copier le dossier contenu dans l&amp;rsquo;archive, sans changer le nom &amp;ldquo;ddt2000data&amp;rdquo; dans &lt;code&gt;C:\Program Files (x86)\ddt4all&lt;/code&gt;. On se retrouve donc avec un dossier &lt;code&gt;C:\Program Files (x86)\ddt4all\ddt2000data&lt;/code&gt; avec plusieurs sous dossiers.&lt;/p&gt;
&lt;h2 id="brancher-la-sonde"&gt;Brancher la sonde
&lt;/h2&gt;&lt;p&gt;Si vous ne savez pas où brancher la sonde OBD sur votre voiture, &lt;a class="link" href="https://www.outilsobdfacile.fr/emplacement-prise-connecteur-obd.php" target="_blank" rel="noopener"
&gt;outilsobdfacile est un site qui permet, entre autres, de le trouver&lt;/a&gt;, quelque soit votre véhicule.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.zwindler.fr/2022/04/20210217_165655.avif"
loading="lazy"
&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.zwindler.fr/2022/04/20210217_165844.avif"
loading="lazy"
&gt;&lt;/p&gt;
&lt;h2 id="lancer-le-logiciel-ddt4all"&gt;Lancer le logiciel DDT4ALL
&lt;/h2&gt;&lt;p&gt;Cette partie-là n&amp;rsquo;était pas non plus hyper claire dans le tuto. Une fois la sonde choisie dans le premier menu, le tuto nous dit d&amp;rsquo;abord de cliquer sur l&amp;rsquo;icône Einstein [5] puis choisir le mode &amp;ldquo;After sale&amp;rdquo; dans le menu déroulant.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.zwindler.fr/2022/04/ddt4all_marche_a_suivre.avif"
loading="lazy"
&gt;&lt;/p&gt;
&lt;p&gt;En réalité, ce n&amp;rsquo;est pas (ou plus ?) du tout le bon ordre. Il faut d&amp;rsquo;abord choisir son véhicule [1] dans la première liste déroulante, tout en haut à gauche.&lt;/p&gt;
&lt;p&gt;Ensuite, on cherche le menu Navigation, puis MFD 5.4 [2] (le tuto parle de MFD 4.6 mais il n&amp;rsquo;existe pas sur mon véhicule).&lt;/p&gt;
&lt;p&gt;Et une fois qu&amp;rsquo;on l&amp;rsquo;a trouvé, on double clique dessus, ce qui le fait apparaitre dans le menu juste en dessous [3] et on clique là où il vient d&amp;rsquo;apparaitre.&lt;/p&gt;
&lt;p&gt;Une fois toutes ces étapes passées, on peut cliquer sur &amp;ldquo;Ecrans&amp;rdquo;, &amp;ldquo;Configuration&amp;rdquo; et chercher le fameux menu &lt;strong&gt;13 – ECU configuration ADAS&lt;/strong&gt; dans lequel configurer Android Auto [4].&lt;/p&gt;
&lt;p&gt;A partir de la seulement, on peut le sélectionner, &lt;strong&gt;puis&lt;/strong&gt; sélectionner le mode &amp;ldquo;After sales&amp;rdquo; [6]. J&amp;rsquo;ai tatônné un moment avant de comprendre ça.&lt;/p&gt;
&lt;p&gt;Après application des modifications, reboot de la tablette (5 fois Home) et branchement du smartphone, c&amp;rsquo;est une victoire :)&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.zwindler.fr/2022/04/androidauto_ok.avif"
loading="lazy"
&gt;&lt;/p&gt;
&lt;h2 id="sites-utiles"&gt;Sites utiles
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="http://www.gps-carminat.com/v3/r-link/activer-android-auto-waze-sur-r-link-1/" target="_blank" rel="noopener"
&gt;Le tutoriel de gps-carminat.com&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/cedricp/ddt4all" target="_blank" rel="noopener"
&gt;Le github de Cedric PAILLE / ddt4all&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://myr.renault.fr/r-link-store.html" target="_blank" rel="noopener"
&gt;Le lien de MyRenault / RLink Store&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://cdn.sa.services.tomtom.com/static/rltb/Windows/InstallRLinkToolbox.exe" target="_blank" rel="noopener"
&gt;Le lien direct pour télécharger la dernière version de RLink Toolbox&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://www.outilsobdfacile.fr/emplacement-prise-connecteur-obd/" target="_blank" rel="noopener"
&gt;outilsobdfacile, un site pour trouver l&amp;rsquo;emplacement pour brancher le connecteur OBD-2&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://www.tlemcen-electronic.com/forum/forumdisplay.php?f=96" target="_blank" rel="noopener"
&gt;Un forum qui parle de ces choses-là&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Open Source Experience 2021 – Récap’ du premier jour</title><link>https://blog.zwindler.fr/2021/11/10/open-source-experience-2021-recap/</link><pubDate>Wed, 10 Nov 2021 08:00:00 +0000</pubDate><guid>https://blog.zwindler.fr/2021/11/10/open-source-experience-2021-recap/</guid><description>&lt;img src="https://blog.zwindler.fr/2021/11/osxp_entrance.webp" alt="Featured image of post Open Source Experience 2021 – Récap’ du premier jour" /&gt;&lt;h2 id="première-conférence-en-présentiel-de-2021-"&gt;Première conférence en présentiel de 2021 !
&lt;/h2&gt;&lt;p&gt;Ca fait quelque chose&amp;hellip;&lt;/p&gt;
&lt;p&gt;Revenir&amp;hellip; IRL&amp;hellip; dans une conférence !&lt;/p&gt;
&lt;p&gt;Et quelle conférence ! Pour la première fois, je participais à l&amp;rsquo;Open Source Experience (que vous connaissez peut être sous son ancien nom, le &lt;em&gt;Paris Open Source Summit&lt;/em&gt;, voire Solution Linux pour les plus vieux 😉).&lt;/p&gt;
&lt;p&gt;Ca se passait au palais des congrès de Paris, porte Maillot, et je vous avais déjà dit que j&amp;rsquo;étais (en plus !) &lt;a class="link" href="https://blog.zwindler.fr/2021/10/11/osxp-2021-ciel-mon-kubernetes-mine-des-bitcoins/" &gt;speaker&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;L&amp;rsquo;occasion de voir des conférences, mais aussi de rencontrer pas mal de gens, que je &amp;ldquo;connaissais d&amp;rsquo;Internet&amp;rdquo; ou pas du tout.&lt;/p&gt;
&lt;h2 id="api--rest--procmail-à-la-rescousse"&gt;API != REST – procmail à la rescousse
&lt;/h2&gt;&lt;p&gt;Dans un talk vraiment détendu, Bruno CORNEC et Frédéric PASSERON nous ont présenté la façon dont était câblé l&amp;rsquo;API de la plateforme de Workshops on Demand sur le site hackshack.hpedev.io/workshops (lien mort)&lt;/p&gt;
&lt;p&gt;L&amp;rsquo;idée était que, pour les besoins de leur outil de Workshops on demand, l&amp;rsquo;utilisation d&amp;rsquo;une API de type REST était totalement surdimensionnée et que le SMTP (certes protocole vénérable) dispose &lt;em&gt;by design&lt;/em&gt; d&amp;rsquo;un traitement de message par file / asynchrone.&lt;/p&gt;
&lt;p&gt;Une façon &lt;em&gt;fun&lt;/em&gt; de montrer, selon eux, que ce n&amp;rsquo;est pas parce qu&amp;rsquo;une technologie n&amp;rsquo;est pas récente et/ou à la mode qu&amp;rsquo;elle n&amp;rsquo;est pas fonctionnelle.&lt;/p&gt;
&lt;p&gt;Les environnements sont ensuite provisionnés avec un mélange de scripts bash mais surtout d&amp;rsquo;&lt;strong&gt;Ansible&lt;/strong&gt; et je ne peux donc qu&amp;rsquo;approuver leur travail 😉.&lt;/p&gt;
&lt;h2 id="ciel-mon-kubernetes-mine-des-bitcoins"&gt;Ciel mon Kubernetes mine des bitcoins
&lt;/h2&gt;&lt;p&gt;&lt;img src="https://blog.zwindler.fr/2021/11/ciel_mon_kube.avif"
loading="lazy"
&gt;&lt;/p&gt;
&lt;p&gt;Bon, je ne vais pas vous refaire le match, c&amp;rsquo;était ma conférence et si vous souhaitez &lt;a class="link" href="https://blog.zwindler.fr/talks/osxp-2021-ciel-mon-kube-mine-bitcoins/index.html" &gt;relire les slides, elles sont disponibles ici ;-)&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="construction-dimages-de-containers-à-laide-de-kaniko"&gt;Construction d&amp;rsquo;images de containers à l&amp;rsquo;aide de Kaniko
&lt;/h2&gt;&lt;p&gt;Yannig PERRE nous a présenté l&amp;rsquo;outil &lt;strong&gt;Kaniko&lt;/strong&gt;, poussé par GoogleContainerTools, qui permet de construire des images de container Docker sans Docker.&lt;/p&gt;
&lt;p&gt;Le talk commence sur un constat : si l&amp;rsquo;écosystème Kubernetes repose très majoritairement sur l&amp;rsquo;utilisation d&amp;rsquo;image de container Docker pour exécuter les runtime, Docker, lui, est de moins en moins disponible sur les serveurs Kubernetes eux même (débrayable depuis 2016 et le CRI, officiellement déprécié en 1.20).&lt;/p&gt;
&lt;p&gt;Kaniko est donc un container qui va nous servir à construire des images docker, qu&amp;rsquo;on poussera ensuite sur notre registry, le tout sans démon/binaire Docker.&lt;/p&gt;
&lt;p&gt;Grosso modo, le fonctionnement de base n&amp;rsquo;est que peu changé, avec le support de l&amp;rsquo;API v2 et des multistage build. Seuls petits bémols, de par sa conception Kaniko est un container qui nécessite d&amp;rsquo;être lancé avec &lt;code&gt;root&lt;/code&gt; (mais sans privilèges particuliers) et Kaniko ne permet pas de builder une image sans la push.&lt;/p&gt;
&lt;p&gt;Kaniko nécessite également de réfléchir un peu à la façon dont vous allez gérer vos caches pour la constructions des images. Au delà de ces points d&amp;rsquo;attention, l&amp;rsquo;outil semble assez mature.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/GoogleContainerTools/kaniko" target="_blank" rel="noopener"
&gt;github.com/GoogleContainerTools/kaniko&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="construire-un-outil-de-cli-userfriendly"&gt;Construire un outil de CLI userfriendly
&lt;/h2&gt;&lt;p&gt;Nicolas LEPAGE a commencé ce talk par une anecdote qui m&amp;rsquo;a bien fait sourire : il a raconté qu&amp;rsquo;un jour, on lui a dit que pour rechercher des informations sur un processus, on lui avait dit de faire un &lt;code&gt;ps aux&lt;/code&gt; et qu&amp;rsquo;il n&amp;rsquo;avait pas pendant des années, cherché à savoir à quoi correspondaient &amp;ldquo;aux&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;Le fait qu&amp;rsquo;on connaisse tous cette commande, sans pour autant tous être au courant du rôle de chaque &amp;ldquo;flag&amp;rdquo; est assez évocateur de l&amp;rsquo;UX parfois discutable de certaines commandes UNIX.&lt;/p&gt;
&lt;p&gt;Nicolas a donc profité de ce talk pour faire un tour des bonnes pratiques et conventions pour que les utilisateurs de vos futures CLI ne mangent pas leur chapeau. Je vous en donne quelques unes pelle mêle :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Avoir des options longues (débutant par --, avec des mots séparés par un tiret)
&lt;ul&gt;
&lt;li&gt;éventuellement des options courtes (1 tiret 1 lettre, éventuellement &lt;em&gt;groupable&lt;/em&gt; avec d&amp;rsquo;autres lettres)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Des options usuelles qu&amp;rsquo;on s&amp;rsquo;attend à trouver (ex. &amp;ndash;help, &amp;ndash;version)&lt;/li&gt;
&lt;li&gt;Une convention différente pour les commandes et les options
&lt;ul&gt;
&lt;li&gt;éventuellement des groupes de commandes voire des hiérarchies de &amp;ldquo;groupes + sous groupes&amp;rdquo; de commandes&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Nicolas nous a rappelé qu&amp;rsquo;il ne fallait pas oublier qu&amp;rsquo;une CLI a parfois vocation à être lancée dans un script ou par un processus (ajouter des options avec des valeurs par défaut qu&amp;rsquo;on peut surcharger si besoin, par exemple pour celles nécessitant un terminal), permettre d&amp;rsquo;ajouter de la configuration.&lt;/p&gt;
&lt;p&gt;Les slides sont disponibles ici (lien mort, pas dispo sur Internet Archive)&lt;/p&gt;
&lt;h2 id="infrastructure-as-code-quelles-tendances-de-lautomatisation-à-lorchestration-multicloud-"&gt;Infrastructure As Code : quelles tendances ? De l’automatisation à l’orchestration multicloud !
&lt;/h2&gt;&lt;p&gt;Comme le titre du talk de Pierre VILLARD le laisse penser, c&amp;rsquo;était un état de l&amp;rsquo;art de l&amp;rsquo;automatisation et de l&amp;rsquo;orchestration.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.zwindler.fr/2021/11/iac.avif"
loading="lazy"
&gt;&lt;/p&gt;
&lt;p&gt;Après un rapide tour d&amp;rsquo;horizon des différents types d&amp;rsquo;outils qui existent (Génération de template / Orchestration / Gestion de configuration), Pierre nous a donné quelques exemples des outils les plus connus, avec des alternatives.&lt;/p&gt;
&lt;p&gt;Pour la partie &lt;em&gt;templating&lt;/em&gt;, on peut citer Packer, buildpacks.io et Kaniko, chacun avec leurs usages et leurs faiblesses.&lt;/p&gt;
&lt;p&gt;Si tous les grands providers de cloud disposent de leur propre manière de déployer des ressources, quand on fait du multi-cloud, Pulumi est une alternative intéressante.&lt;/p&gt;
&lt;p&gt;Gestion de configuration pure, Ansible reste sans conteste l&amp;rsquo;outil le plus populaire.&lt;/p&gt;
&lt;p&gt;Pierre nous a également parlé d&amp;rsquo;une dernière catégorie d&amp;rsquo;outils : le &lt;code&gt;Policy as code&lt;/code&gt;. Ces outils nous permettent de vérifier que le code IaC qui est produit est conforme aux politiques de sécurité et de conformité de l&amp;rsquo;entreprise. Dans cette catégorie, on peut citer évidemment &lt;a class="link" href="https://blog.zwindler.fr/recherche/?keyword=OPA" target="_blank" rel="noopener"
&gt;Open Policy Agent&lt;/a&gt; et Kyverno, deux outils de la CNCF.&lt;/p&gt;
&lt;h2 id="exposants-visiteurs-et-village-associatif"&gt;Exposants, visiteurs et village associatif
&lt;/h2&gt;&lt;p&gt;Au delà des conférences, cet événement était l&amp;rsquo;occasion rêvée de rencontrer des gens qu&amp;rsquo;on avait pas pu voir &amp;ldquo;en vrai&amp;rdquo; depuis quasiment 2 ans.&lt;/p&gt;
&lt;p&gt;J&amp;rsquo;ai eu une discussion passionnante avec les business model des entreprises éditant des logiciels open sources avec Ludovic DUBOST de &lt;a class="link" href="https://blog.zwindler.fr/recherche/?keyword=xwiki" &gt;XWiki&lt;/a&gt; et &lt;a class="link" href="https://blog.zwindler.fr/recherche/?keyword=cryptpad" &gt;Cryptpad&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;J&amp;rsquo;ai également pu parler avec l&amp;rsquo;équipe de développement de &lt;a class="link" href="https://xcp-ng.org/#easy-to-install" target="_blank" rel="noopener"
&gt;XCP-NG&lt;/a&gt;, une alternative libre à XenServer (lui même basé sur Xen) assez prometteuse. La communauté est assez active, a ajouté le support de terraform et travaille pour écrire une API pour piloter XCP-NG avec Kubernetes (de la même manière qu&amp;rsquo;on peut le faire avec kubevirt).&lt;/p&gt;
&lt;p&gt;J&amp;rsquo;ai assisté à une présentation de la dernière beta de &lt;a class="link" href="https://www.rudder.io/" target="_blank" rel="noopener"
&gt;Rudder&lt;/a&gt; que je ne connaissais pas du tout (au delà du nom). Même si le produit ne s&amp;rsquo;adresse pas prioritairement à des admins systèmes&lt;/p&gt;
&lt;p&gt;J&amp;rsquo;ai eu une discussion passionnante avec les gens de &lt;a class="link" href="https://www.centreon.com/" target="_blank" rel="noopener"
&gt;Centreon&lt;/a&gt; sur le monitoring et l&amp;rsquo;observabilité en général. On a aussi beaucoup parlé de haute disponibilité des brokers/pollers 😏.&lt;/p&gt;
&lt;p&gt;J&amp;rsquo;ai également pas mal discuté Genma, AtaxyaNetwork (&amp;amp; une partie de la team Aquaray), Rémi VERCHERE, Nicolas LEPAGE, la &lt;a class="link" href="https://linuxfr.org/" target="_blank" rel="noopener"
&gt;team de LinuxFR&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;De très belles rencontres :).&lt;/p&gt;</description></item><item><title>[OSXP 2021] Ciel ! Mon Kubernetes mine des bitcoins</title><link>https://blog.zwindler.fr/2021/10/11/osxp-2021-ciel-mon-kubernetes-mine-des-bitcoins/</link><pubDate>Mon, 11 Oct 2021 06:20:00 +0000</pubDate><guid>https://blog.zwindler.fr/2021/10/11/osxp-2021-ciel-mon-kubernetes-mine-des-bitcoins/</guid><description>&lt;img src="https://blog.zwindler.fr/2021/08/osxp_logo.webp" alt="Featured image of post [OSXP 2021] Ciel ! Mon Kubernetes mine des bitcoins" /&gt;&lt;h2 id="open-source-experience-le-successeur-du-paris-open-source-summit"&gt;Open Source Experience, le successeur du Paris Open Source Summit
&lt;/h2&gt;&lt;p&gt;GROSSE (mais excellente) surprise ! Je serai speaker à l’&lt;a class="link" href="https://www.opensource-experience.com/" target="_blank" rel="noopener"
&gt;OSXP qui se déroulera au Palais des congrès à Paris les 9 et 10 novembre prochains (et c’est gratuit)&lt;/a&gt; ! J’avais cité le POSS dans un de mes tout premiers talks et je ne pensais pas un jour y être moi-même :).&lt;/p&gt;
&lt;p&gt;A vrai dire, j’ai postulé sans grand espoir et c’est une version modifiée (20 minutes au lieu de 40) de mon talk « Ciel, mon Kubernetes mine des bitcoins » qui a été sélectionné. Je suis vraiment très flatté, car c’est ma plus grosse conf en tant que speaker jusqu’à présent.&lt;/p&gt;
&lt;p&gt;Dans les speakers il y a de très beaux noms (certains que j’ai hâte de retrouver, d’autre que j’ai hâte de rencontrer), je vous laisse jeter un œil :&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.zwindler.fr/2021/08/osxp.avif"
loading="lazy"
&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://www.opensource-experience.com/programme/intervenants-2021/" target="_blank" rel="noopener"
&gt;www.opensource-experience.com/programme/intervenants-2021/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Je serai également présent sur les 2 jours et aurait ainsi l’occasion de vous rencontrer. N’hésitez pas à me prévenir si vous venez, ou à m’écrire sur Twitter si vous voulez qu’on se cale un créneau pour discuter :)&lt;/p&gt;
&lt;h2 id="le-pitch"&gt;Le pitch
&lt;/h2&gt;&lt;blockquote&gt;
&lt;p&gt;A tort ou à raison, Kubernetes s’est imposé, ces 4 dernières années, comme un des nouveaux standards dans la gestion des architectures microservices modernes.&lt;/p&gt;
&lt;p&gt;Cependant cet outil, riche plus que complexe, amène son lot de pièges dans lesquels les débutants ne manqueront pas de tomber… Et ce n’est pas l’apparente facilité apportée par les offres Kubernetes as a Service qui va arranger les choses !&lt;/p&gt;
&lt;p&gt;Après un rapide tour de l’actualité sécurité autour de Kubernetes, je vous donnerai les clés pour éviter de vous faire voler (trop facilement) vos cycles CPU.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="slides"&gt;Slides
&lt;/h2&gt;&lt;p&gt;Comme à mon habitude, je met les slides à disposition &lt;a class="link" href="https://blog.zwindler.fr/talks/osxp-2021-ciel-mon-kube-mine-bitcoins/ciel_mon_kube_mine_bitcoin.pdf" &gt;ici pour que vous pouviez cliquer sur les liens en même temps que le talk :-)&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Hacker un calendrier javascript (datepicker) avec un scraper python</title><link>https://blog.zwindler.fr/2017/05/09/hacker-calendrier-datepicker-scraper-python/</link><pubDate>Tue, 09 May 2017 12:00:26 +0000</pubDate><guid>https://blog.zwindler.fr/2017/05/09/hacker-calendrier-datepicker-scraper-python/</guid><description>&lt;img src="https://blog.zwindler.fr/2017/05/maitre-gims-scrape-comme-jamais2.webp" alt="Featured image of post Hacker un calendrier javascript (datepicker) avec un scraper python" /&gt;&lt;h2 id="mais-quel-rapport-entre-un-datepicker-javascript-et-un-scraper-python-"&gt;Mais quel rapport entre un datepicker javascript et un scraper python ?
&lt;/h2&gt;&lt;p&gt;Si vous ne savez ni ce qu’est un &lt;em&gt;datepicker&lt;/em&gt; en Javascript ou un &lt;em&gt;scraper python&lt;/em&gt;, je vous ai probablement déjà perdu. Pourtant, dans cet article ultra fun (ok, je suis bizarre), je vous montrerai comme j’ai automatisé via un scraper développé en python la recherche de dates libres dans un calendrier Javascript sur une page web :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;en scriptant la génération de cette page via une ligne de commande&lt;/li&gt;
&lt;li&gt;en simulant un clic pour passer au mois suivant&lt;/li&gt;
&lt;li&gt;et enfin en récupérant les bonnes valeurs (pour me les envoyer par email par exemple)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="commençons-donc-par-un-peu-de-storytelling"&gt;Commençons donc par un peu de storytelling
&lt;/h2&gt;&lt;p&gt;Depuis quelques mois, je vais régulièrement sur un site web un peu artisanal sur lequel je fais des réservations. Pour se faire, ce site web propose une page web simple dans lequel a été intégré un composant calendrier :&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.zwindler.fr/2017/05/calendrier1.avif"
loading="lazy"
&gt;&lt;/p&gt;
&lt;p&gt;Rien de particulièrement extraordinaire jusque là.&lt;/p&gt;
&lt;p&gt;Mais (car bien sûr il y a un mais), ce site à l’inconvénient d’être victime de son succès. Pour vous donner une idée, c’est le genre de site web qui tombe 30 secondes après l’ouverture des réservations à 19h00. Et que dès que l’administrateur système le relance entre 20 et 50 minutes plus tard, les réservations sont complètes en quelques minutes.&lt;/p&gt;
&lt;h2 id="méthode-1--f5"&gt;Méthode 1 : F5
&lt;/h2&gt;&lt;p&gt;La première méthode, probablement plébiscité par la plupart des utilisateurs, est à base de refresh frénétique du site web, jusqu’à ce qu’il devienne inopérant&amp;hellip; Une fois que le site est down, on peut continuer à appuyer sur F5 en espérant être le premier quand il reviendra.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.zwindler.fr/2017/05/F5.gif"
loading="lazy"
&gt;&lt;/p&gt;
&lt;p&gt;Le souci de cette méthode, c’est que je manque cruellement de patience et que je lâche l’affaire assez vite. Et donc tous les mois, les plus hargneux (ou les plus chanceux) me passent toujours devant car j’ai loupé le moment où le site redevient accessible.&lt;/p&gt;
&lt;h2 id="méthode-2--curl"&gt;Méthode 2 : cURL
&lt;/h2&gt;&lt;p&gt;En bon administrateur système que je suis, je ne pouvais pas me résoudre à en rester là. Mon problème principal étant d’être prévenu lorsque le site devenait à nouveau opérationnel, j’ai sorti ma boîte à outils habituelle : cURL !&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;cURL&lt;/strong&gt; (abréviation de &lt;em&gt;client URL request library&lt;/em&gt;), est un outil à tout faire quand on veut jouer avec des URL sur un serveur Linux. C’est simple et efficace.&lt;/p&gt;
&lt;p&gt;Dans le cas où le site est tombé suite à la connexion massive des internautes avides de réservations, j’ai donc créé un petit script basé sur ce &lt;em&gt;oneliner&lt;/em&gt;&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;curl http://@IP_ou_FQDN/le_chemin_de_la_page/ -I 2&amp;gt;/dev/null | head -n 1
HTTP/1.1 200 OK
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Dès que le code retour passe de 503 à 200, c’est que le site web est de nouveau accessible et je peux me remettre à faire F5 en espérant que les réservations ouvrent.&lt;/p&gt;
&lt;h2 id="méthode-2bis--aller-plus-loin-avec-curl"&gt;Méthode 2bis : aller plus loin avec cURL
&lt;/h2&gt;&lt;p&gt;Bon&amp;hellip; La méthode précédente fonctionne&amp;hellip; mais ce n’est pas encore ça !&lt;/p&gt;
&lt;p&gt;Typiquement, il arrive que l’ouverture des dates soit reportée au lendemain, quand le site est vraiment trop longtemps dans les choux. Du coup le site répond (et mon test me revoie que le site est opérationnel), mais les dates ne sont pas disponibles pour autant&amp;hellip;&lt;/p&gt;
&lt;p&gt;Un rapide coup d’œil aux sources me donne l’info que je cherche. Il n’y a plus qu’à automatiser ça.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.zwindler.fr/2017/05/calendrier2.avif"
loading="lazy"
&gt;&lt;/p&gt;
&lt;p&gt;Mais évidemment ça n’est pas si simple&amp;hellip;&lt;/p&gt;
&lt;p&gt;Firefox interprète le Javascript, mais pas cURL, qui ne sait pas &lt;a class="link" href="http://stackoverflow.com/questions/20554113/how-to-get-webcontent-that-is-loaded-by-javascript-using-curl" target="_blank" rel="noopener"
&gt;interpréter le Javascript (cf ce post de Stack Overflow)&lt;/a&gt;. Le retour de ma commande contient donc le code source HTML avec le Javascript brut, mais pas les données que je recherche&amp;hellip;&lt;/p&gt;
&lt;h2 id="méthode-3--un-scraper-"&gt;Méthode 3 : Un scraper ?
&lt;/h2&gt;&lt;p&gt;Je dois écrire un &lt;em&gt;scraper&lt;/em&gt; qui va aller simuler l’action de l’humain qui va ouvrir la page dans un navigateur. Le post de Stack Overflow cite &lt;a class="link" href="http://phantomjs.org/" target="_blank" rel="noopener"
&gt;PhantomJS&lt;/a&gt; qui est probablement une bonne solution.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;PhantomJS is a headless WebKit scriptable with a JavaScript API. It has &lt;strong&gt;fast&lt;/strong&gt; and &lt;strong&gt;native&lt;/strong&gt; support for various web standards: DOM handling, CSS selector, JSON, Canvas, and SVG.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Cependant je ne connais pas bien JS (ça fait longtemps on va dire) et je préfère capitaliser sur Python. J’ai donc cherché un module Python pour régler mon problème, et j’en ai trouvé 2 : un module python &lt;strong&gt;selenium&lt;/strong&gt; et un plus simple appelé &lt;strong&gt;dryscrape&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;J’ai installé dryscrape sur un de mes serveurs (un CentOS 7 minimal, sans environnement graphique). La documentation de dryscrape &lt;a class="link" href="http://dryscrape.readthedocs.io/en/latest/installation.html" target="_blank" rel="noopener"
&gt;est disponible ici&lt;/a&gt; et &lt;a class="link" href="https://dryscrape.readthedocs.io/en/stable/usage.html" target="_blank" rel="noopener"
&gt;ici (stable, documentation plus fournie)&lt;/a&gt;.&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;yum install -y qt5-qtwebkit-devel gcc-c++
sed -i &amp;#39;s/PATH=$PATH:$HOME\/bin/PATH=$PATH:$HOME\/bin:\/usr\/lib64\/qt5\/bin/&amp;#39; .bash_profile
source .bash_profile
pip install dryscrape
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Et j’ai tout de suite voulu tester un bout de code sans trop chercher à comprendre.&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;cat &amp;lt;&amp;lt; EOF &amp;gt; test.py
import dryscrape
session = dryscrape.Session()
session.visit(&amp;#39;http://@IP_ou_FQDN/le_chemin_de_la_page/&amp;#39;)
response = session.body()
print response
EOF
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&amp;hellip; je me suis donc pris un bon gros Traceback :&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;Traceback (most recent call last):
File &amp;#34;test.py&amp;#34;, line 3, in &amp;lt;module&amp;gt;;
session = dryscrape.Session()
[...]raise NoX11Error(&amp;#34;Could not connect to X server. &amp;#34;
webkit_server.NoX11Error: Could not connect to X server. Try calling dryscrape.start_xvfb() before creating a session.
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Ahhhhh oui&amp;hellip; ça !&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;xvfb_ (necessary only if no other X server is available)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;En fait il suffit d’ajouter un test pour exécuter dans xvfb si nécessaire.&lt;/p&gt;
&lt;h3 id="un-premier-exemple"&gt;Un premier exemple
&lt;/h3&gt;&lt;p&gt;Le bout de code suivant ne fait que récupérer le code source de la page et l’afficher à l’écran.&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;cat &amp;lt;&amp;lt; EOF &amp;gt; simple_scraper.py
#!/usr/bin/python
# -*- coding: utf-8 -*-
import sys
import dryscrape
if &amp;#39;linux&amp;#39; in sys.platform:
# start xvfb in case no X is running. Make sure xvfb
# is installed, otherwise this won&amp;#39;t work!
dryscrape.start_xvfb()
session = dryscrape.Session()
session.visit(&amp;#39;http://@IP_ou_FQDN/le_chemin_de_la_page/&amp;#39;)
response = session.body()
print response
EOF
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Mais la grosse différence avec le cURL précédent, c’est que dans le cas présent, &lt;strong&gt;ici le Javascript est interprété&lt;/strong&gt;. Cette fois ci dans le code source retourné, je retrouve bien mon calendrier&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.zwindler.fr/2017/05/datepicky.avif"
loading="lazy"
&gt;&lt;/p&gt;
&lt;p&gt;A partir de là, il ne me reste donc en théorie qu’à terminer d’écrire un petit bout de script pour extraire les informations qui m’intéressent et à me notifier quand des places sont libres ! On progresse !&lt;/p&gt;
&lt;h2 id="méthode-3--scraper-comme-jamais"&gt;Méthode 3 : Scraper comme jamais
&lt;/h2&gt;&lt;p&gt;&lt;img src="https://blog.zwindler.fr/2017/05/maitre-gims-scrape-comme-jamais2.avif"
loading="lazy"
&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Ce montage pourri d’un clip de Maître Gimms avec des logos dans la main vous est offert par Zwindler&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Mais je n’étais pas encore satisfait. Mon but est d’être prévenu lorsque des places sont disponibles. Or, les places s’ouvrent le 1er du mois, &lt;strong&gt;pour le mois suivant&lt;/strong&gt;. En revanche, le composant Javascript datepicker a la mauvaise idée de donner les disponibilités &lt;strong&gt;pour le mois en cours&lt;/strong&gt;. Mon script &lt;strong&gt;simple_scraper.py&lt;/strong&gt; ne récupère donc pas les bonnes dates&amp;hellip;&lt;/p&gt;
&lt;p&gt;Pour contourner le problème, il faut aller encore un peu plus loin dans l’automatisation des actions. Il faut simuler le clic de l’utilisateur sur la flèche vers la droite, qui passe au mois suivant.&lt;/p&gt;
&lt;p&gt;C’est possible avec &lt;strong&gt;dryscrape&lt;/strong&gt;, qui propose notamment une fonction pour sélectionner des nodes XPATH et interagir avec. Pour ceux qui ne connaissent pas XPATH, vous pouvez aller sur la doc de dryscrape qui donne quelques exemples, et aussi sur &lt;a class="link" href="https://www.w3schools.com/xml/xpath_intro.asp" target="_blank" rel="noopener"
&gt;le tutoriel de la W3School&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Comme j’ai examiné le code HTML retourné par le datepicker, je sais quoi chercher :&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.zwindler.fr/2017/05/datepicker3.avif"
loading="lazy"
&gt;&lt;/p&gt;
&lt;p&gt;Pour changer de mois en cours, dans un premier temps j’ai essayé d’utiliser le label « » » mais le module dryscrape ne supporte pas les caractères non ASCII ! Une solution qui fonctionne est de cliquer sur le lien qui contient &lt;em&gt;javascript:void(0)&lt;/em&gt; contenu dans le div de classe &lt;em&gt;datepick-next&lt;/em&gt; :&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;cat &amp;lt;&amp;lt; EOF &amp;gt; datepick_scraper.py
#!/usr/bin/python
# -*- coding: iso-8859-15 -*-
import sys
import dryscrape
if &amp;#39;linux&amp;#39; in sys.platform:
# start xvfb in case no X is running. Make sure xvfb
# is installed, otherwise this won&amp;#39;t work!
dryscrape.start_xvfb()
session = dryscrape.Session()
session.visit(&amp;#39;http://@IP_ou_FQDN/le_chemin_de_la_page/&amp;#39;)
datepicknext = session.at_xpath(&amp;#39;//*[@class=&amp;#34;datepick-next&amp;#34;]/a&amp;#39;)
datepicknext.click()
response = session.body()
print response
EOF
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Après vérification, cette version du script renvoie bien le tableau avec les date de Juin (quand on est en Mai) !&lt;/p&gt;
&lt;h2 id="le-mot-de-la-fin"&gt;Le mot de la fin
&lt;/h2&gt;&lt;p&gt;A partir du moment où vous en êtes là, il n’y a plus vraiment de limites à ce que vous êtes capable de faire. Dans mon exemple, j’aurai pu aller encore plus loin, extraire les dates disponibles, et même pourquoi pas aller jusqu’à remplir automatiquement le formulaire pour réserver automatiquement une date prédéfinie (voire même toutes les dates disponibles).&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.zwindler.fr/2017/05/datepickx.avif"
loading="lazy"
&gt;&lt;/p&gt;
&lt;p&gt;Ce n’est pas mon but : je vais me contenter de m’envoyer un email dès qu’une date se libère. Mais c’est possible !&lt;/p&gt;
&lt;p&gt;Si vous voulez explorer les possibilité de dryscrape, la documentation officielle donne quelques exemples, et notamment celui de l’envoi d’un email depuis Gmail, entièrement automatisé comme si c’était un humain (!)&lt;/p&gt;
&lt;p&gt;De quoi donner des idées, pour &lt;em&gt;&lt;strong&gt;scraper comme jamais&lt;/strong&gt;&lt;/em&gt; !&lt;/p&gt;</description></item></channel></rss>