← Retour au blog

2 mai 2026 · 9 min de lecture

Kubernetes low-cost : Hetzner, k3s, Argo CD et le vrai coût autour

Mon retour sur l'idée de monter un cluster Kubernetes abordable avec Hetzner, k3s et Argo CD : le cluster peut coûter peu, mais l'exploitation demande du temps.

Kubernetes a souvent une image d’infrastructure chère, réservée aux grosses équipes ou aux clouds managés type EKS, GKE et AKS. Cette image n’est pas complètement fausse : si on prend un cluster managé, des load balancers, du stockage, de l’observabilité et plusieurs environnements, la facture grimpe vite.

Mais ce n’est pas la seule façon d’aborder le sujet. Avec Hetzner, k3s et des outils comme hetzner-k3s, on peut monter un cluster Kubernetes sérieux sans payer plusieurs centaines d’euros par mois. On peut même viser un minimum de haute disponibilité pour un budget raisonnable.

Le piège, c’est de croire que le cluster est le produit fini. En réalité, créer le cluster est devenu la partie facile. Ce qui coûte cher, c’est tout ce qu’il faut autour pour l’opérer proprement.

Le cluster n’est plus la partie difficile

k3s a rendu Kubernetes beaucoup plus accessible. C’est une distribution légère, adaptée à des machines modestes, et suffisamment proche de Kubernetes pour garder les bons réflexes : manifests, ingress, services, secrets, volumes, namespaces.

Sur Hetzner, le rapport ressources/prix est très intéressant pour des projets personnels, des environnements de staging ou de petites plateformes. Avec hetzner-k3s, on peut déclarer un cluster dans un fichier YAML, créer les machines, configurer le réseau, installer k3s et obtenir un kubeconfig utilisable rapidement.

Ce n’est pas magique, mais ce n’est plus réservé à une équipe infra non plus.

cluster_name: traces-prod
kubeconfig_path: ./kubeconfig
k3s_version: v1.34.5+k3s1

networking:
  allowed_networks:
    ssh:
      - REPLACE_WITH_YOUR_ADMIN_IP/32
    api:
      - REPLACE_WITH_YOUR_ADMIN_IP/32
  private_network:
    enabled: true
    subnet: 10.0.0.0/16
  cni:
    enabled: true
    mode: flannel

datastore:
  mode: etcd

schedule_workloads_on_masters: false

masters_pool:
  instance_type: cx33
  instance_count: 1
  locations:
    - fsn1

worker_node_pools:
  - name: workers
    instance_type: cx33
    instance_count: 2
    location: fsn1
    labels:
      - key: ingress
        value: "true"

addons:
  csi_driver:
    enabled: true
  traefik:
    enabled: true
  servicelb:
    enabled: false
  metrics_server:
    enabled: true
  cloud_controller_manager:
    enabled: true
  system_upgrade_controller:
    enabled: true

protect_against_deletion: true

Ce genre de configuration rend Kubernetes presque banal à provisionner. Mais elle montre aussi que les vrais choix arrivent tout de suite : qui peut accéder à l’API, est-ce qu’on active un réseau privé, est-ce que les workloads tournent sur les masters, quel CNI utiliser, quels addons activer directement avec k3s et lesquels installer séparément.

Même dans une version simple, on ne déclare pas seulement “deux workers”. On décide déjà du modèle réseau, du stockage Hetzner via le CSI driver, du load balancing, des upgrades, de l’endroit où l’ingress a le droit de tourner.

Dans mon cas, j’ajoute aussi NetBird après l’installation pour raccorder les machines à un réseau privé d’administration :

additional_post_k3s_commands:
  - |
    if ! command -v netbird >/dev/null 2>&1; then
      curl -fsSL https://pkgs.netbird.io/install.sh | sh
    fi
  - |
    if ! netbird status >/dev/null 2>&1; then
      netbird up --setup-key REPLACE_WITH_NETBIRD_SETUP_KEY
    fi

Ce n’est pas indispensable pour tous les setups, mais ça illustre bien le sujet : le cluster est créé rapidement, puis on ajoute immédiatement des décisions de sécurité, d’accès et d’exploitation.

Mais “avoir un cluster” ne veut pas dire “avoir une plateforme”.

