K3s : Déployez un Cluster Kubernetes Léger en Haute Disponibilité

K3s, le Kubernetes léger certifié CNCF en moins de 100 Mo. Installation single-node et HA, Traefik, Longhorn, Helm, monitoring et upgrade rolling.

Introduction : Kubernetes Sans la Complexité

Kubernetes est devenu le standard de facto pour l'orchestration de conteneurs. Mais soyons honnêtes : déployer et maintenir un cluster Kubernetes « vanilla » reste une épreuve technique considérable. Entre la gestion d'etcd, les certificats TLS, le networking CNI, les composants du control plane et les innombrables fichiers de configuration, la barrière d'entrée est élevée — surtout pour les petites équipes, les environnements edge ou les homelabs.

C'est exactement le problème que K3s résout. Créé par Rancher Labs (désormais partie de SUSE), K3s est une distribution Kubernetes certifiée CNCF qui tient dans un seul binaire de moins de 100 Mo. Lancé en 2019, K3s est devenu en 2026 la distribution Kubernetes légère la plus populaire au monde, déployée sur des millions de nœuds — des Raspberry Pi aux serveurs edge en passant par les clusters de production en entreprise.

Architecture en un coup d'œil

Diagramme - K3s : Déployez un Cluster Kubernetes Léger en Haute Disponibilité

Dans cet article, nous allons explorer K3s en profondeur : son architecture, ses différences avec Kubernetes standard, l'installation en mode single-node et multi-nodes, la haute disponibilité avec etcd embarqué, le déploiement d'applications, le monitoring, et bien plus encore.

Qu'est-ce que K3s ?

K3s est une distribution Kubernetes certifiée CNCF (Certified Kubernetes Conformant), ce qui signifie qu'elle passe tous les tests de conformité Kubernetes. Toute application compatible Kubernetes fonctionnera sur K3s sans modification.

Le nom « K3s » est un jeu de mots : si Kubernetes (K8s) a 8 lettres entre le K et le s, K3s en a seulement 3 — symbolisant sa légèreté.

Caractéristiques Principales

  • Binaire unique de moins de 100 Mo contenant tout le nécessaire
  • Kubernetes certifié CNCF à 100% de conformité
  • Démarrage en moins de 30 secondes
  • Consommation mémoire réduite : ~512 Mo de RAM pour le server, ~256 Mo pour un agent
  • Batteries included : Traefik (Ingress), CoreDNS, ServiceLB (ex-Klipper), local-path-provisioner, Flannel (CNI), Helm controller
  • SQLite par défaut pour le stockage (remplaçable par etcd, MySQL, PostgreSQL)
  • containerd intégré comme runtime de conteneurs
  • Support ARM64 et ARMv7 natif (Raspberry Pi, edge devices)
  • Mises à jour automatiques possibles via system-upgrade-controller

Ce que K3s Supprime par Rapport à K8s Standard

Pour atteindre sa légèreté, K3s fait des choix opinionés :

  • Drivers de stockage in-tree supprimés : Pas de drivers cloud intégrés (AWS, GCE, Azure). Utilisez les CSI drivers à la place.
  • Legacy API supprimées : Les API dépréciées sont retirées plus agressivement
  • etcd externe optionnel : SQLite par défaut (suffisant pour le single-node), etcd embarqué pour la HA
  • Docker non inclus : containerd est le runtime par défaut (Docker peut être ajouté si nécessaire)

Architecture de K3s

L'architecture de K3s se compose de deux types de nœuds :

Server (Control Plane)

Le nœud server exécute les composants du control plane Kubernetes :

  • kube-apiserver : Point d'entrée de l'API Kubernetes
  • kube-scheduler : Planification des pods sur les nœuds
  • kube-controller-manager : Contrôleurs Kubernetes (ReplicaSet, Deployment, etc.)
  • Datastore : SQLite (défaut), etcd embarqué, ou base externe
  • Tunnel proxy : Communication sécurisée entre server et agents

Par défaut, un nœud server exécute également les workloads (comme un agent). Ce comportement peut être désactivé avec le flag --node-taint.

Agent (Worker Node)

Les nœuds agent exécutent les workloads :

  • kubelet : Gestion des pods sur le nœud
  • kube-proxy : Gestion du networking des Services
  • containerd : Runtime de conteneurs
  • Flannel : CNI pour le réseau inter-pods

Composants Intégrés (Batteries Included)

