Featured image of post Test de CKE, le Kubernetes managé chez Clever Cloud (partie 1)

Test de CKE, le Kubernetes managé chez Clever Cloud (partie 1)

Ecrit par ~ zwindler ~

La suite de ma saga avec Clever Cloud

Ça fait maintenant quelques années que je teste les produits de Clever Cloud sur ce blog. En 2022, j’avais testé le Clever Kubernetes Operator, qui permet de provisionner des services managés (MySQL, Redis, Pulsar…) directement depuis un cluster Kubernetes via des CRDs. En 2025, j’ai réessayé leur offre d’hébergement de sites statiques, et j’ai même poussé le délire jusqu’à déployer un control plane Kubernetes sur leurs apps Linux, pour rigoler en attendant leur offre managée.

Bref, à la fin de cet article, je concluais avec un trollface et un “j’attends mon accès au k8s managé de Clever Cloud”. Et bien… c’est maintenant !

Clever Cloud a lancé CKE (Clever Kubernetes Engine) en bêta publique. J’ai eu accès en avant-première pour tester et je leur ai fait quelques retours. Maintenant que le produit est public, j’ai enfin le droit de vous partager mes impressions.

CKE c’est quoi exactement ?

CKE est l’offre Kubernetes managée de Clever Cloud. Le positionnement est clair : Vanilla Kubernetes, pas de lock-in, le kubeconfig standard fonctionne avec kubectl comme n’importe où ailleurs.

Ce qui distingue CKE des offres plus conventionnelles, c’est ça :

  • Materia etcd : leur implémentation maison de l’API etcd, construite sur FoundationDB (pas d’etcd VM à provisionner ou dimensionner, c’est serverless). C’était pas gagné, cf cet article de Pierre Zemb “Diving into Kubernetes’ Watch Cache”
  • Infrastructure souveraine et isolée des autres clients : tout tourne sur des VMs dédiées, en France. Rien de mutualisé entre tenants.
  • Cilium + eBPF natif, avec WireGuard pour le chiffrement inter-nodes.

Activation : c’est un peu caché

CKE est en bêta publique, mais l’accès n’est pas actif par défaut. Il faut l’activer, soit via la CLI :

clever features enable k8s

Soit depuis l’interface web, dans l’onglet Labs de votre compte : https://console.clever-cloud.com/users/me/feature-list

L’onglet Labs n’est pas particulièrement mis en avant dans la console (il faut savoir où chercher). Une fois le feature flag activé, un nouveau menu apparaît dans la console et les commandes clever k8s sont disponibles dans la CLI (version 4.9+ requise).

Création d’un cluster

Depuis la CLI, voici la commande minimale pour créer un cluster :

clever k8s create moncluster --watch

--watch suit le déploiement jusqu’à ce que le cluster soit ACTIVE. En pratique, ça ressemble à ça :

⏳ Cluster status: DEPLOYING. Waiting for 10s before checking again...
✓ Cluster moncluster (kubernetes_01KRDDW6YNMDE7ZT0RYD3MY0GE) deployed successfully

On peut passer tout un tas d’options : version K8s (--cluster-version 1.36), topology, flavor du control plane, replication factor, autoscaling, CSI… On y reviendra.

Mais il est aussi possible, depuis peu, de créer un cluster via formulaire de création, avec un récapitulatif en temps réel.

SCREENSHOT console création cluster

On y retrouve tous les paramètres : version K8s, topology, flavor, replication factor, autoscaling, persistent storage. C’est bien fait, les topologies sont expliquées inline. Le nom de cluster est généré aléatoirement (style cunning-arcane-runic-corsair, modifiable bien sûr).

Les 3 topologies : Essential, Business, Enterprise

C’est l’un des aspects les plus inhabituel de CKE. Trois topologies sont disponibles à la création (et immutables après, ce qui oblige à bien choisir dès le départ).

TopologyOffreCe que vous payezUsage typique
ALL_IN_ONEEssentialrf (replication factor) × VM bundle (CP + worker intégré)Dev, test, petits clusters
DEDICATED_COMPUTEBusinessrf × VM CP + chaque worker VMProd avec isolation CP/workers
DISTRIBUTEDEnterprise5 composants × rf × VM + workersProd HA fine par composant

ALL_IN_ONE est la topologie par défaut. Le control plane et un worker node partagent la même VM (c’est le mode k3s-style, pour reprendre la description de la console). Ça a une conséquence concrète : kubectl get nodes liste le node du control plane comme worker disponible pour les pods.

