K3S + K3D = K8S, un nouveau match parfait pour le dev et les tests

Travailler avec Kubernetes sur une machine locale quand on est Dev ou Ops n’est pas aussi simple qu’on pourrait le penser. Alors, comment créer facilement un cluster Kubernetes local qui réponde à ces besoins ? Chez SoKube nous utilisons intensivement k3d et k3s pour cela.
Il y a plus d’un an, j’avais présenté dans un précédent article ce qu’est k3d (avec k3s) et comment l’utiliser. Depuis, k3d a été entièrement réécrit. Les objectifs de cet article sont de montrer :
- Ce que sont k3d/k3s
- Les nouveautés de k3d v3
- Comment créer un cluster Kubernetes simple sur votre machine locale
- Comment créer un cluster Kubernetes multi serveurs (masters) et multi agents (workers) sur votre machine locale
- Comment créer un cluster avec une version spécifique de Kubernetes
- Comment remplacer le plugin CNI par défaut de k3s
- Comment remplacer le contrôleur d’ingress par défaut de k3s
- Comment utiliser un registre dédié pour télécharger les images avec k3s
- Quelles sont les autres alternatives
k3s/k3d ?
k3s est une distribution Kubernetes pleinement conforme, très efficace et légère. k3d est un utilitaire conçu pour faire tourner facilement k3s dans Docker, il fournit une CLI simple pour créer, lancer, supprimer un cluster Kubernetes pleinement conforme avec 1 à n nœuds.
K3s inclut :
- Flannel : un réseau overlay L2 très simple qui satisfait les exigences de Kubernetes. C’est un plugin CNI (Container Network Interface), au même titre que Calico, Romana, Weave-net. Flannel ne supporte pas les Network Policy de Kubernetes, mais il peut être remplacé par Calico (voir les sections suivantes).
- CoreDNS : un serveur DNS flexible et extensible qui peut servir de DNS du cluster Kubernetes
- Traefik est un reverse proxy HTTP et un load balancer moderne. Dans une section suivante, je montrerai également comment le remplacer soit par Traefik v2, soit par Nginx
- Klipper Load Balancer : un load balancer de service qui utilise les ports disponibles de l’hôte.
- SQLite3 : le backend de stockage utilisé par défaut (supporte également MySQL, Postgres et etcd3)
- Containerd est un runtime de conteneurs comme Docker, sans la partie build d’image
Ces composants ont été choisis pour obtenir la distribution la plus légère possible. Mais comme nous le verrons plus loin dans cet article, k3s est une distribution modulaire dont les composants peuvent facilement être remplacés.
Récemment, k3s a rejoint la Cloud Native Computing Foundation (CNCF) au niveau sandbox en tant que première distribution Kubernetes (suscitant de nombreux débats sur le fait de savoir si k3s devrait plutôt être un sous-projet de Kubernetes).
Installation
L’installation est très simple et disponible via de nombreux installeurs : wget, curl, Homebrew, Aur, … et prend en charge tous les OS connus (linux, darwin, windows) ainsi que les architectures processeur (386, amd64) !
À noter que seul le client k3d doit être installé, il se chargera de créer un cluster k3s en utilisant la bonne image Docker.
Une fois installé, configurez l’autocomplétion avec votre shell préféré (bash, zsh, powershell), par exemple avec zsh :
|
Les nouveautés de k3d v3
En un an, l’équipe de k3d a fait un travail remarquable en réécrivant entièrement k3d v3. Il ne s’agit donc pas d’une simple montée de version majeure : de nouveaux concepts et structures ont été mis en place pour en faire un outil évolutif, doté de fonctionnalités très pratiques et intéressantes.
- Nouvelle terminologie de k3d et k3s : pour être aussi inclusive que possible vis-à-vis de la communauté, les termes “Server” et “Agent” sont désormais utilisés pour désigner les nœuds “master” et “worker”.
- Chaque cluster que vous créez génère désormais au moins 2 conteneurs : 1 load balancer et 1 nœud “server”. Le load balancer constitue le point d’accès à l’API Kubernetes, de sorte que même pour les clusters multi serveurs, un seul port API doit être exposé. Le load balancer se charge ensuite de proxifier vos requêtes vers le bon nœud server. (peut être désactivé avec le flag –no-lb)
- Adoption de la syntaxe “NOM VERBE” : ce changement structurant facilite l’ajout de nouveaux noms (c’est à dire les objets gérés par k3d) et se rapproche d’autres CLI cloud-native (gcloud, awscli, azure cli, …), tout en offrant une hiérarchie de commandes plus claire.
- Support des clusters multi serveurs (dqlite) avec rechargement à chaud de la configuration lors de l’ajout d’un nouveau nœud server au cluster
- Gestion des nœuds indépendamment des clusters :
k3d create/start/stop/delete node mynode - Autocomplétion shell via k3d completion [zsh | bash | psh | fish]
- Support basique d’un système de plugins (k3d my-plugin)
- …
Mon premier cluster k3d
Créons un cluster simple avec 1 loadbalancer et 1 nœud (avec le rôle de server et d’agent) nommé “dev” :
|
docker ps affichera les conteneurs sous-jacents créés par cette commande :