Composant Rôle Alternative
Traefik Ingress Controller Nginx Ingress, HAProxy
CoreDNS DNS interne du cluster
ServiceLB (Klipper) Load Balancer pour les Services de type LoadBalancer MetalLB
local-path-provisioner Provisionnement automatique de PersistentVolumes sur le disque local Longhorn, NFS, Ceph
Flannel CNI (Container Network Interface) Calico, Cilium
Metrics Server Métriques des nœuds et pods
Helm Controller Déploiement de charts Helm via des manifestes

Installation Single Node

L'installation la plus simple : un seul nœud qui fait à la fois server et agent. Idéal pour le développement, les tests, ou les petits projets.

Prérequis

  • Linux (Ubuntu 20.04+, Debian 11+, RHEL/Rocky 8+, SLES 15+)
  • Minimum 1 CPU, 512 Mo de RAM (2 CPU / 2 Go recommandés)
  • systemd ou openrc
  • Accès root ou sudo

Installation Rapide

# Installation en une seule commande
curl -sfL https://get.k3s.io | sh -

# Vérifier que K3s est démarré
sudo systemctl status k3s

# Vérifier que le cluster est opérationnel
sudo k3s kubectl get nodes

# Le kubeconfig est automatiquement créé
sudo cat /etc/rancher/k3s/k3s.yaml

C'est tout. En moins de 30 secondes, vous avez un cluster Kubernetes fonctionnel avec Traefik, CoreDNS, et tout le nécessaire.

Installation Personnalisée

# Installation avec des options personnalisées
curl -sfL https://get.k3s.io | INSTALL_K3S_EXEC="server" sh -s - \
  --write-kubeconfig-mode 644 \
  --disable traefik \
  --disable servicelb \
  --flannel-backend wireguard-native \
  --cluster-cidr 10.42.0.0/16 \
  --service-cidr 10.43.0.0/16 \
  --tls-san mon-serveur.exemple.fr \
  --tls-san 192.168.1.100

Quelques options notables :

  • --write-kubeconfig-mode 644 : Rend le kubeconfig lisible sans sudo
  • --disable traefik : Désactive Traefik (si vous préférez Nginx Ingress ou autre)
  • --disable servicelb : Désactive le ServiceLB intégré (si vous utilisez MetalLB)
  • --flannel-backend wireguard-native : Chiffrement WireGuard pour le trafic inter-nœuds
  • --tls-san : Ajoute des Subject Alternative Names au certificat TLS de l'API server

Configurer kubectl

# Option 1 : Utiliser la commande k3s kubectl
sudo k3s kubectl get pods -A

# Option 2 : Configurer kubectl standard
mkdir -p ~/.kube
sudo cp /etc/rancher/k3s/k3s.yaml ~/.kube/config
sudo chown $(id -u):$(id -g) ~/.kube/config
export KUBECONFIG=~/.kube/config

# Vérifier
kubectl get nodes
kubectl get pods -A

Cluster Multi-Nodes : Server + Agents

Pour un cluster multi-nœuds simple (un server, plusieurs agents), la procédure est directe.

Sur le Server (nœud 1)

# Installer le server
curl -sfL https://get.k3s.io | sh -s - server \
  --write-kubeconfig-mode 644 \
  --tls-san k3s.exemple.fr \
  --tls-san 192.168.1.100

# Récupérer le token pour joindre les agents
sudo cat /var/lib/rancher/k3s/server/node-token
# Exemple : K10xxxx::server:yyyy

Sur les Agents (nœuds 2, 3, ...)

# Joindre le cluster comme agent
curl -sfL https://get.k3s.io | K3S_URL=https://192.168.1.100:6443 \
  K3S_TOKEN="K10xxxx::server:yyyy" \
  sh -s - agent

# Vérifier que l'agent a rejoint le cluster (depuis le server)
sudo k3s kubectl get nodes
# NAME     STATUS   ROLES                  AGE   VERSION
# node-1   Ready    control-plane,master   10m   v1.31.4+k3s1
# node-2   Ready    <none>                 2m    v1.31.4+k3s1
# node-3   Ready    <none>                 1m    v1.31.4+k3s1

Haute Disponibilité avec Embedded etcd

Pour la production, un seul server constitue un point de défaillance unique (SPOF). K3s supporte la haute disponibilité via etcd embarqué, nécessitant au minimum 3 nœuds server (nombre impair requis pour le consensus etcd).

Architecture HA

Le setup HA typique comprend :

  • 3 nœuds server avec etcd embarqué (quorum de 3)
  • N nœuds agent pour les workloads
  • 1 load balancer devant les servers (HAProxy, Nginx, ou un VIP avec Keepalived)

