k3s est une distribution Kubernetes certifiée, packagée en un seul binaire de moins de 100 MB. Développée par Rancher (SUSE), elle embarque tout le nécessaire : containerd, Flannel, CoreDNS, Traefik, metrics-server, local-path-provisioner. Compatible 100 % avec l'API Kubernetes standard.
Idéale pour : edge computing, IoT, CI/CD, développement local, clusters ARM.
Informations essentielles
Origine : Rancher / SUSE · Licence : Apache 2.0 · Architectures : x86_64, ARM64, ARMv7
Liens : Site officiel · Documentation · GitHub
Stack par défaut
| Composant | Valeur |
|---|---|
| Runtime | containerd (inclus) |
| CNI | Flannel |
| Ingress controller | Traefik |
| Stockage | local-path-provisioner |
| Base de données | SQLite (défaut), etcd, MySQL, PostgreSQL |
Composants embarqués
k3s intègre tout ce qu'il faut pour un cluster fonctionnel sans installation supplémentaire :
| Composant | Rôle |
|---|---|
| containerd | Runtime de conteneurs |
| Flannel | CNI (réseau pods) |
| CoreDNS | DNS interne cluster |
| Traefik | Ingress controller |
| metrics-server | Métriques CPU/RAM |
| local-path-provisioner | Volumes persistants locaux |
| kube-proxy | Proxy réseau |
| Helm controller | Déploiement de charts Helm natif |
Chaque composant peut être désactivé individuellement avec --disable <composant>.
Prérequis
Système d'exploitation
- Linux 64-bit : Ubuntu 20.04+, Debian 11+, RHEL/CentOS 8+, Raspberry Pi OS
- Kernel ≥ 4.0
iptablesounftablesdisponible
Ports à ouvrir
| Port | Protocole | Rôle |
|---|---|---|
| 6443 | TCP | API server Kubernetes |
| 10250 | TCP | kubelet (metrics) |
| 8472 | UDP | Flannel VXLAN (inter-nœuds) |
| 51820 | UDP | Flannel WireGuard (si activé) |
| 2379-2380 | TCP | etcd (HA uniquement) |
Désactiver le swap (recommandé)
sudo swapoff -a
# Rendre permanent
sudo sed -i '/ swap / s/^/#/' /etc/fstab
Installation
Nœud server (master) - installation rapide
curl -sfL https://get.k3s.io | sh -
Le script installe k3s, crée un service systemd k3s et le démarre automatiquement.
Vérifier le statut
sudo systemctl status k3s
sudo k3s kubectl get nodes
Configurer kubectl en local (sans sudo)
mkdir -p ~/.kube
sudo cp /etc/rancher/k3s/k3s.yaml ~/.kube/config
sudo chown $(id -u):$(id -g) ~/.kube/config
chmod 600 ~/.kube/config
# Vérification
kubectl get nodes
Installer une version spécifique
curl -sfL https://get.k3s.io | INSTALL_K3S_VERSION="v1.30.2+k3s1" sh -
Installation sans Traefik ni servicelb (cluster nu)
curl -sfL https://get.k3s.io | sh -s - \
--disable traefik \
--disable servicelb
Ajouter des nœuds workers
Récupérer le token du server
# Sur le nœud server
sudo cat /var/lib/rancher/k3s/server/node-token
Rejoindre le cluster
# Sur chaque nœud worker
curl -sfL https://get.k3s.io | \
K3S_URL=https://<IP_SERVER>:6443 \
K3S_TOKEN=<TOKEN> \
sh -
Vérifier les nœuds
kubectl get nodes -o wide
NAME STATUS ROLES AGE VERSION INTERNAL-IP
server-1 Ready control-plane,master 10m v1.30.2+k3s1 192.168.1.10
worker-1 Ready <none> 2m v1.30.2+k3s1 192.168.1.11
worker-2 Ready <none> 1m v1.30.2+k3s1 192.168.1.12
Premier déploiement
Déployer une application
# Créer un déploiement nginx
kubectl create deployment nginx --image=nginx:alpine --replicas=2
# Attendre que les pods soient prêts
kubectl rollout status deployment/nginx
# Vérifier
kubectl get pods -o wide
Exposer en NodePort
kubectl expose deployment nginx --type=NodePort --port=80
# Trouver le port assigné
kubectl get svc nginx
# NAME TYPE CLUSTER-IP PORT(S) AGE
# nginx NodePort 10.43.180.123 80:31234/TCP 5s
# Accéder
curl http://<IP_NODE>:31234
Exposer via un fichier YAML
# service-nginx.yaml
apiVersion: v1
kind: Service
metadata:
name: nginx
spec:
selector:
app: nginx
type: NodePort
ports:
- port: 80
targetPort: 80
nodePort: 30080
kubectl apply -f service-nginx.yaml
Ingress avec Traefik
Traefik est installé par défaut dans k3s et écoute sur les ports 80 et 443 du nœud server.
Ingress Kubernetes standard
# ingress-nginx.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: nginx-ingress
annotations:
traefik.ingress.kubernetes.io/router.entrypoints: web
spec:
rules:
- host: nginx.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: nginx
port:
number: 80
kubectl apply -f ingress-nginx.yaml
# Accéder via : curl -H "Host: nginx.example.com" http://<IP_SERVER>
IngressRoute Traefik (API native)
# ingressroute.yaml
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: nginx-route
spec:
entryPoints:
- web
routes:
- match: Host(`nginx.example.com`)
kind: Rule
services:
- name: nginx
port: 80
TLS avec Let's Encrypt
cert-manager n'est pas inclus dans k3s. Installez-le d'abord :
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/latest/download/cert-manager.yaml
# issuer.yaml
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-prod
spec:
acme:
server: https://acme-v02.api.letsencrypt.org/directory
email: admin@example.com
privateKeySecretRef:
name: letsencrypt-prod
solvers:
- http01:
ingress:
class: traefik
Stockage persistant
local-path-provisioner (inclus par défaut)
k3s inclut un provisioner de volumes locaux. Il crée des dossiers dans /var/lib/rancher/k3s/storage/.
# pvc-example.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: my-pvc
spec:
accessModes:
- ReadWriteOnce
storageClassName: local-path
resources:
requests:
storage: 5Gi
kubectl apply -f pvc-example.yaml
kubectl get pvc
Utiliser un PVC dans un pod
apiVersion: apps/v1
kind: Deployment
metadata:
name: app-with-storage
spec:
replicas: 1
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
containers:
- name: app
image: nginx:alpine
volumeMounts:
- name: data
mountPath: /data
volumes:
- name: data
persistentVolumeClaim:
claimName: my-pvc
Longhorn (stockage distribué - recommandé en prod)
# Installer Longhorn via Helm
helm repo add longhorn https://charts.longhorn.io
helm repo update
helm install longhorn longhorn/longhorn \
--namespace longhorn-system \
--create-namespace \
--set defaultSettings.defaultReplicaCount=2
Helm sur k3s
Helm CLI (standard)
# Installer Helm
curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash
# Vérifier
helm version
# Ajouter un repo et déployer
helm repo add bitnami https://charts.bitnami.com/bitnami
helm repo update
helm install my-redis bitnami/redis \
--namespace redis \
--create-namespace \
--set auth.enabled=false
kubectl get pods -n redis
HelmChart (controller natif k3s)
k3s inclut un controller Helm natif - déclarer un chart via un objet HelmChart :
# helmchart-grafana.yaml
apiVersion: helm.cattle.io/v1
kind: HelmChart
metadata:
name: grafana
namespace: kube-system
spec:
repo: https://grafana.github.io/helm-charts
chart: grafana
targetNamespace: monitoring
createNamespace: true
valuesContent: |-
adminPassword: "admin"
service:
type: NodePort
kubectl apply -f helmchart-grafana.yaml
# k3s gère l'installation automatiquement
kubectl get pods -n monitoring
Configuration avancée
Options de démarrage importantes
# Désactiver des composants spécifiques
curl -sfL https://get.k3s.io | sh -s - \
--disable traefik \ # Désactiver Traefik (utiliser NGINX Ingress)
--disable servicelb \ # Désactiver Klipper LB
--disable metrics-server # Désactiver metrics-server
# Forcer un CIDR de pods spécifique
curl -sfL https://get.k3s.io | sh -s - \
--cluster-cidr 10.244.0.0/16 \
--service-cidr 10.96.0.0/12
# Exposer l'API server sur une IP spécifique
curl -sfL https://get.k3s.io | sh -s - \
--tls-san 192.168.1.10 \
--tls-san mon-cluster.example.com
Fichier de configuration (recommandé)
Créer /etc/rancher/k3s/config.yaml avant l'installation :
# /etc/rancher/k3s/config.yaml
disable:
- traefik
- servicelb
cluster-cidr: "10.244.0.0/16"
service-cidr: "10.96.0.0/12"
tls-san:
- "192.168.1.10"
- "k3s.example.com"
node-label:
- "env=production"
Variables d'environnement utiles
# Installation silencieuse (pas de questions)
INSTALL_K3S_SKIP_START=true # Installer sans démarrer
INSTALL_K3S_SKIP_ENABLE=true # Ne pas activer le service systemd
K3S_KUBECONFIG_MODE="644" # Permissions du kubeconfig (accès sans sudo)
K3S_NODE_NAME="mon-server" # Nom du nœud
Haute disponibilité (HA)
k3s supporte le mode HA avec un datastore externe ou etcd embarqué.
HA avec etcd (recommandé pour 3+ nœuds)
# Premier server (initialise le cluster etcd)
curl -sfL https://get.k3s.io | sh -s - \
--cluster-init \
--tls-san <LOAD_BALANCER_IP>
# Token pour rejoindre
sudo cat /var/lib/rancher/k3s/server/node-token
# Autres servers (rejoignent le cluster)
curl -sfL https://get.k3s.io | sh -s - \
--server https://<PREMIER_SERVER>:6443 \
--token <TOKEN> \
--tls-san <LOAD_BALANCER_IP>
HA avec base de données externe
curl -sfL https://get.k3s.io | sh -s - \
--datastore-endpoint="mysql://user:pass@tcp(host:3306)/k3s"
Mise à jour
# Mettre à jour vers la dernière version stable
curl -sfL https://get.k3s.io | sh -
# Mettre à jour vers une version spécifique
curl -sfL https://get.k3s.io | INSTALL_K3S_VERSION="v1.30.2+k3s1" sh -
# Vérifier la version
k3s --version
kubectl version
Mettre à jour le server en premier, puis les agents.
Sauvegarde et restauration
Sauvegarder etcd
# Snapshot etcd (mode HA uniquement)
k3s etcd-snapshot save --name backup-$(date +%Y%m%d)
# Lister les snapshots
k3s etcd-snapshot ls
# Snapshots automatiques (toutes les 12h par défaut)
# Vérifier dans /var/lib/rancher/k3s/server/db/snapshots/
ls /var/lib/rancher/k3s/server/db/snapshots/
Restaurer un snapshot
# Arrêter k3s
sudo systemctl stop k3s
# Restaurer
k3s server \
--cluster-reset \
--cluster-reset-restore-path=/var/lib/rancher/k3s/server/db/snapshots/backup-20240115
# Redémarrer
sudo systemctl start k3s
Troubleshooting
Logs du server k3s
sudo journalctl -u k3s -f
sudo journalctl -u k3s --since "10 minutes ago"
Logs d'un agent
sudo journalctl -u k3s-agent -f
Inspecter un pod en erreur
# Voir les événements
kubectl describe pod <nom-pod>
# Logs du pod
kubectl logs <nom-pod>
kubectl logs <nom-pod> --previous # Logs du crash précédent
# Shell dans un pod
kubectl exec -it <nom-pod> -- /bin/sh
Pod bloqué en Pending
# Voir les événements du pod
kubectl describe pod <nom-pod> | grep -A10 Events
# Vérifier les ressources disponibles
kubectl top nodes
kubectl describe nodes | grep -A5 "Allocated resources"
Problème de certificats
# Regénérer les certificats (expire tous les 12 mois)
sudo k3s certificate rotate
sudo systemctl restart k3s
Vérifier la connectivité réseau
# Tester la résolution DNS interne
kubectl run test-dns --image=busybox --rm -it --restart=Never -- nslookup kubernetes.default
# Ping entre pods
kubectl run ping-test --image=busybox --rm -it --restart=Never -- ping <IP_POD>
Reset complet
# Sur les workers (d'abord)
sudo /usr/local/bin/k3s-agent-uninstall.sh
# Sur le server (en dernier)
sudo /usr/local/bin/k3s-uninstall.sh
Commandes utiles
# État général du cluster
kubectl get nodes -o wide
kubectl get pods -A
kubectl get svc -A
kubectl top nodes
kubectl top pods -A
# Contexte et config
kubectl config view
kubectl config current-context
# Events du cluster
kubectl get events -A --sort-by='.lastTimestamp' | tail -20
# Accès shell dans un pod debug
kubectl run debug --image=busybox --rm -it --restart=Never -- /bin/sh
# Redémarrer un deployment
kubectl rollout restart deployment/<nom>
# Scaler un deployment
kubectl scale deployment/<nom> --replicas=3
# Port-forward local
kubectl port-forward svc/<nom-service> 8080:80
Ressources
- Documentation officielle : https://docs.k3s.io
- Quick Start : https://docs.k3s.io/quick-start
- GitHub : https://github.com/k3s-io/k3s
- Releases : https://github.com/k3s-io/k3s/releases
- Blog Rancher : https://www.rancher.com/blog