DEDICATED_COMPUTE isole le CP sur ses propres VMs, les workers sont dans des node groups séparés. Avec un replication factor de 3, les VMs sont réparties sur les 3 datacenters parisiens de Clever Cloud (un datacenter peut tomber sans impacter le control plane).

DISTRIBUTED pousse l’isolation plus loin : chaque composant du CP (apiserver, controller-manager, scheduler, cloud-controller-manager, node-group-operator) tourne sur sa propre VM, avec sa propre flavor et son propre replication factor. J’ai du mal à voir dans quel cas c’est utile, mais pourquoi pas.

Un mot sur la tarification

Contrairement à certains cloud providers (de moins en moins cela dit…) qui offrent parfois le control plane quand il est mutualisé et ne facturent que les workers, Clever Cloud facture une vraie VM dédiée par cluster (rien de mutualisé entre tenants).

En ALL_IN_ONE, cette VM fait aussi office de worker, ce qui en fait paradoxalement l’option la moins chère. La flavor S (8 vCPU / 12 GB RAM) revient à 64 €/mois, CP et workers inclus sur la même machine. L’isolation se paye davantage : DEDICATED_COMPUTE commence à 96 €/mois pour le CP seul (+ workers séparés), DISTRIBUTED à 180 €/mois minimum pour 5 composants CP en 2XS.

Ce n’est pas donné pour du dev, mais le prix s’explique par le choix architectural : vous avez vraiment 8 vCPU / 12 GB de RAM rien que pour vous, pas un dixième de VM partagée entre dix clients.

Note : pendant la bêta publique, le CSI (Ceph) et les LoadBalancers ne sont pas encore facturés. Seuls le CP et les workers le sont.

Récupérer le kubeconfig

clever k8s get-kubeconfig moncluster > ~/.kube/clever.yaml
kubectl --kubeconfig ~/.kube/clever.yaml get nodes

Un détail à noter : l’API server écoute sur un port non standard (1032 ou 1022 selon les clusters). Ce n’est pas bloquant dans la plupart des environnements, mais j’ai eu la surprise de me retrouver bloqué depuis un réseau qui filtre les ports non-standards. À garder en tête si vous devez accéder au cluster depuis un réseau d’entreprise restrictif.

Anatomie du cluster

Une fois connecté, quelques observations :

$ kubectl get nodes -o wide
NAME                                      STATUS   VERSION   OS-IMAGE        KERNEL-VERSION                        CONTAINER-RUNTIME
control-plane-be4e3383-...-node           Ready    v1.36.0   Exherbo Linux   6.19.14-clevercloud-vm-dirty (amd64)  containerd://2.3.0

Exherbo Linux : on retrouve bien la marque de fabrique de Clever Cloud. Pour celleux qui ne connaissent pas, Exherbo est une distro minimaliste et source-based, peu connue en dehors de cercles très spécialisés. Le kernel est un build custom Clever Cloud (clevercloud-vm-dirty), et le container runtime est containerd 2.3.0.

Les composants pré-installés dans kube-system :

$ kubectl get pods -A
NAMESPACE     NAME                                    READY
kube-system   cilium-tv9m7                            1/1     # CNI
kube-system   cilium-operator-7db7f998d7-z5zq8        1/1
kube-system   coredns-5986bf5c44-wkzb9                1/1
kube-system   konnectivity-agent-l26kl                2/2     # proxy CP->workers
kube-system   kube-state-metrics-75b86d74f6-6slx8     2/2
kube-system   kubelet-csr-approver-68d5bfcb6b-kgz5c   1/1
kube-system   metrics-server-559c9b85f9-wflvk         1/1
kube-system   cc-collector-wwpld                      1/1     # collecteur OTel Clever Cloud

Quelques absences notables par rapport à une install classique : pas de kube-proxy (remplacé par Cilium en mode eBPF kube-proxy replacement).

Pour la petite histoire, les premiers teasers de CKE avaient montré l’usage de flannel. Heureusement que les équipes de clever ont écouté la communauté et migré vers cilium.

Konnectivity : l’isolation réseau du control plane

Le pod konnectivity-agent mérite une mention. C’est un composant qu’on retrouve assez souvent sur les Kubernetes managés et certaines distribution de Kubernetes. Il tourne sur chaque node (2 containers : proxy-agent + haproxy) et sert de proxy entre le control plane et les workers. Le CP ne parle pas directement aux pods : tout le trafic CP->workers (logs, exec, port-forward, métriques) passe par ce tunnel.

Pour un service managé, c’est la bonne pratique : le control plane n’a pas besoin d’accès réseau direct aux pods, et les workers n’ont pas besoin d’exposer kubelet directement au CP.

Materia etcd