Installation du Premier Server

# Server 1 : Initialiser le cluster avec etcd embarqué
curl -sfL https://get.k3s.io | sh -s - server \
  --cluster-init \
  --write-kubeconfig-mode 644 \
  --tls-san k3s-vip.exemple.fr \
  --tls-san 192.168.1.100 \
  --tls-san 192.168.1.101 \
  --tls-san 192.168.1.102 \
  --node-taint CriticalAddonsOnly=true:NoExecute

# Le flag --cluster-init active etcd embarqué
# --node-taint empêche les workloads utilisateur sur les servers

# Récupérer le token
sudo cat /var/lib/rancher/k3s/server/node-token

Joindre les Servers 2 et 3

# Server 2
curl -sfL https://get.k3s.io | K3S_TOKEN="K10xxxx::server:yyyy" sh -s - server \
  --server https://192.168.1.100:6443 \
  --tls-san k3s-vip.exemple.fr \
  --tls-san 192.168.1.100 \
  --tls-san 192.168.1.101 \
  --tls-san 192.168.1.102 \
  --node-taint CriticalAddonsOnly=true:NoExecute

# Server 3 (même commande, exécutée sur le 3ème nœud)
curl -sfL https://get.k3s.io | K3S_TOKEN="K10xxxx::server:yyyy" sh -s - server \
  --server https://192.168.1.100:6443 \
  --tls-san k3s-vip.exemple.fr \
  --tls-san 192.168.1.100 \
  --tls-san 192.168.1.101 \
  --tls-san 192.168.1.102 \
  --node-taint CriticalAddonsOnly=true:NoExecute

Ajouter les Agents

# Les agents pointent vers le load balancer ou VIP
curl -sfL https://get.k3s.io | K3S_URL=https://k3s-vip.exemple.fr:6443 \
  K3S_TOKEN="K10xxxx::server:yyyy" \
  sh -s - agent

Load Balancer avec HAProxy

# /etc/haproxy/haproxy.cfg
frontend k3s-api
    bind *:6443
    mode tcp
    default_backend k3s-servers

backend k3s-servers
    mode tcp
    balance roundrobin
    option tcp-check
    server server1 192.168.1.100:6443 check
    server server2 192.168.1.101:6443 check
    server server3 192.168.1.102:6443 check

Vérifier le Cluster HA

# Vérifier les nœuds
kubectl get nodes
# NAME       STATUS   ROLES                       AGE   VERSION
# server-1   Ready    control-plane,etcd,master   15m   v1.31.4+k3s1
# server-2   Ready    control-plane,etcd,master   10m   v1.31.4+k3s1
# server-3   Ready    control-plane,etcd,master   8m    v1.31.4+k3s1
# agent-1    Ready    <none>                      5m    v1.31.4+k3s1
# agent-2    Ready    <none>                      4m    v1.31.4+k3s1

# Vérifier l'état d'etcd
sudo k3s etcd-snapshot list
# Vérifier la santé du cluster etcd
curl -sL https://192.168.1.100:2379/health --cacert /var/lib/rancher/k3s/server/tls/etcd/server-ca.crt --cert /var/lib/rancher/k3s/server/tls/etcd/server-client.crt --key /var/lib/rancher/k3s/server/tls/etcd/server-client.key

Installation avec k3sup

k3sup (prononcé « ketchup ») est un outil créé par Alex Ellis qui simplifie l'installation de K3s via SSH. Il est particulièrement utile pour provisionner rapidement un cluster depuis votre poste de travail.

# Installer k3sup
curl -sLS https://get.k3sup.dev | sh
sudo install k3sup /usr/local/bin/

# Installer K3s sur le premier server via SSH
k3sup install \
  --ip 192.168.1.100 \
  --user ubuntu \
  --ssh-key ~/.ssh/id_ed25519 \
  --cluster \
  --k3s-extra-args "--disable traefik --write-kubeconfig-mode 644" \
  --local-path ~/.kube/config \
  --context k3s-ha

# Joindre un second server
k3sup join \
  --ip 192.168.1.101 \
  --user ubuntu \
  --ssh-key ~/.ssh/id_ed25519 \
  --server-ip 192.168.1.100 \
  --server-user ubuntu \
  --server \
  --k3s-extra-args "--disable traefik"

# Joindre un agent
k3sup join \
  --ip 192.168.1.110 \
  --user ubuntu \
  --ssh-key ~/.ssh/id_ed25519 \
  --server-ip 192.168.1.100 \
  --server-user ubuntu