Mapping des ports :
--port 8080:80@loadbalancerajoute un mapping du port 8080 de l’hôte local vers le port 80 du loadbalancer, qui redirigera les requêtes vers le port 80 de tous les nœuds agents--api-port 6443: par défaut, aucun API-Port n’est exposé (pas de mapping de port hôte). Il sert à faire écouter l’API-Server de k3s sur le port 6443, ce port étant mappé sur le système hôte. Ainsi, le load balancer devient le point d’accès à l’API Kubernetes, de sorte que même pour les clusters multi serveurs, un seul port API doit être exposé. Le load balancer se charge ensuite de proxifier vos requêtes vers le nœud server approprié-p "32000-32767:32000-32767@loadbalancer": vous pouvez aussi exposer une plage de NodePort (si vous souhaitez vous passer du contrôleur d’Ingress).
Kubeconfig :
- Par défaut, le contexte courant du kubeconfig par défaut bascule directement sur le contexte du nouveau cluster, de sorte que votre “
~/.kube/config” est automatiquement mis à jour (vérifiez avec “kubectl config current-context”) - vous pouvez désactiver ce comportement avec le flag “
--update-default-kubeconfig=false” : il faudra alors créer un fichier kubeconfig et exporter la variable KUBECONFIG :export KUBECONFIG=$(k3d kubeconfig write dev) - La suppression du cluster supprimera également l’entrée dans le fichier kubeconfig.
- k3d fournit quelques commandes pour manipuler facilement le kubeconfig :
# récupérer le kubeconfig du cluster dev k3d kubeconfig get dev # créer un fichier kubeconfig dans $HOME/.k3d/kubeconfig-dev.yaml k3d kubeconfig write dev # récupérer le kubeconfig d'un ou plusieurs cluster(s) et # le(s) fusionner dans un fichier dans $HOME/.k3d ou un autre fichier k3d kubeconfig merge ...
Cycle de vie :
- Arrêter un cluster est très simple :
k3d cluster stop dev - Puis le redémarrer et restaurer l’état du cluster tel qu’il était avant l’arrêt :
k3d cluster start dev - Supprimer un cluster est tout aussi simple :
k3d cluster delete dev
Test avec une simple application conteneur nginx
Une fois le cluster lancé, exécutez les commandes suivantes pour tester avec un simple conteneur nginx :
|
Pour tester : http://localhost:8080/
Un cluster Kubernetes multi serveurs et multi agents sur votre machine locale
À des fins de test, et pour se rapprocher au maximum d’un cluster Kubernetes de production, vous pouvez créer un cluster multi serveurs et/ou multi agents :
|
Récupérer la liste des nœuds :
|
Une fois tous les nœuds démarrés, vous pouvez déployer la même application nginx à des fins de test. Passer l’application à 3 réplicas :
|
Les pods devraient se répartir sur les nœuds agents :

Ce cluster contient 7 images Docker représentant le cluster de test complet (1 loadbalancer, 3 conteneurs pour les servers et 3 conteneurs pour les agents). À noter que les nœuds server font également tourner des workloads :