Argo CD rend le déploiement agréable

Une fois le cluster prêt, Argo CD est souvent l’étape qui donne l’impression que tout devient propre. On versionne les manifests, les charts Helm ou les overlays Kustomize. Le cluster synchronise l’état attendu depuis Git. On voit ce qui est déployé, ce qui dérive, ce qui échoue.

Pour une application, le modèle est très confortable :

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: api
  namespace: argocd
spec:
  project: default
  source:
    repoURL: https://github.com/example/infra
    targetRevision: main
    path: apps/api
  destination:
    server: https://kubernetes.default.svc
    namespace: api
  syncPolicy:
    automated:
      prune: true
      selfHeal: true

À partir de là, déployer une app peut devenir presque simple : un commit, une sync, un rollback si besoin. C’est très satisfaisant, surtout quand on vient de déploiements plus manuels.

Mais Argo CD ne remplace pas l’exploitation. Il rend le déploiement plus propre, pas l’infrastructure automatiquement fiable.

Un repo GitOps finit vite par ressembler à autre chose qu’un simple dossier apps. Même pour un petit cluster, on sépare naturellement les applications, les bases de données, l’observabilité, la plateforme, les repositories Helm, les secrets, l’ingress, le VPN.

argocd/
  apps/
    apps/
      backend.yaml
      webapp.yaml
      backend-worker-media.yaml
      backend-worker-transmission.yaml
    data/
      cnpg-cluster.yaml
      cnpg-operator.yaml
      redis.yaml
    observability/
      monitoring.yaml
      monitoring-addons.yaml
    platform/
      argocd-netbird.yaml
      cert-manager.yaml
      cert-manager-issuers.yaml
      grafana-netbird.yaml
      netbird-config.yaml
      netbird-operator.yaml
      traefik-public.yaml
    repositories/
      gitlab-group-repo-creds.yaml
    root-application.yaml
cert-manager/
  certificate-internal-root-ca.yaml
  clusterissuer-internal-bootstrap.yaml
  clusterissuer-internal-ca.yaml
  clusterissuer-letsencrypt-prod.yaml
charts/
clusters/
cnpg/
ingress/
monitoring/
  backend-api-servicemonitor.yaml
  cnpg-cluster-podmonitor.yaml
  grafana-dashboard-traces-api.yaml
  grafana-dashboard-traces-database.yaml
  grafana-dashboard-traces-redis.yaml
  prometheusrule-traces-alerts.yaml
netbird/
secrets/

C’est propre, et c’est justement ça le piège. L’arborescence donne une impression de contrôle. Mais chaque dossier représente aussi une responsabilité : base de données, certificats, réseau, accès privé, monitoring, secrets.

L’observabilité, par exemple, ce n’est pas juste “installer Prometheus”. On finit avec des ServiceMonitor, des PodMonitor, des dashboards Grafana, des règles Prometheus, des alertes spécifiques à l’API, PostgreSQL, Redis. Même chose pour le réseau privé : NetBird ou un VPN équivalent devient une vraie brique d’accès, pas un bonus.

Argo CD rend tout ça déclaratif, il ne rend pas tout ça gratuit.

La haute disponibilité peut coûter peu, mais elle se paie ailleurs

Sur le papier, faire de la haute disponibilité avec de petites machines Hetzner est tentant. Trois masters, plusieurs workers, un load balancer, et on évite qu’une seule VM fasse tomber toute la plateforme.

C’est déjà beaucoup mieux qu’un serveur unique avec Docker Compose.

Mais la HA ne se résume pas au nombre de nodes. Il faut aussi penser :

  • aux upgrades de k3s ;
  • au renouvellement des certificats ;
  • aux backups d’etcd ou de la base de données utilisée par le cluster ;
  • à la répartition des workloads ;
  • aux volumes persistants ;
  • aux pannes réseau ;
  • au comportement du cluster quand un node disparaît.

La facture cloud reste basse, mais la facture mentale augmente. Tu ne paies pas un fournisseur managé pour absorber une partie de cette complexité. Tu la récupères.

Ce n’est pas forcément un problème. Pour apprendre, expérimenter ou héberger des projets maîtrisés, c’est même très formateur. Il faut simplement être honnête sur le contrat : moins d’euros, plus de responsabilité.