Pas de pod etcd dans le cluster : c’est normal. Clever Cloud utilise Materia etcd, leur implémentation serverless de l’API etcd construite sur FoundationDB. C’est transparent pour vous.

Cilium

Le CNI est Cilium v1.19.1. Pour aller plus loin sur l’intégration Cilium/CKE, je vous recommande l’article de Joseph qui est le premier à en avoir parlé publiquement et qui s’y connaît bien mieux que moi sur le sujet.

Les NodeGroups

Les workers sont gérés via une CRD custom NodeGroup (groupe api.clever-cloud.com/v1).

apiVersion: api.clever-cloud.com/v1
kind: NodeGroup
metadata:
  name: mes-workers
spec:
  flavor: S
  nodeCount: 3
kubectl apply -f nodegroup.yaml

Les nodes apparaissent dans kubectl get nodes environ 35-40 secondes après la création du NodeGroup. La CRD supporte le subresource scale, ce qui permet de faire :

kubectl scale nodegroup mes-workers --replicas=5

Les flavors disponibles en ALL_IN_ONE : S (8 vCPU / 12 GB), M (10 vCPU / 16 GB), L (12 vCPU / 24 GB), XL (16 vCPU / 32 GB). Un quota global s’applique au niveau de l’organisation (40 vCPU / 40 GB RAM par défaut, tous clusters confondus). Ca peut probablement être augmenté en faisant une demande au support, mais j’ai pas assez d’argent à crâmer pour justifier une telle demande 😅.

En cas de dépassement de quota, le NodeGroup passe en phase QuotaExceeded avec un message d’erreur très lisible :

'Quota exceeded: RAM max: limit = 40.0 GB | actual = 48.0 GB | excess = 8.0 GB'

C’est appréciable : on sait exactement ce qui bloque et de combien.

La CLI propose aussi une gestion des node groups :

clever k8s nodegroups create moncluster workers M:3
clever k8s nodegroups update moncluster workers --count 5
clever k8s nodegroups update moncluster workers --autoscaling --min 2 --max 10

Combien de temps pour booter ?

Un des points forts mis en avant par Clever Cloud. J’ai mesuré avec un script de benchmark (3 runs) et via la commande clever k8s activity qui expose les timestamps précis de chaque étape :

clever k8s activity moncluster --format json
[
  { "operation": "CREATE", "stepName": "Deploy Control Plane", "status": "STARTED",   "createdAt": "2026-05-12T06:27:11Z" },
  { "operation": "CREATE", "stepName": "Deploy Control Plane", "status": "COMPLETED", "createdAt": "2026-05-12T06:27:28Z" },
  { "operation": "CREATE", "stepName": "Install Plugins",      "status": "STARTED",   "createdAt": "2026-05-12T06:27:28Z" },
  { "operation": "CREATE", "stepName": "Install Plugins",      "status": "COMPLETED", "createdAt": "2026-05-12T06:28:01Z" }
]

activity détaille chaque étape du bootstrap : création du réseau, déploiement de Materia LogicalDB, déploiement du control plane, configuration du load balancer, installation des plugins. Elle couvre aussi les opérations sur les NodeGroups.

Résultats mesurés (K8s 1.35, 3 runs, 5 nodes S) :

ÉtapeMoyenne
Cluster DEPLOYING -> ACTIVE~57s
NodeGroup -> 1er node Ready~38s
NodeGroup -> tous les nodes Ready~46s
Suppression du cluster (API)~244ms

Pour comparaison, SKS d’Exoscale bootstrappe le control plane en ~2 minutes (on me souffle dans l’oreille que ça a peut être baissé depuis). Et à la bonne époque où je faisais du AKS, c’était carrément 20+ minutes (j’espère qu’ils se sont améliorés depuis). Clever Cloud se place très haut sur ce critère.

Réseau, services, sécurité

LoadBalancer: chaque service de type LoadBalancer provisionne un L4 LB avec deux IPs publiques dédiées.

Ingress : pas d’ingress controller préinstallé. Traefik s’installe sans problème via Helm.

NetworkPolicies : Cilium étant le CNI natif, les NetworkPolicies sont enforced nativement. Pas besoin d’installer quoi que ce soit en plus.

Note pour ceux qui auraient lu mon article de mars sur le CNI chaining Flannel/Cilium : cet article était né des tests sur la bêta privée de CKE, qui utilisait Flannel à l’époque. Depuis le passage en bêta publique, CKE livre Cilium nativement (les NetworkPolicies fonctionnent out of the box).