Une fois le cluster créé, il est également possible d’ajouter des nœuds :
|
Un cluster avec une version spécifique de Kubernetes
Il peut être très pratique de créer un cluster Kubernetes avec une version spécifique, que ce soit une version plus ancienne :
|
ou une version plus récente :
|
La liste des versions disponibles se trouve dans le dépôt Docker de k3s. Actuellement, la version la plus ancienne de ce dépôt est la V1.16.x.
Utiliser Calico à la place de Flannel comme plugin CNI
Flannel est un très bon plugin CNI, léger, mais il ne supporte pas les ressources Network Policy de Kubernetes (à noter que la NetworkPolicy sera appliquée sans erreur, mais aussi sans aucun effet) ! La modularité de k3s permet de remplacer le CNI par défaut par Calico. Pour déployer Calico, 2 fonctionnalités de k3s sont utilisées :
--k3s-server-arg '--flannel-backend=none': retire Flannel de l’installation initiale de k3s.- Le déploiement automatique de manifests (“Auto-Deploying Manifests”), une fonctionnalité pratique de k3s : tout fichier trouvé dans
/var/lib/rancher/k3s/server/manifestssera automatiquement déployé sur Kubernetes, de manière similaire à un kubectl apply
Vous devrez donc enregistrer localement le fichier de configuration calico.yaml, puis créer le cluster avec les arguments suivants :
|
Test :
|
Tout devrait fonctionner Ajoutons maintenant une NetworkPolicy qui refuse toutes les communications :
|
Désormais, le pod “web” n’est plus accessible !
Changer le contrôleur d’Ingress par défaut
Par défaut, k3s utilise Traefik v1 comme contrôleur d’Ingress, mais il s’agit d’une ancienne version et Traefik v2 est sorti il y a plus d’un an avec de nombreuses fonctionnalités intéressantes, telles que le support TCP avec routage SNI et ports multi-protocoles, le déploiement Canary, le mirroring avec les Service Load Balancers, un nouveau Dashboard et une nouvelle WebUI… Il est prévu de remplacer par défaut ce contrôleur d’ingress par Traefik v2, mais là encore, la modularité de k3s permet dès à présent de remplacer le contrôleur d’Ingress par défaut grâce à :
--k3s-server-arg '--no-deploy=traefik': pour retirer traefik v1 de l’installation de k3s- Le déploiement automatique de manifests, comme mentionné précédemment
- Les opérateurs de charts Helm : k3s inclut un Helm Controller qui gère les charts Helm via une Custom Resource Definition (CRD) HelmChart
Remplacer par le contrôleur d’ingress Nginx :
Créez un fichier local “helm-ingress-nginx.yaml” :
|
puis créez le cluster avec le contrôleur d’Ingress Nginx
|
Remplacer par le contrôleur traefik v2
Créez un fichier local ‘helm-ingress-traefik.yaml’ :
|
Puis créez le cluster avec le contrôleur d’Ingress Traefik v2
|
Utiliser votre propre registre
Par défaut, k3s utilise DockerHub pour télécharger les images, mais il peut être très pratique d’utiliser son propre registre Docker
- Pour les environnements “Air-gap” où aucun accès internet n’est autorisé
- Pour se connecter à votre registre Docker d’entreprise (Harbor, Nexus, Artifactory, …)
- Pour valider la manière de se connecter à un registre externe
- Pour ceux qui disposent d’une connexion internet de mauvaise qualité (garder les images disponibles sur votre laptop).
Dans cet exemple, un registre très simple (celui de Docker) sera créé en tant que cache pull-through :
|
Créez un fichier local “registries.yaml” avec le contenu suivant :
|
host.k3d.internal : depuis la version v3.1.0, l’entrée host.k3d.internal est automatiquement injectée dans les conteneurs k3d (nœuds k3s) ainsi que dans la ConfigMap CoreDNS, ce qui permet d’accéder à votre système hôte depuis l’intérieur des nœuds k3s (qui tournent dans Docker) en la désignant simplement par host.k3d.internal.
Après la création d’un cluster k3d, vous pouvez vérifier cette configuration via :
|
Créez ensuite le cluster k3d en utilisant ce registre :
|
Toutes les images (y compris celles utilisées en interne par k3d et k3s) seront téléchargées vers le registre Docker, vous pouvez vérifier le contenu de votre registre via
|
Le déploiement d’une image nginx sera lui aussi téléchargé via le registre Docker :
|
Utiliser “host.k3d.internal” s’avère très pratique dans d’autres situations, lorsque vous souhaitez accéder à un service présent sur votre machine, ou même à un service se trouvant dans un autre cluster k3d.
Alternatives
Il existe plusieurs façons et outils de travailler avec un cluster Kubernetes local, parmi lesquels :
- K3d projet open source maintenu par Rancher
- Docker for Desktop produit Docker gratuit
- Minikube projet open source, Kubernetes SIGs (Special Interest Groups)
- Kind projet open source, Kubernetes SIGs (Special Interest Groups)
- MicroK8s projet open source maintenu par Canonical
- k0s projet open source maintenu par Mirantis
- CodeReady Container projet open source maintenu par RedHat
Aujourd’hui, ma préférence va à k3d, car il combine simplicité, extrême légèreté, modularité et fonctionnalité, tout en permettant de répondre à des besoins plus poussés. Mais les choses évoluent très vite, avec des fonctionnalités originales et innovantes. Et de nouveaux projets comme k0s semblent eux aussi très prometteurs.
Autres alternatives ou outils à considérer pour un usage en développement :
- Skaffold gère le workflow de build, de push et de déploiement de votre application sur Kubernetes
- Tye outil pour développeurs .Net qui facilite le développement, le test et le déploiement de microservices sur Kubernetes
- Devspace déployez et développez des applications Kubernetes plus rapidement
- Oketo une plateforme de développement Kubernetes dans le cloud
Conclusion
L’équipe Rancher a une nouvelle fois fait un excellent travail en réécrivant k3d, le rendant très simple, modulaire et efficace pour faire tourner plusieurs instances de clusters Kubernetes k3s, avec différentes topologies, sur une seule machine.
Les usages sont multiples et très adaptés au développement, au test et à la formation sur Kubernetes. k3s est une distribution de production sérieuse, qui répond également aux enjeux du edge computing et de l’IoT en proposant des architectures moins gourmandes en énergie et plus compactes, permettant d’évoluer vers une démarche GreenIT.
Par ailleurs, la distribution Kubernetes k3s est la première distribution Kubernetes de la Cloud Native Computing Foundation (CNCF). Son avenir est extrêmement prometteur, à suivre…
Pour aller plus loin, découvrez notre formation Kubernetes et l’accompagnement de nos experts Kubernetes.