Le vrai coût est autour du cluster

Le cluster Kubernetes est rarement ce qui prend le plus de temps une fois installé. Le vrai travail commence avec tout ce qu’une plateforme doit fournir pour être vivable.

Le monitoring arrive très vite. Pas juste “Prometheus est installé”, mais des métriques utiles, des alertes compréhensibles, et une façon de savoir si l’application est lente, saturée ou cassée.

Les logs deviennent indispensables dès qu’un pod redémarre, qu’une requête échoue ou qu’un worker disparaît. Sans ça, on finit par SSH dans les machines, ce qui est exactement ce qu’on voulait éviter.

Les secrets demandent aussi une vraie décision. Les mettre dans Git en clair est exclu. Il faut donc choisir entre Sealed Secrets, External Secrets, SOPS, un vault, ou une solution plus simple selon le contexte.

L’accès au cluster ne peut pas rester un kubeconfig admin partagé. Un VPN, du RBAC, des accès limités, une séparation des namespaces et des environnements deviennent vite nécessaires.

Les backups sont un autre sujet qu’on ne peut pas repousser longtemps. Pas seulement ceux du cluster, surtout ceux des données applicatives : PostgreSQL, Redis si nécessaire, fichiers, volumes, exports.

Et il faut documenter un minimum. Une infra personnelle non documentée marche tant que la personne qui l’a créée se souvient de tout. Trois mois plus tard, c’est déjà moins vrai.

Le piège du “j’ai juste besoin de déployer une app”

C’est souvent comme ça que ça commence. On veut déployer une API, un frontend, une base PostgreSQL, peut-être un worker. Kubernetes semble propre. Argo CD rend le déploiement élégant. Hetzner rend le coût acceptable.

Et petit à petit, on ajoute un ingress controller, cert-manager, du monitoring, un dashboard, un registry, des backups, un VPN, une stratégie de secrets, des alertes.

Chaque brique est justifiée. Aucune n’est absurde. Mais l’ensemble devient une plateforme.

La question n’est donc pas “est-ce que Kubernetes low-cost fonctionne ?”. Oui, ça fonctionne. La vraie question est : est-ce que le projet mérite que tu deviennes l’opérateur de cette plateforme ?

Pour un produit critique, le coût d’un cluster managé peut être plus rationnel que le temps passé à tout maintenir soi-même. Pour un projet personnel sérieux, un staging robuste ou une montée en compétence DevOps, Hetzner + k3s + Argo CD est une très bonne école.

Ce que je mettrais dès le départ

Si je devais repartir sur ce type d’infra, je ne commencerais pas par empiler toutes les briques possibles. Je poserais un socle minimal mais propre.

D’abord, un cluster reproductible depuis un fichier de configuration, pas une suite de commandes lancées à la main. Ensuite, Argo CD pour que l’état applicatif soit dans Git. Puis un ingress clair, cert-manager pour les certificats, et une stratégie de secrets décidée tôt.

Je mettrais aussi rapidement un monitoring simple. Pas forcément une usine à gaz, mais au moins de quoi répondre à trois questions : est-ce que le cluster est vivant, est-ce que l’application répond, et est-ce que les ressources sont proches de la limite ?

Enfin, je traiterais le VPN et les accès comme une priorité, pas comme une finition. Un cluster Kubernetes exposé ou administré n’importe comment peut devenir un problème plus vite qu’une simple VM.

Le compromis que je retiens

Kubernetes sur Hetzner avec k3s et Argo CD peut être une excellente option. On peut obtenir une infrastructure flexible, déclarative, plutôt robuste, et beaucoup moins chère qu’une plateforme managée équivalente.

Mais il ne faut pas confondre coût d’hébergement et coût d’exploitation. Le cluster peut être abordable. La plateforme autour demande du temps, des choix et une discipline.

Pour moi, c’est le bon compromis si l’objectif est d’apprendre, de garder la main, ou d’héberger des projets dont on accepte d’opérer l’infrastructure. Si l’objectif est simplement de livrer un produit sans porter l’infra au quotidien, Kubernetes low-cost n’est pas forcément le raccourci qu’il promet d’être.