Pod Security Admission : aucun namespace n’a de labels PSA par défaut (ni kube-system, ni default). Ça signifie que les pods sont en mode privileged implicite, sans restriction. On peut bien sûr configurer ça soi-même, mais sur un cluster managé on s’attendrait à avoir au minimum des profils baseline ou restricted préconfigurés sur les namespaces utilisateur.

RBAC : pas de surprise, le kubeconfig fourni donne un accès cluster-admin. A ne pas utiliser au delà de l’administration initiale ;-).

Stockage (CSI)

Le CSI n’est pas activé par défaut. Pour l’activer :

clever k8s add-persistent-storage moncluster

Activation en ~1 minute. Une StorageClass csi-rbd-sc (défaut) est créée, provisionnée par rbd.csi.ceph.com (Ceph RBD), filesystem XFS, volume expansion activée.

Les tests complets du cycle de vie (PVC, resize, snapshots) feront l’objet de la partie 2.

Un vrai déploiement : GroROTI

Histoire de valider que tout fonctionne de bout en bout, j’ai déployé GroROTI (ma propre application web en golang de ROTI) via Helm, avec Traefik en ingress controller et un certificat TLS.

helm install traefik traefik/traefik -n traefik --create-namespace
helm install groroti oci://ghcr.io/zwindler/groroti-chart \
  -f values-clever.yaml \
  --namespace groroti --create-namespace

Au bout de quelques minutes, l’application tourne sur groroti.zwindler.fr, accessible publiquement, TLS inclus. Ça fonctionne.

Bugs rencontrés (alpha / bêta oblige)

LoadBalancer : lors de mes premiers tests (alpha / bêta privée), j’avais eu un cas où l’EXTERNAL-IP restait en <pending> pendant… 32 heures. Ce problème semble avoir disparu en bêta publique.

Cluster FAILED sans diagnostic : lors de mes tests, j’ai eu plusieurs clusters qui passaient en FAILED ~25 secondes après la création, sans aucun message d’erreur exploitable. clever k8s get <ID> retourne juste Status: FAILED, même avec --verbose. Aucune commande logs ou events pour un cluster n’existe dans la CLI.

C’est d’autant plus frustrant que le status QuotaExceeded des NodeGroups est, lui, extrêmement bien documenté dans le message d’erreur. Il y a une belle asymétrie là.

Le bug a été résolu côté Clever Cloud dans la nuit. Mais le manque de diagnostic reste un point à améliorer. L’UI est aussi encore clairement en bêta, avec un petit bug graphique que j’ai pu remonter.

Conclusion (partie 1)

Première impression globalement positive. CKE est impressionnant pour une bêta :

  • Boot time excellent : ~57s pour le cluster (CP à part ou All in one), ~38s pour le premier node quand on ajoute des NodeGroups (dans le haut du panier des Kubernetes managés que j’ai testé au fil des années)
  • Cilium natif avec WireGuard inter-nodes, NetworkPolicies out of the box
  • Materia etcd sur FoundationDB : une approche originale pour gérer les problématiques etcd (scalabilité, multi tenancy) d’un cloud provider
  • Design CRD propre pour les NodeGroups, compatible kubectl scale
  • Konnectivity : isolation réseau du CP comme chez les grands cloud providers

Les points à améliorer : diagnostic du status FAILED, PSA non configurée par défaut, pas d’ingress controller inclus.

La tarification du control plane me parait un poil élevée, typiquement face à des concurrents européens comme SKS ou Kapsule (mode mutualisé), mais elle s’explique par le choix architectural (VMs dédiées, rien de mutualisé). Pour une équipe déjà sur Clever Cloud, l’intégration avec le Clever Kubernetes Operator et les add-ons managés est un vrai argument.

Dans la partie 2, on creusera sûrement plus de fonctionnalités, comme le CSI (lifecycle PVC, resize, snapshots), les upgrades de cluster, l’intégration avec Clever Cloud operator (justement). Peut être aussi qu’on testera vCluster ou k3k ?

Licensed under CC BY-SA 4.0

Vous aimez ce blog ou cet article ? Partagez-le avec vos amis !   Twitter Linkedin email Facebook

Vous pouvez également vous abonner à la mailing list des articles ici

L'intégralité du contenu appartenant à Denis Germain (alias zwindler) présent sur ce blog, incluant les textes, le code, les images, les schémas et les supports de talks de conf, sont distribués sous la licence CC BY-SA 4.0.

Les autres contenus (thème du blog, police de caractères, logos d'entreprises, articles invités...) restent soumis à leur propre licence ou à défaut, au droit d'auteur. Plus d'informations dans les Mentions Légales

Généré avec Hugo
Thème Stack conçu par Jimmy