Remplacer Kubernetes par systemd (2024)
(blog.yaakov.online)- Sur un serveur personnel ou un petit VPS, l’automatisation déclarative de Kubernetes est séduisante, mais sa charge CPU et mémoire ainsi que sa complexité d’exploitation peuvent dépasser ses bénéfices réels
- Kubernetes automatise des tâches comme l’ajustement des Pods et le renouvellement des certificats TLS en maintenant en permanence l’état souhaité, mais cela implique de faire tourner en continu un runtime assez lourd
- Sur Azure Kubernetes Service, Microk8s, K3S et lors d’expérimentations sur Raspberry Pi, la consommation de ressources au repos ainsi que la chaleur et le bruit du ventilateur se sont révélés problématiques de façon répétée
- Podman peut transformer des conteneurs en services systemd et détecter puis remplacer de nouvelles images avec
io.containers.autoupdateetpodman auto-update - La combinaison Podman, systemd et user lingering fournit de façon plus simple l’essentiel de l’automatisation recherchée avec Kubernetes, mais l’intégration systemd évolue désormais vers Quadlet
Pourquoi l’automatisation de Kubernetes était trop lourde pour un serveur personnel
- Kubernetes se compose de multiples éléments, services web, sidecars et webhooks, mais son fonctionnement central ressemble surtout à une boucle qui compare en continu l’état actuel et l’état souhaité pour appliquer les écarts
- Si un Pod doit exister mais n’existe pas, il est créé
- Si le nombre de replicas doit être de 3 mais qu’il y en a 4, l’un d’eux est supprimé
- Ce modèle était particulièrement utile avec des extensions comme cert-manager
- On déclare qu’un certificat TLS valide doit exister pour un domaine donné
- Une fois la méthode de demande de certificat définie, un nouveau certificat est obtenu et installé sur le serveur web lorsqu’il manque ou approche de son expiration
- Pour des expérimentations personnelles, c’était amusant et formateur, mais pour un usage de production réel, cela relevait davantage de l’outil excessif
- La charge sur les ressources s’est répétée dans plusieurs environnements
- Sur un NUC, la machine tournait en permanence, chauffait et faisait du bruit, au point de rendre le sommeil difficile
- Sur Azure Kubernetes Service, l’implémentation de Kubernetes consommait beaucoup de RAM et utilisait environ 7 à 10 % du CPU au repos sur le worker node
- Une instance unique de Microk8s sur un VPS x86_64 à 2 vCPU utilisait environ 12 % de CPU au repos
- K3S sur une machine Ampere A1 à 2 vCPU, pourtant réputé plus léger, utilisait environ 6 % de CPU en continu
- Même sur Raspberry Pi, il n’a pas été possible de trouver une implémentation laissant assez de CPU pour les workloads sans problèmes de chaleur ni de ventilateur
La méthode d’automatisation adoptée avec Podman et systemd
- La principale raison de conserver Kubernetes était l’automatisation du déploiement
- Avec GitOps et Flux, les changements étaient faciles à appliquer
- Grâce à l’automatisation des images de conteneurs et au webhook de Flux v2, lorsqu’une nouvelle image était poussée, le serveur la récupérait en quelques secondes et lançait l’application de production mise à jour
- Les alternatives classiques trouvées hors de Kubernetes n’étaient pas satisfaisantes
- Recréer les conteneurs en mémorisant tous les arguments de ligne de commande d’origine impliquait une lourde charge de gestion
- Les outils réclamant un contrôle total de
docker.sockn’étaient pas non plus appréciés
- Podman auto-updating correspondait de près au besoin
- Podman peut être vu comme une alternative à la CLI Docker
- Après avoir créé un conteneur, il est possible de générer un fichier de service systemd
- Quand le service démarre, il crée ou remplace le conteneur ; quand le service s’arrête, il supprime le conteneur
- Les mises à jour automatiques reposent sur le tag
io.containers.autoupdate- Elles s’exécutent une fois par jour via un timer ou en lançant directement
podman auto-update - Si une nouvelle image est disponible, le conteneur est recréé à partir de cette image
- Elles s’exécutent une fois par jour via un timer ou en lançant directement
- L’article de Fedora Magazine, Auto-updating Podman containers with systemd, fournissait l’essentiel de la mise en œuvre, avec en plus deux réglages nécessaires
systemctl --user enable mycontainer.servicepermet de démarrer automatiquement le conteneur à la connexionloginctl enable-lingerpermet d’activer la session utilisateur au démarrage du serveur
- La combinaison Podman, systemd et user lingering permet de retrouver environ 99 % des avantages obtenus avec Kubernetes, avec bien moins de complexité et une charge CPU/mémoire nettement plus faible
- L’ensemble des services a été migré vers un nouveau VPS disposant de moitié moins de vCPU et de RAM que l’ancien, tout en étant plus léger, plus rapide et moins coûteux à faire tourner après plusieurs heures d’exécution
- En revanche, l’intégration de Podman avec systemd semble déjà dépréciée, et les définitions de conteneurs s’orientent désormais vers des fichiers Quadlet
1 commentaires
Avis de Hacker News
Je comprends totalement le ressenti de l’auteur original. Au travail, on gère relativement facilement plusieurs clusters Kubernetes qui font tourner des dizaines de microservices, mais pour des projets perso sans revenus, le budget est trop serré pour utiliser Kubernetes même si on en a envie.
Sur un VPS à 10 $/mois avec 1 vCPU partagé et 2 Go de RAM, Kubernetes est beaucoup trop lourd. Au lieu de Deployments, je lance manuellement
docker compose up/downen SSH ; au lieu d’un Ingress, je m’appuie sur la découverte de conteneurs de Traefik ; et comme je ne peux pas utiliser les CronJobs, j’ai même écrit un petit script pour gérer crontab de façon idempotente.Ce que je veux vraiment, c’est une alternative légère qui fournisse une API compatible Kubernetes et tourne bien même sur un VPS bon marché. L’écart entre l’orchestration de conteneurs de niveau entreprise et l’hébergement low cost pour projets perso reste beaucoup trop grand.
docker composeutilisant des manifestes Kubernetes.On peut aussi l’utiliser avec des unités systemd, comme dans l’approche décrite dans l’article. Podman prend également en charge la majeure partie, voire la totalité, de l’API Docker, donc
docker composefonctionne aussi, et on peut se connecter à un socket distant via SSH pour travailler.https://docs.podman.io/en/latest/markdown/podman-kube-play.1...
https://docs.podman.io/en/latest/markdown/podman-systemd.uni...
Ils offrent gratuitement 4 cœurs ARM64 et 24 Go de RAM, que l’on peut répartir sur 1 à 4 nœuds selon la configuration souhaitée.
https://www.oracle.com/cloud/free/
docker composerenforcé.Avec Traefik et des labels, on généralise le reverse proxy et les certificats TLS, puis on ajoute Authelia comme fournisseur d’authentification simple. Il y a aussi beaucoup de projets d’exemple sur GitHub, et avec un week-end de configuration on obtient un système assez facile à administrer.
systemd se fait beaucoup critiquer, mais il résout vraiment énormément de problèmes, donc il ne faut pas l’écarter trop vite. Quand il a commencé à arriver par défaut dans les distributions, une bonne partie du rejet venait du fait que les gens devaient changer leurs habitudes.
Il y a les conteneurs,
machinectl,nspawn, qui est un chroot plus puissant,vmspawnquand on a besoin de virtualisation complète,importctlpour télécharger, importer et exporter des machines,homed/homectlpour faciliter le chiffrement des répertoires personnels et le contrôle des permissions, etc.Au lieu de
fstab, on traite les montages comme des unités ; on contrôle l’ordre de démarrage ainsi que le lancement et l’arrêt des services ; et il fournit aussi des timers plus puissants quecron. Par exemple, on peut savoir qu’une tâche n’a pas pu s’exécuter parce que la machine était éteinte, ou la lancer avec un délai après le démarrage sous certaines conditions.Les unités de service permettent de contrôler finement les tâches et de restreindre les permissions, et
systemctl editpermet de créer des overrides sans toucher à la configuration d’origine. C’est un peu pénible à apprendre au début, mais de toute façon, pour faire des choses complexes, aucun outil ne permet d’éviter totalement la documentation.Le problème, c’était l’attitude des mainteneurs. Ils cassaient sans scrupule des choses qui fonctionnaient bien, sans fournir de correctifs appropriés. Si systemd ne t’a jamais fait souffrir, c’est peut-être que tu es arrivé plus tard, ou que tes besoins coïncidaient par hasard avec ceux des mainteneurs principaux.
execlui-même sur place lors des mises à niveau.Un programme qui fait exactement à 100 % ce que PID 1 doit faire, et rien d’autre, peut être beaucoup plus petit. Si on lance systemd par-dessus, un problème dans systemd ne mène pas immédiatement à un kernel panic.
Source : https://ewontfix.com/14/
cron. Il fonctionne bien depuis 50 ans, et soudain il serait devenu une très mauvaise solution qui devrait naturellement être remplacée par systemd.fstabau profit des montages systemd, les règles d’automount sont complexes et, même en les alignant 1:1 avec la documentation, il arrive qu’elles ne fonctionnent tout simplement pas, si bien que le système de fichiers peut ne pas être monté à temps.Pour les distributions ou les projets upstream, il simplifie énormément la vie, mais en contrepartie il ajoute une complexité croissante dans les couches les plus basses du système. Selon le point de vue, des éléments comme
journalctl,timedatectl, la dépendance à dbus ou son remplacement peuvent être vus comme contraires à la philosophie Unix.Si l’objectif est simplement de coordonner des processus, de les exécuter dans le bon ordre et de garantir l’activation automatique, je le considère comme un outil d’un niveau plus approprié que k8s ou Docker.
J’ai fait tourner mon homelab pendant un bon moment avec podman-systemd, autrement dit Quadlet, et chaque fois que je regardais une nouvelle variante de k8s, ça ne valait pas la peine d’accepter la complexité supplémentaire. Mes vieux playbooks Ansible suffisent déjà à pré-télécharger les images et à mettre les fichiers d’unités au bon endroit
J’ai aussi fait tourner toute la stack de mon imprimante 3D Voron avec podman-systemd, ce qui permet de mettre à jour et de revenir en arrière sur tous les composants d’un coup. Cela dit, j’envisage maintenant aussi une approche avec
mkosietsystemd-sysupdatepour mettre à jour et rollbacker toute l’image disque en une seule foisLe principal problème, c’est que les gens distribuent généralement seulement des fichiers
docker-compose, qu’il faut donc convertir en unités systemd, et que certaines images Docker ont, côté utilisateurs et permissions, une complexité inutile pour Podman. En particulier, si un conteneur refuse de s’exécuter en root ou bascule vers un autre utilisateur, il faut parfois se coltiner des mappings d’IDusernspéniblesMalgré tout, dans l’ensemble, c’est beaucoup moins complexe que n’importe quelle configuration k8s ou variante de k8s. J’aime aussi le fait que tout soit intégré à systemd et journald, sans être scindé entre deux endroits
Comme il suffit de déposer les unités, c’est très stable et simple
composeen fichiers Quadlet, on peut utiliserpodlet: https://github.com/containers/podletMais ça ne remplace pas l’abstraction d’orchestration et de scheduling sur plusieurs nœuds fournie par k8s. Il manque la partie « voici des machines capables d’exécuter des fichiers Podman-systemd, voici la spécification que je veux lancer, placez-la comme il faut »
podman run, vérifier qu’il tourne correctement, puis créer un fichier conteneur de base avecpodlet, et enfin modifier ce fichier en séparant les volumes et le réseau dans d’autres fichiers QuadletLe projet
podman-composesemble toujours activement maintenu et peut être une bonne alternative àdocker-compose. Mais l’intégration entre Podman et systemd est tellement satisfaisanteL’étape suivante pour simplifier encore cela consiste à gérer les conteneurs avec Quadlet dans systemd. Les détails sont ici : https://www.redhat.com/en/blog/quadlet-podman
docker composevers Podman Quadlet rootless ; la transition a été difficile, mais je suis très satisfait du résultatJ’ai créé skate : https://github.com/skateco/skate. C’est essentiellement fait pour ce genre d’usage, mais avec la prise en charge de plusieurs hôtes et aussi des manifestes k8s. En interne, ça utilise Podman et systemd
En revanche, je trouve que k8s a une API et une expérience utilisateur catastrophiques. La spec Docker Compose est beaucoup plus conviviale, donc j’expérimente actuellement un
docker-composemulti-hôtes : https://github.com/psviderski/uncloudJe suis revenu à une approche où je empaquette de nouveau en paquets deb et les exécute directement avec systemd sur des instances EC2, sans utiliser de conteneurs. Les instances sont placées dans un Auto Scaling Group derrière un ALB, et au démarrage un simple
ansible-pullinstalle le debC’est assez brut de décoffrage, mais j’en avais assez du HCL dans du YAML dans du JSON à n’en plus finir. Maintenant, je veux seulement avoir à gérer un peu de YAML Ansible
apt full-upgradeet de redémarrer uniquement les processus en cours pour être protégéPas besoin de reconstruire quoi que ce soit, ni de chercher comment mettre à jour une bibliothèque enfouie au fin fond d’un conteneur que l’on a peut-être construit soi-même, ou pas
Grâce à la prise en charge des cgroups, c’est aussi pratique pour faire tourner plusieurs services sur un seul VPS
L’article datant de plus d’un an, il existe désormais même ParticleOS, une distribution d’OS officiellement prise en charge par systemd pour les workflows immuables
https://github.com/systemd/particleos
https://news.ycombinator.com/item?id=43649088
systemd-kernel, et là ce serait completÀ la lecture, tout cela semble pouvoir être remplacé par une commande
docker composeet quelque chose comme Caddy, qui récupère automatiquement les certificatsAvec seulement
compose.yaml, en gros une seule ligne suffit :docker compose up -d --pull always. Pour la configuration CI,scp compose.yaml user@remote-host:~/puisssh user@remote-host 'docker compose up -d --pull always'suffisent aussiL’avantage, c’est que c’est simple et que ça fonctionne aussi sur une machine de développement. Bien sûr, si l’objectif secondaire est d’essayer des choses intéressantes et d’apprendre, Quadlet, k8s et systemd sont aussi de bons choix
docker context create --docker 'host=ssh://user@remote-host' remote-hostEnsuite, on peut utiliser
docker -c remote-host compose -f compose.yaml up -d --pull always, sans avoir à copier le fichier. De plus, si l’on configure les informations utilisateur dans~/.ssh/config, il n’est plus nécessaire d’écrireuser@dans les appels SSH, ce qui facilite la copie de la documentation ou des commandes au sein d’une équipeDOCKER_HOST. Attention toutefois : l’interpolation du fichiercomposeutilise les variables d’environnement localesComme je pense que déployer sur un seul serveur ne devrait pas être aussi compliqué, j’ai créé un outil qui déploie comme je le souhaite : https://harbormaster.readthedocs.io/
Harbormaster localise les dépôts via un fichier YAML, les clone et les met à jour périodiquement, puis exécute les fichiers Docker Compose qu’ils contiennent. Tout l’état est également conservé dans un seul répertoire, ce qui facilite les sauvegardes
Si vous n’avez besoin que d’un seul serveur, c’est l’outil d’orchestration de conteneurs le plus simple et le meilleur que j’aie vu jusqu’ici. J’aime le fait que toute la configuration soit déclarée dans le dépôt, que tout l’état soit dans un répertoire et que tout soit simplement des fichiers Compose
En lisant les commentaires ici, j’ai l’impression de prendre un coup de vieux. Plus personne n’utilise simplement ssh et nginx ?
On entasse tout dans une seule machine, on la sauvegarde de manière agressive, et c’est réglé. Pour un usage domestique, il n’est vraiment pas nécessaire d’aller jusqu’à gérer des microservices