# Vérifier
export KUBECONFIG=~/.kube/config
kubectl config use-context k3s-ha
kubectl get nodes

Options de Configuration Avancées

Flags Importants

Flag Description Valeur par défaut
--disable Désactive un composant intégré
--flannel-backend Backend réseau Flannel vxlan
--cluster-cidr CIDR pour les pods 10.42.0.0/16
--service-cidr CIDR pour les services 10.43.0.0/16
--cluster-dns IP du service DNS 10.43.0.10
--data-dir Répertoire de données K3s /var/lib/rancher/k3s
--node-label Ajouter des labels au nœud
--node-taint Ajouter des taints au nœud
--kubelet-arg Arguments supplémentaires pour kubelet
--kube-apiserver-arg Arguments pour l'API server

Fichier de Configuration

Au lieu de passer des flags en ligne de commande, vous pouvez utiliser un fichier de configuration YAML :

# /etc/rancher/k3s/config.yaml
write-kubeconfig-mode: "0644"
tls-san:
  - "k3s.exemple.fr"
  - "192.168.1.100"
cluster-init: true
disable:
  - traefik
  - servicelb
flannel-backend: wireguard-native
node-taint:
  - "CriticalAddonsOnly=true:NoExecute"
kubelet-arg:
  - "max-pods=110"
  - "eviction-hard=memory.available<200Mi,nodefs.available<10%"
kube-apiserver-arg:
  - "default-not-ready-toleration-seconds=30"
  - "default-unreachable-toleration-seconds=30"

Registres Privés

# /etc/rancher/k3s/registries.yaml
mirrors:
  docker.io:
    endpoint:
      - "https://registry.exemple.fr"
  "registry.exemple.fr":
    endpoint:
      - "https://registry.exemple.fr"

configs:
  "registry.exemple.fr":
    auth:
      username: admin
      password: motdepasse
    tls:
      insecure_skip_verify: false

Déployer une Application Complète

Déployons une application web complète avec base de données, ingress, et certificat TLS pour illustrer les capacités de K3s.

Namespace et Base de Données

# app-namespace.yaml
apiVersion: v1
kind: Namespace
metadata:
  name: demo-app
---
# postgres-secret.yaml
apiVersion: v1
kind: Secret
metadata:
  name: postgres-secret
  namespace: demo-app
type: Opaque
stringData:
  POSTGRES_USER: appuser
  POSTGRES_PASSWORD: S3cur3P@ssw0rd!
  POSTGRES_DB: appdb
---
# postgres-pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: postgres-pvc
  namespace: demo-app
spec:
  accessModes:
    - ReadWriteOnce
  storageClassName: local-path
  resources:
    requests:
      storage: 5Gi
---
# postgres-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: postgres
  namespace: demo-app
spec:
  replicas: 1
  selector:
    matchLabels:
      app: postgres
  template:
    metadata:
      labels:
        app: postgres
    spec:
      containers:
        - name: postgres
          image: postgres:16-alpine
          ports:
            - containerPort: 5432
          envFrom:
            - secretRef:
                name: postgres-secret
          volumeMounts:
            - mountPath: /var/lib/postgresql/data
              name: postgres-storage
              subPath: pgdata
          resources:
            requests:
              cpu: 100m
              memory: 256Mi
            limits:
              cpu: 500m
              memory: 512Mi
      volumes:
        - name: postgres-storage
          persistentVolumeClaim:
            claimName: postgres-pvc
---
# postgres-service.yaml
apiVersion: v1
kind: Service
metadata:
  name: postgres
  namespace: demo-app
spec:
  selector:
    app: postgres
  ports:
    - port: 5432
      targetPort: 5432

Application Web

# app-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-app
  namespace: demo-app
spec:
  replicas: 3
  selector:
    matchLabels:
      app: web-app
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0
  template:
    metadata:
      labels:
        app: web-app
    spec:
      containers:
        - name: web-app
          image: nginx:alpine
          ports:
            - containerPort: 80
          resources:
            requests:
              cpu: 50m
              memory: 64Mi
            limits:
              cpu: 200m
              memory: 128Mi
          livenessProbe:
            httpGet:
              path: /
              port: 80
            initialDelaySeconds: 10
            periodSeconds: 10
          readinessProbe:
            httpGet:
              path: /
              port: 80
            initialDelaySeconds: 5
            periodSeconds: 5
---
# app-service.yaml
apiVersion: v1
kind: Service
metadata:
  name: web-app
  namespace: demo-app
