Kubernetes avec Vagrant – Talos & kubeadm
Il peut être utile de monter rapidement un cluster Kubernetes de laboratoire pour explorer une solution ou faire un POC.
Chez OPS, nous avons répondu à cette question avec deux dépôts jumeaux : Vagrant-kubeadm et Vagrant-Talos.
Deux labs, deux systèmes d’exploitation radicalement opposés — et une couche applicative strictement identique, partagée entre les deux sous la forme d’un sous-module git. Voici comment ils s’articulent.
Deux OS opposés, un plan d’adressage commun
Les deux dépôts font tourner des machines VirtualBox (bientôt dispo pour libvirt/KVM) pilotées par Vagrant, sur le même réseau host-only 192.168.56.0/24, avec la même VIP d’API et le même pool LoadBalancer. Ce qui les sépare, c’est le modèle d’exploitation du système sous-jacent.
| Vagrant-kubeadm | Vagrant-Talos | |
|---|---|---|
| OS des nodes | Debian 13 | Talos Linux (immuable) |
| Accès node | vagrant ssh, apt, systemd | aucun SSH — API talosctl |
| Bootstrap | kubeadm init / join | talosctl bootstrap |
| VIP de l’API | keepalived (VRRP) | VIP native Talos |
| kube-proxy | remplaçable en eBPF | posé par Talos |
Dans les deux cas, la topologie va du control plane unique au HA complet à 3 control planes derrière une VIP, avec le nombre de workers souhaité.
Vagrant-kubeadm — l’installation vanilla
Ce lab n’est délibérément pas un installeur clé en main. Chaque VM est une Debian ordinaire avec SSH et apt ; chaque étape des scripts est une commande kubeadm que l’on pourrait taper soi-même, et la documentation les montre une par une.
Ce que le dépôt apporte, c’est la part ingrate et casse-figure du travail : la VIP qui doit exister avant le kubeadm init, la bonne node-ip , la configuration de containerd 2.x, et les SAN de certificats qu’on ne peut plus ajouter après coup.
git clone --recurse-submodules https://github.com/OPS-NC/Vagrant-kubeadm.git
cd Vagrant-kubeadm
cp lab.env.example lab.env # choix de la topologie
vagrant up # crée et PRÉPARE les VM (pas encore de cluster)
./kubeadm/cluster-up.sh # kubeadm init + join + kubeconfig
./_k8s/platform-up.sh # CNI, Envoy Gateway, metrics-server, TLS wildcard
En quelques commandes simples vous avez votre cluster kubeadm proche d’une installation de production disponible.
Vagrant-Talos — l’OS immuable, piloté par API
À l’exact opposé : Talos Linux n’a ni shell, ni SSH, ni gestionnaire de paquets. Le système de fichiers est en lecture seule, et toute la configuration passe par l’API talosctl depuis la machine hôte. Vagrant se contente ici de créer et démarrer les VM, qui bootent sur une ISO en mode maintenance.
git clone --recurse-submodules https://github.com/OPS-NC/Vagrant-Talos.git
cd Vagrant-Talos
vagrant up # les VM démarrent en mode maintenance
./talos/cluster-up.sh # config + bootstrap etcd + kubeconfig + health
export TALOSCONFIG="$PWD/_out/talosconfig" KUBECONFIG="$PWD/kubeconfig"
./_k8s/platform-up.sh
Le contraste pédagogique est le vrai bénéfice de la paire : la même plateforme applicative, déployée sur deux modèles d’exploitation que tout oppose.
On mesure alors très concrètement ce que l’immuabilité coûte et ce qu’elle apporte.
lab.env — une seule source de vérité
Chaque lab se configure par un unique fichier lab.env, copié depuis un modèle versionné et ignoré par git. Il est lu par le Vagrantfile, par le script de bootstrap et par la couche applicative : il n’y a plus rien à « garder aligné à la main » entre les trois étages.
CONTROL_PLANES=3 # 1 = simple, 3 = HA (quorum etcd)
WORKERS=3
CP_MEM=3072
CNI=cilium # cilium (défaut), calico ou flannel
KUBE_PROXY_REPLACEMENT=true
LAB_DOMAIN=k8s.mon-domaine.tld
SELF_SIGNED=true # false = Let's Encrypt DNS-01 via Cloudflare
La règle de précédence est constante partout : variable d’environnement réelle > lab.env > défaut. Une surcharge ponctuelle ne demande donc jamais d’éditer le fichier :
WORKERS=1 vagrant up
_k8s/ — la couche applicative, écrite une seule fois
C’est le cœur du dispositif. Tout ce qui vient après le bootstrap — CNI, Gateway API, stockage, bases de données, secrets, observabilité, sécurité, etc.
Ce code vit dans un troisième dépôt, k8s-playground, monté dans chaque lab comme sous-module git sur le chemin _k8s/.
Monté ainsi, il fonctionne sans qu’on lui déclare quoi que ce soit : il remonte au dossier parent, le reconnaît comme lab à son Vagrantfile, et en déduit la distribution. Les divergences entre Talos et Debian sont concentrées dans deux fichiers de profil.
La plateforme de base, en une commande
Un seul script pose le socle, dans l’ordre des dépendances : pas d’IP LoadBalancer sans annonceur L2, pas de HTTPS sans Gateway, pas d’interface web sans certificat.
- CNI — Cilium par défaut, avec pool d’IP LoadBalancer et annonce L2 (ARP)
- Envoy Gateway — contrôleur +
main-gatewayavec listeners:80et:443 - metrics-server — l’API
metrics.k8s.io(kubectl top, HPA) - TLS wildcard — AC locale auto-signée, ou Let’s Encrypt en DNS-01 Cloudflare
Le catalogue, entièrement opt-in
./_k8s/install.sh list # le catalogue complet
./_k8s/install.sh longhorn vault argocd # ce dont on a besoin
./_k8s/install.sh all # tout, dans l'ordre des dépendances
./_k8s/install.sh kubeadm longhorn # la distribution, explicitement
./_k8s/longhorn/longhorn-up.sh talos # un composant seul, hors du point d'entrée
La distribution s’écrit en premier argument, talos ou kubeadm, et elle est transmise telle quelle à chaque script de composant. Depuis la racine d’un lab elle est optionnelle : le point d’entrée la déduit de la structure du dépôt parent. La passer reste utile pour lever toute ambiguïté — et c’est elle qui l’emporte sur la détection.
Le catalogue compte aujourd’hui vingt et un composants, répartis en huit familles. La liste ci-dessous est celle du dépôt à l’instant où ces lignes sont écrites ; ./_k8s/install.sh list en donne toujours la version à jour, et all les enchaîne dans l’ordre des dépendances.
🌐 Réseau et TLS
| Composant | Ce qu’il déploie | Prérequis |
|---|---|---|
cilium | CNI par défaut, pool d’IP LoadBalancer et annonce L2 (ARP) | — |
calico | CNI alternatif via l’opérateur Tigera — CNI seul, sans annonce L2 | — |
envoy-gateway | contrôleur Envoy et main-gateway (listeners :80 et :443) | via platform |
self-signed | mode TLS par défaut : wildcard signé par une AC locale (openssl) | via platform |
cert-manager | wildcard TLS automatique, ACME DNS-01 Cloudflare | via platform si SELF_SIGNED=false |
💾 Stockage
| Composant | Ce qu’il déploie | Prérequis |
|---|---|---|
longhorn | stockage bloc répliqué — prérequis iSCSI différent selon la distro | SC longhorn, longhorn-r1 |
local-path | stockage local dynamique (hostPath) — chemin différent selon la distro | SC local-path |
minio | MinIO standalone : S3 et console, 1 nœud | — |
minio-cluster | MinIO distribué 4 nœuds (EC:2) — la cible des sauvegardes | — |
🐘 Bases de données
| Composant | Ce qu’il déploie | Prérequis |
|---|---|---|
cnpg | CloudNativePG : opérateur PostgreSQL HA, cluster 3 nœuds, bascule automatique, sauvegardes S3 et PITR | SC longhorn-r1 |
🪪 Identité
| Composant | Ce qu’il déploie | Prérequis |
|---|---|---|
keycloak | Keycloak déployé par son opérateur, realm lab déclaré, émetteur OIDC sur keycloak.<LAB_DOMAIN> | cnpg |
dex | Dex devant Keycloak : connexion kubectl en OIDC (oidc-login), droits pilotés par un groupe | keycloak |
🔐 Secrets
| Composant | Ce qu’il déploie | Prérequis |
|---|---|---|
vault | HashiCorp Vault HA (Raft), 3 nœuds, UI et API en HTTPS | SC longhorn |
vso | Vault Secrets Operator : secrets Vault projetés en Secret Kubernetes natifs (KV statique, base dynamique, PKI) | Vault descellé |
📈 Observabilité
| Composant | Ce qu’il déploie | Prérequis |
|---|---|---|
observability | kube-prometheus-stack (Prometheus, Grafana, Alertmanager) avec Loki et Alloy | SC longhorn-r1, CP ≥ 4 Go |
npd | node-problem-detector : santé des nodes remontée depuis le noyau | — |
chaos | chaoskube : supprime un pod au hasard, toutes les heures | — |
🛡️ Sécurité
| Composant | Ce qu’il déploie | Prérequis |
|---|---|---|
kyverno | moteur de policies et Policy Reporter (UI) — policies pédagogiques livrées en mode Audit | main-gateway |
trivy | Trivy Operator : scan continu des CVE, de la configuration, des secrets et du RBAC | kyverno (UI partagée) |
🧪 Démonstrations
| Composant | Ce qu’il déploie | Prérequis |
|---|---|---|
argocd | Argo CD (GitOps), UI HTTPS sur argo.<LAB_DOMAIN> | — |
wordpress-example | WordPress et MariaDB sur Longhorn, exposés par Envoy | kubectl apply, cf. README |
Chaque composant reste lançable seul, et chaque dossier embarque un parcours guidé : la même installation, commande par commande, avec ce qu’il faut observer à chaque étape. Le script tout-en-un et le parcours font exactement la même chose — l’un pour aller vite, l’autre pour comprendre.
Petit bonus, si vous utilisez Tailscale, un simple tailscale up --advertise-routes '192.168.56.0/24' vous permettra de contacter votre API k8s et votre Envoy-gateway depuis n’importe quelle machine de votre Tailnet.
Pour aller voir
Les trois dépôts sont publics, sous licence libre, et documentés en anglais comme en français.
Toutes les versions de charts sont épinglées et surchargeables par variable d’environnement.
- github.com/OPS-NC/Vagrant-kubeadm — documentation
- github.com/OPS-NC/Vagrant-Talos — documentation
- github.com/OPS-NC/k8s-playground — documentation
Un seul avertissement pratique : --recurse-submodules n’est pas optionnel.
Un git clone ordinaire laisse le dossier _k8s/ vide.
Laisser un commentaire