Si vous suivez ce blog, vous êtes familiers avec le dogme central du Cloud Native : l’immuabilité.

Ce principe stipule que les workloads sont jetables (Cattle). On ne corrige pas un processus défaillant, on le tue (kill) et on le remplace. Cette approche a révolutionné la résilience et la scalabilité de nos systèmes distribués en éliminant la dérive de configuration.

Mais cette robustesse a un coût que nous avons fini par accepter comme une fatalité : le temps d’initialisation.

Démarrer un conteneur, charger les bibliothèques, “chauffer” les caches, établir les pools de connexions… tout cela prend de précieuses secondes (le fameux Cold Start, voir mon article sur les MicroVM). Nous avons appris à vivre avec cette latence, considérant que l’état d’un processus (RAM) est, par définition, perdu au redémarrage.

Et si l’immuabilité de l’artefact n’impliquait pas nécessairement la perte de l’état ?

C’est la promesse de CRIU (Checkpoint/Restore In Userspace). Cette technologie permet de “geler” un processus en cours d’exécution, de sauvegarder son état complet sur disque, et de le “téléporter” pour le restaurer à l’identique, ailleurs et plus tard.

Dans cet article, nous allons explorer la notion de mobilité d’état (State Mobility). Nous verrons comment CRIU opère dans les entrailles de Linux et comment il remet en question le modèle du “tout jetable”.

Le malentendu du “Stateless”

Note : Dans cet article, j’utiliserai de manière interchangeable les termes “processus” et “application”, même si techniquement un processus est une instance d’exécution.

Avant de plonger dans la technique, il faut dissiper un malentendu. On confond souvent l’état des données (Data State) et l’état d’exécution (Execution State).

Quand on dit qu’une application Cloud Native doit être stateless, on parle généralement de l’architecture REST : le serveur ne doit pas conserver de session client entre deux requêtes. Si le serveur redémarre, la base de données (Postgres, Redis) a toujours les informations, donc le service n’est pas interrompu.

Cependant, du point de vue du système d’exploitation, le concept de “stateless” n’existe pas. Un processus, même le plus simple “Hello World” en Java ou Node.js, possède un état. Il a chargé des pages en mémoire RAM, il a compilé du code, il a ouvert des descripteurs de fichiers et il maintient des sockets TCP connectés.

C’est cet état d’exécution que nous perdons systématiquement aujourd’hui. Quand Kubernetes tue un Pod pour le déplacer, il détruit cet investissement en temps de calcul (le temps de chauffe) et force le nouveau Pod à tout recommencer à zéro. C’est du gaspillage de ressources et de temps.

CRIU propose de capturer cet état volatil pour le rendre persistant.

Comment figer le temps sous Linux

Contrairement aux anciennes méthodes de snapshot de machines virtuelles qui copient tout le disque et la RAM brute, CRIU opère, comme son nom l’indique, en Userspace. Cela signifie qu’il n’a pas besoin de modules noyau exotiques pour fonctionner ; il utilise les outils standard de Linux.

La procedure est plutot simple mais tres ingenieuse. Lorsqu’on demande à CRIU de faire un checkpoint, il commence par geler l’arbre de processus cible en utilisant l’appel système ptrace. Une fois le processus figé, CRIU lui injecte un petit bout de code “parasite”.

Bientot je vais faire un article sur les syscalls Linux, mais pour faire simple, ptrace est un mécanisme qui permet à un processus de contrôler un autre processus. C’est la base des debuggers comme GDB.

Ce parasite va scanner le processus de l’intérieur. Il va lire l’emplacement des pages mémoires, lister les fichiers ouverts, noter la position des pointeurs d’instruction du CPU et identifier les connexions réseaux actives. Toutes ces informations sont ensuite sérialisées et écrites dans une série de fichiers images sur le disque. Une fois le dump terminé, le processus peut être soit tué, soit laissé en vie…

La restauration est l’opération inverse, mais elle est beaucoup plus spectaculaire. CRIU lit les fichiers images et demande au noyau de recréer les processus exactement comme ils étaient. Le plus impressionnant est que CRIU est capable de restaurer le même PID (Process ID) qu’à l’origine. Il “remplit” ensuite la mémoire RAM avec les données sauvegardées et rouvre les fichiers. Pour le processus, c’est comme s’il s’était endormi une microseconde, alors qu’il s’est peut-être passé des jours, ou qu’il a changé de serveur physique.