spec:
  selector:
    app: web-app
  ports:
    - port: 80
      targetPort: 80

Ingress avec Traefik

# app-ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: web-app-ingress
  namespace: demo-app
  annotations:
    traefik.ingress.kubernetes.io/router.entrypoints: websecure
    traefik.ingress.kubernetes.io/router.tls: "true"
    cert-manager.io/cluster-issuer: letsencrypt-prod
spec:
  tls:
    - hosts:
        - app.exemple.fr
      secretName: web-app-tls
  rules:
    - host: app.exemple.fr
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: web-app
                port:
                  number: 80

Déployer le Tout

# Appliquer tous les manifestes
kubectl apply -f app-namespace.yaml
kubectl apply -f postgres-secret.yaml
kubectl apply -f postgres-pvc.yaml
kubectl apply -f postgres-deployment.yaml
kubectl apply -f postgres-service.yaml
kubectl apply -f app-deployment.yaml
kubectl apply -f app-service.yaml
kubectl apply -f app-ingress.yaml

# Ou en une seule commande si tout est dans un dossier
kubectl apply -f ./manifests/

# Vérifier le déploiement
kubectl get all -n demo-app
kubectl get ingress -n demo-app

Helm : Le Gestionnaire de Paquets Kubernetes

# Installer Helm
curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash

# Ajouter des repositories
helm repo add bitnami https://charts.bitnami.com/bitnami
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm repo update

# Installer une application avec Helm
helm install my-wordpress bitnami/wordpress \
  --namespace wordpress \
  --create-namespace \
  --set wordpressUsername=admin \
  --set wordpressPassword=MonMotDePasse \
  --set mariadb.auth.rootPassword=rootpwd \
  --set persistence.size=10Gi \
  --set service.type=ClusterIP

# Lister les releases Helm
helm list -A

K3s inclut également un Helm Controller qui permet de déployer des charts Helm via des manifestes Kubernetes natifs, sans avoir besoin du CLI Helm :

# HelmChart CRD (spécifique à K3s)
apiVersion: helm.cattle.io/v1
kind: HelmChart
metadata:
  name: prometheus
  namespace: kube-system
spec:
  repo: https://prometheus-community.github.io/helm-charts
  chart: kube-prometheus-stack
  targetNamespace: monitoring
  createNamespace: true
  valuesContent: |-
    grafana:
      adminPassword: MonGrafana2026!
      ingress:
        enabled: true
        hosts:
          - grafana.exemple.fr
    prometheus:
      prometheusSpec:
        retention: 15d
        storageSpec:
          volumeClaimTemplate:
            spec:
              storageClassName: local-path
              resources:
                requests:
                  storage: 50Gi

Stockage Persistant avec Longhorn

Le local-path-provisioner intégré à K3s est pratique mais limité : il stocke les données localement sur le nœud, sans réplication. Pour un stockage distribué et résilient, Longhorn (également de Rancher/SUSE) est le choix naturel.

# Installer les prérequis
sudo apt-get install -y open-iscsi nfs-common
sudo systemctl enable --now iscsid

# 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 \
  --set defaultSettings.defaultDataPath=/mnt/longhorn \
  --set ingress.enabled=true \
  --set ingress.host=longhorn.exemple.fr

# Vérifier l'installation
kubectl get pods -n longhorn-system
kubectl get storageclass

Longhorn offre :

  • Réplication des données entre les nœuds (configurable de 1 à N réplicas)
  • Snapshots et backups vers S3 ou NFS
  • Interface web de gestion
  • Disaster recovery avec restauration cross-cluster
  • Expansion de volume en ligne
  • Chiffrement des volumes

Ingress : Traefik vs Nginx

Traefik (Par Défaut)

K3s inclut Traefik comme Ingress Controller par défaut. C'est un choix solide avec le support automatique de Let's Encrypt, des middlewares puissants, et une interface dashboard.

Nginx Ingress Controller

Si vous préférez Nginx, désactivez d'abord Traefik puis installez Nginx Ingress :

# Si K3s est déjà installé avec Traefik, désactivez-le
# Ajoutez --disable traefik dans /etc/rancher/k3s/config.yaml
# puis redémarrez K3s

# Installer Nginx Ingress Controller
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm repo update

helm install ingress-nginx ingress-nginx/ingress-nginx \
  --namespace ingress-nginx \
  --create-namespace \
  --set controller.service.type=LoadBalancer \
  --set controller.publishService.enabled=true

Cert-Manager : Certificats TLS Automatiques

# Installer cert-manager
helm repo add jetstack https://charts.jetstack.io
helm repo update

helm install cert-manager jetstack/cert-manager \
  --namespace cert-manager \
  --create-namespace \
  --set crds.enabled=true

# Créer un ClusterIssuer Let's Encrypt
cat <<EOF | kubectl apply -f -
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: letsencrypt-prod
spec:
  acme:
    server: https://acme-v02.api.letsencrypt.org/directory
    email: admin@exemple.fr
    privateKeySecretRef:
      name: letsencrypt-prod
    solvers:
      - http01:
          ingress:
            class: traefik
EOF

# Vérifier
kubectl get clusterissuer
kubectl describe clusterissuer letsencrypt-prod

Monitoring : Prometheus + Grafana

Le monitoring est essentiel pour tout cluster de production. Le stack kube-prometheus-stack fournit tout le nécessaire.

# Installer le stack complet
helm install monitoring prometheus-community/kube-prometheus-stack \
  --namespace monitoring \
  --create-namespace \
  --set grafana.adminPassword=MonGrafana2026! \
  --set prometheus.prometheusSpec.retention=30d \
  --set prometheus.prometheusSpec.storageSpec.volumeClaimTemplate.spec.storageClassName=local-path \
  --set prometheus.prometheusSpec.storageSpec.volumeClaimTemplate.spec.resources.requests.storage=50Gi \
  --set alertmanager.alertmanagerSpec.storage.volumeClaimTemplate.spec.storageClassName=local-path \
  --set alertmanager.alertmanagerSpec.storage.volumeClaimTemplate.spec.resources.requests.storage=5Gi

# Accéder à Grafana (port-forward pour test rapide)
kubectl port-forward -n monitoring svc/monitoring-grafana 3000:80

# Ou via un Ingress pour un accès permanent
cat <<EOF | kubectl apply -f -
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: grafana-ingress
  namespace: monitoring
  annotations:
    cert-manager.io/cluster-issuer: letsencrypt-prod
spec:
  tls:
    - hosts:
        - grafana.exemple.fr
      secretName: grafana-tls
  rules:
    - host: grafana.exemple.fr
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: monitoring-grafana
                port:
                  number: 80
EOF

Le stack inclut des dashboards Grafana préconfigurés pour :

  • Vue d'ensemble du cluster (CPU, RAM, réseau par nœud)
  • Métriques des pods et conteneurs
  • Performance de l'API server
  • État de CoreDNS
  • Métriques des PersistentVolumes
  • Alertes préconfigurées (nœud down, disque plein, pod en CrashLoopBackOff, etc.)

Backup etcd

Pour les clusters HA avec etcd embarqué, les sauvegardes régulières sont critiques.

# Snapshot etcd manuel
sudo k3s etcd-snapshot save --name pre-upgrade-$(date +%Y%m%d)

# Lister les snapshots
sudo k3s etcd-snapshot list

# Les snapshots sont stockés dans :
ls -la /var/lib/rancher/k3s/server/db/snapshots/

# Configurer les snapshots automatiques
# Dans /etc/rancher/k3s/config.yaml :
# etcd-snapshot-schedule-cron: "0 */6 * * *"   # Toutes les 6 heures
# etcd-snapshot-retention: 10                    # Garder 10 snapshots
# etcd-snapshot-dir: /mnt/backup/etcd-snapshots  # Répertoire custom

# Restaurer depuis un snapshot (ATTENTION : opération destructive)
sudo systemctl stop k3s
sudo k3s server \
  --cluster-reset \
  --cluster-reset-restore-path=/var/lib/rancher/k3s/server/db/snapshots/pre-upgrade-20260307
sudo systemctl start k3s

Upgrade Rolling

K3s supporte les mises à jour via le System Upgrade Controller, qui permet des upgrades automatiques et contrôlés.

# Installer le System Upgrade Controller
kubectl apply -f https://github.com/rancher/system-upgrade-controller/releases/latest/download/system-upgrade-controller.yaml

# Attendre que le contrôleur soit prêt
kubectl get pods -n system-upgrade
# Plan d'upgrade pour les servers
apiVersion: upgrade.cattle.io/v1
kind: Plan
metadata:
  name: server-plan
  namespace: system-upgrade
spec:
  concurrency: 1
  cordon: true
  nodeSelector:
    matchExpressions:
      - key: node-role.kubernetes.io/control-plane
        operator: Exists
  serviceAccountName: system-upgrade
  upgrade:
    image: rancher/k3s-upgrade
  version: v1.31.5+k3s1