Voila une demo pas mal pour comprendre le processus :

Boot vs Resume

Pourquoi s’embêter avec cette complexité ? Parce que cela nous permet de passer d’un modèle basé sur le Démarrage (Boot) à un modèle basé sur la Reprise (Resume).

Prenons l’exemple du Serverless et des fonctions Java. Démarrer une JVM, charger Spring Boot et initialiser les frameworks peut prendre 5 à 10 secondes. C’est inacceptable pour une fonction qui doit répondre en millisecondes.

Avec l’approche CRIU, on change la stratégie. On démarre l’application une fois, lors de la phase de build. On la laisse s’initialiser complètement. Puis, on effectue un checkpoint. On obtient une image disque de la mémoire “chaude”. En production, lorsqu’une requête arrive, on ne démarre pas l’application mais on restaure simplement l’image mémoire. Le temps de “boot” disparaît, remplacé par le temps de copie mémoire, qui est négligeable.

C’est exactement la technologie utilisée par AWS pour Lambda SnapStart. Ce n’est pas de la magie, c’est de la gestion intelligente de l’état d’exécution.

Au-delà de la performance : La sécurité et le Forensic

Si l’optimisation des performances est le cas d’usage le plus évident, mon préféré reste l’application en cybersécurité.

Imaginons un scénario classique, votre SIEM (Wazuh, par exemple) détecte un comportement suspect dans un conteneur en production. Le réflexe standard est d’isoler le conteneur ou de le tuer. Mais en le tuant, on détruit les preuves volatiles : les clés de chiffrement en RAM, les connexions actives vers le C2 (Command & Control) de l’attaquant.

Avec CRIU, nous pouvons “geler” le conteneur compromis instantanément. Nous déplaçons ensuite les fichiers de checkpoint vers un environnement sécurisé (une Sandbox déconnectée du réseau de production) et nous restaurons le processus.

Nous avons alors une copie parfaite de l’attaque en cours, figée dans le temps, que nous pouvons analyser, laisser tourner, ou inspecter avec un debugger, sans aucun risque pour la production. C’est ce qu’on appelle le Live Forensic, et c’est une arme redoutable.

Pourquoi ce n’est pas encore la norme ?

Si la technologie est si puissante, pourquoi ne l’utilisons-nous pas partout par défaut dans Kubernetes ?

La réponse réside dans la complexité de l’environnement extérieur. Sauvegarder la mémoire est “facile”. Mais restaurer les connexions avec le monde extérieur est un cauchemar.

Le problème principal est le réseau. Si vous sauvegardez un processus qui a une connexion TCP ouverte, et que vous le restaurez sur une autre machine avec une adresse IP différente, la connexion TCP est invalide. Le noyau va tenter d’envoyer des paquets avec des numéros de séquence qui ne correspondent plus à rien, et la connexion sera réinitialisée (RST). CRIU possède un mode “TCP Repair” pour gérer cela, mais cela nécessite souvent une infrastructure réseau capable de suivre (SDN, IP virtuelles qui suivent le conteneur).

Il y a aussi la question de l’horloge système. Si un processus calcule une durée en comparant l’heure avant et après le checkpoint, il peut se réveiller en pensant que 5 jours se sont écoulés en une seconde, ce qui peut causer des timeouts ou des bugs logiques imprévus.

Enfin, CRIU nécessite des privilèges élevés (souvent CAP_SYS_ADMIN ou root) pour manipuler les processus d’une telle manière, ce qui va à l’encontre des bonnes pratiques de sécurité consistant à tout verrouiller.

Conclusion

CRIU n’est pas juste un outil de “pause”. C’est une technologie qui remet en perspective notre conception de l’architecture Cloud.

Nous avons passé la dernière décennie à optimiser la destruction et la recréation de nos infrastructures (Immutability). La prochaine étape logique n’est pas de reconstruire plus vite, mais de ne plus avoir besoin de reconstruire. C’est la transition vers la mobilité d’état.

Bien que l’utilisation directe de CRIU reste complexe aujourd’hui, elle s’intègre progressivement dans nos outils quotidiens (Podman, Containerd, Kubernetes via des projets comme Checkpoint/Restore in Kubernetes). Comprendre son fonctionnement, c’est comprendre comment nous opérerons les systèmes de demain : fluides, persistants et véritablement mobiles.