---
# Plan d'upgrade pour les agents
apiVersion: upgrade.cattle.io/v1
kind: Plan
metadata:
  name: agent-plan
  namespace: system-upgrade
spec:
  concurrency: 1
  cordon: true
  nodeSelector:
    matchExpressions:
      - key: node-role.kubernetes.io/control-plane
        operator: DoesNotExist
  prepare:
    args:
      - prepare
      - server-plan
    image: rancher/k3s-upgrade
  serviceAccountName: system-upgrade
  upgrade:
    image: rancher/k3s-upgrade
  version: v1.31.5+k3s1
# Appliquer les plans
kubectl apply -f upgrade-plans.yaml

# Surveiller la progression
watch kubectl get nodes
kubectl get plans -n system-upgrade

Upgrade Manuel

# Méthode manuelle (un nœud à la fois)
# 1. Drainer le nœud
kubectl drain node-1 --ignore-daemonsets --delete-emptydir-data

# 2. Mettre à jour K3s sur le nœud
curl -sfL https://get.k3s.io | INSTALL_K3S_CHANNEL=stable sh -

# 3. Rendre le nœud disponible
kubectl uncordon node-1

# 4. Vérifier
kubectl get nodes

Comparaison K3s / K0s / MicroK8s / kind

Critère K3s K0s MicroK8s kind
Éditeur SUSE/Rancher Mirantis Canonical Kubernetes SIG
Certification CNCF Oui Oui Oui Non (dev only)
Taille binaire ~70 Mo ~170 Mo ~200 Mo (snap) ~10 Mo (CLI)
RAM minimale 512 Mo 1 Go 1 Go Selon workload
Installation Script curl Script curl Snap Go install
HA intégrée Oui (etcd) Oui (etcd/kine) Oui (dqlite) Non
Support ARM Oui Oui Oui Oui
Composants intégrés Traefik, Flannel, CoreDNS, ServiceLB kube-router, CoreDNS Calico, CoreDNS, addons kindnet, CoreDNS
Cas d'usage principal Edge, IoT, prod, homelab Edge, production Dev, CI/CD, Ubuntu CI/CD, tests
Windows support Agents uniquement Agents uniquement Non (WSL2) Oui (Docker Desktop)
Communauté Très large Moyenne Large (Ubuntu) Large (dev/CI)

Quel Outil Choisir ?

  • K3s : Le choix polyvalent. Parfait pour la production légère, l'edge computing, les Raspberry Pi, les homelabs, et même les environnements de développement. Son écosystème (Longhorn, Rancher, k3sup) est le plus riche.
  • K0s : Alternative solide à K3s, avec un focus sur l'absence totale de dépendances système (zero friction). Bon choix pour les environnements très contraints.
  • MicroK8s : Idéal si vous êtes dans l'écosystème Ubuntu/Canonical. Le système d'addons (enable/disable) est très pratique. Moins adapté au vrai edge computing.
  • kind : Uniquement pour le développement local et les pipelines CI/CD. Crée des clusters éphémères dans des conteneurs Docker. Ne convient pas à la production.

Cas d'Usage de K3s

Edge Computing et IoT

K3s est la distribution Kubernetes la plus déployée en edge. Sa faible empreinte mémoire et son support ARM natif en font le choix idéal pour :

  • Points de vente : Gestion d'applications retail sur des mini-PC en magasin
  • Usines : Orchestration de conteneurs sur des passerelles industrielles
  • Télécommunications : Déploiement de fonctions réseau virtualisées (VNF)
  • Véhicules autonomes : Traitement d'images et ML embarqué

Homelab

K3s est devenu le standard de facto pour les homelabs :

  • Fonctionne sur des Raspberry Pi 4/5 en cluster
  • Compatible avec les mini-PC Intel N100/N305
  • Parfait pour héberger des services comme Immich, Nextcloud, Home Assistant, etc.
  • Facilement extensible avec Longhorn pour le stockage distribué

CI/CD

K3s est utilisé dans de nombreux pipelines CI/CD :

  • Clusters éphémères pour les tests d'intégration Kubernetes
  • Environnements de staging légers
  • Tests de Helm charts et d'opérateurs

Production

De plus en plus d'entreprises utilisent K3s en production :

  • Microservices avec des contraintes de ressources
  • Clusters Kubernetes sur des VPS ou des serveurs dédiés
  • Déploiements multi-régions avec des clusters K3s interconnectés

Bonnes Pratiques de Production

Sécurité

# 1. Restreindre l'accès au kubeconfig
chmod 600 /etc/rancher/k3s/k3s.yaml

# 2. Activer les audit logs
# Dans /etc/rancher/k3s/config.yaml :
# kube-apiserver-arg:
#   - "audit-log-path=/var/log/k3s-audit.log"
#   - "audit-log-maxage=30"
#   - "audit-log-maxbackup=10"
#   - "audit-policy-file=/etc/rancher/k3s/audit-policy.yaml"

# 3. Network Policies (exemple : deny all par défaut)
cat <<EOF | kubectl apply -f -
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-all
  namespace: production
spec:
  podSelector: {}
  policyTypes:
    - Ingress
    - Egress
EOF

# 4. Pod Security Standards
# Labeler le namespace avec le niveau de sécurité
kubectl label namespace production \
  pod-security.kubernetes.io/enforce=restricted \
  pod-security.kubernetes.io/warn=restricted

Ressources et Limites

# LimitRange pour imposer des limites par défaut dans un namespace
apiVersion: v1
kind: LimitRange
metadata:
  name: default-limits
  namespace: production
spec:
  limits:
    - default:
        cpu: 500m
        memory: 512Mi
      defaultRequest:
        cpu: 100m
        memory: 128Mi
      type: Container
---
# ResourceQuota pour limiter les ressources totales du namespace
apiVersion: v1
kind: ResourceQuota
metadata:
  name: namespace-quota
  namespace: production
spec:
  hard:
    requests.cpu: "4"
    requests.memory: 8Gi
    limits.cpu: "8"
    limits.memory: 16Gi
    pods: "50"
    persistentvolumeclaims: "10"

Dépannage Courant

# Vérifier les logs du service K3s
sudo journalctl -u k3s -f

# Vérifier l'état des pods système
kubectl get pods -n kube-system

# Vérifier les événements du cluster
kubectl get events --sort-by=.metadata.creationTimestamp -A

# Problème de DNS ? Tester la résolution depuis un pod
kubectl run dns-test --image=busybox:1.36 --rm -it --restart=Never -- nslookup kubernetes.default

# Problème de networking ? Vérifier Flannel
kubectl get pods -n kube-system -l app=flannel
kubectl logs -n kube-system -l app=flannel

# Réinitialiser complètement K3s (DANGER : supprime tout)
/usr/local/bin/k3s-uninstall.sh      # Sur un server
/usr/local/bin/k3s-agent-uninstall.sh # Sur un agent

Conclusion

K3s a fondamentalement changé la perception de Kubernetes. Ce qui était autrefois réservé aux grandes entreprises avec des équipes platform engineering dédiées est désormais accessible à un développeur seul sur un Raspberry Pi. Et pourtant, K3s ne fait aucun compromis sur la conformité : c'est du vrai Kubernetes, certifié CNCF, compatible avec l'intégralité de l'écosystème.

En 2026, K3s est la distribution Kubernetes légère la plus mature et la mieux supportée. Que vous construisiez un homelab, déployiez des applications en edge, ou cherchiez une alternative plus simple à kubeadm pour vos clusters de production, K3s mérite d'être votre premier choix.

Les points clés à retenir :

  • Simplicité d'installation : Une commande curl pour un cluster fonctionnel
  • Haute disponibilité : etcd embarqué pour un setup HA sans composants externes
  • Batteries included : Traefik, CoreDNS, Flannel, ServiceLB — tout fonctionne out of the box
  • Écosystème riche : Longhorn, Rancher, k3sup, System Upgrade Controller
  • Polyvalence : Du Raspberry Pi au datacenter, du développement à la production
  • 100% Kubernetes : Aucune adaptation nécessaire pour vos manifestes et Helm charts
Ressources utiles :
Site officiel K3s
Documentation K3s
GitHub K3s
k3sup
Longhorn
Rancher
Vous vous êtes abonné avec succès à CodeClan
Parfait ! Ensuite, complétez le paiement pour obtenir un accès complet à tout le contenu premium.
Erreur ! Impossible de s'inscrire. Lien invalide.
Bienvenue ! Vous vous êtes connecté avec succès.
Erreur ! Impossible de se connecter. Veuillez réessayer.
Succès ! Votre compte est entièrement activé, vous avez maintenant accès à tout le contenu.
Erreur ! Le paiement Stripe a échoué.
Succès ! Vos informations de facturation sont mises à jour.
Erreur ! La mise à jour des informations de facturation a échoué.