Créer 511 clusters Kubernetes interconnectés avec Cilium Cluster Mesh (Partie 1)

Joseph Ligier
8 min readJun 6, 2024

--

Cela me trottait dans la tête de jouer avec Cilium Cluster Mesh. Mais pour être didactique et pour vous tenir en haleine, on va essayer d’établir un petit record.

Donc le dessein de cette série d’articles est de déployer 511 clusters kubernetes qui peuvent communiquer entre eux avec Cilium Cluster Mesh dans un temps raisonnable.

Cluster what ?

Le but du Cluster Mesh c’est de pouvoir faire communiquer des pods de différents cluster Kubernetes sans passer le flux par des Load Balancers et de pouvoir mettre en place des règles de firewall (les fameuses Network Policy). Ça permet ainsi d’établir des règles de sécurité (segmentation), de faire du multi-région ou du multi-cloud.

Exemple de cas d’utilisation

Le multi-cluster Kubernetes n’est pas encore standardisé par la CNCF. Cela avance doucement. Il y a différentes solutions qui proposent cela comme par exemple Istio ou Submariner. Mais j’ai choisi Cilium car je connais mieux la solution.

Si vous voulez apprendre à créer un Cluster Mesh entre 2 clusters Kubernetes, je vous conseille ce lab d’Isovalent :

511 clusters pourquoi pas 512 ?

J’ai défini ce record à 511 car c’est la nouvelle limite du nombre de clusters possibles depuis la version 1.15 de Cilium. Si j’arrive déjà à en créer 100, j’en serais déjà content pour être honnête.

Quand y en a plus et ben y en a encore

Il y a d’autres contraintes au niveau de Cilium :

  • Même datapath mode (natif ou encapsulé) partout
  • Les CIDRs de chaque réseau des clusters doivent être disjoint
  • Les nœuds de tous les clusters sont routables (un nœud du cluster A doit pouvoir pinguer un autre nœud du cluster B pour simplifier)

Ce n’est pas magique ! Pour plus de détails, vous pouvez consulter la documentation.

Cluster Mesh avec 2 clusters

Infrastructure

Pour cette première partie et pour comprendre mieux ce qu’est le Cluster Mesh, je vais créer 2 clusters Kubernetes interconnectés avec Cluster Mesh avec Kind. Kind est distribution Kubernetes qui utilise Docker pour simuler les nœuds en local. Elle est très pratique pour tester Kubernetes et facile à automatiser dans les CI.

Créons d’abord l’infrastructure :

kind create cluster --name cmesh1 --config cmesh-1.yaml # Le premier cluster
Creating cluster "cmesh1" ...
✓ Ensuring node image (kindest/node:v1.27.3) 🖼
✓ Preparing nodes 📦 📦 📦
✓ Writing configuration 📜
✓ Starting control-plane 🕹️
✓ Installing StorageClass 💾
✓ Joining worker nodes 🚜
Set kubectl context to "kind-cmesh1"
You can now use your cluster with:

kubectl cluster-info --context kind-cmesh1

Not sure what to do next? 😅 Check out https://kind.sigs.k8s.io/docs/user/quick-start/

kind create cluster --name cmesh2 --config cmesh-2.yaml # Le deuxième cluster
Creating cluster "cmesh2" ...
✓ Ensuring node image (kindest/node:v1.27.3) 🖼
✓ Preparing nodes 📦 📦 📦
✓ Writing configuration 📜
✓ Starting control-plane 🕹️
✓ Installing StorageClass 💾
✓ Joining worker nodes 🚜
Set kubectl context to "kind-cmesh2"
You can now use your cluster with:

kubectl cluster-info --context kind-cmesh2

Not sure what to do next? 😅 Check out https://kind.sigs.k8s.io/docs/user/quick-start/

Les fichiers de configuration de kind (cmesh-1.yaml et cmesh-2.yaml) :

apiVersion: kind.x-k8s.io/v1alpha4
kind: Cluster
nodes:
- role: control-plane
- role: worker
- role: worker
networking:
disableDefaultCNI: true
podSubnet: "10.1.0.0/16"
apiVersion: kind.x-k8s.io/v1alpha4
kind: Cluster
nodes:
- role: control-plane
- role: worker
- role: worker
networking:
disableDefaultCNI: true
podSubnet: "10.2.0.0/16"

Les configurations des deux clusters sont assez simples :

  • On installe un control plane et deux workers.
  • On n’installe pas de CNI (pour pouvoir installer Cilium ensuite avec la configuration qu’on veut)
  • On définit les CIDRs des pods qui doivent être disjoint
Ce qu’on a créé avec Kind

Voici les deux contextes des deux clusters kubernetes après le déploiement :

kubectl config get-contexts
CURRENT NAME CLUSTER AUTHINFO NAMESPACE
kind-cmesh1 kind-cmesh1 kind-cmesh1
* kind-cmesh2 kind-cmesh2 kind-cmesh2

Cilium Cluster Mesh

Maintenant on va installer Cilium sur les deux clusters :

cilium install --set cluster.name=kind-cmesh1 --set cluster.id=1 --context kind-cmesh1
🔮 Auto-detected Kubernetes kind: kind
✨ Running "kind" validation checks
✅ Detected kind version "0.20.0"
ℹ️ Using Cilium version 1.15.5
ℹ️ Using cluster name "kind-cmesh1"
🔮 Auto-detected kube-proxy has been installed
cilium install --set cluster.name=kind-cmesh2 --set cluster.id=2 --context kind-cmesh2
🔮 Auto-detected Kubernetes kind: kind
✨ Running "kind" validation checks
✅ Detected kind version "0.20.0"
ℹ️ Using Cilium version 1.15.5
ℹ️ Using cluster name "kind-cmesh2"
🔮 Auto-detected kube-proxy has been installed

Il y a deux variables à définir pour différencier les clusters :

  • Le nom du cluster
  • L’id du cluster (il doit être différent de 0)

On a déployé le CNI, les agents cilium et l’opérateur cilium :

Comme le CNI est maintenant déployé, les pods (Coredns et local path provisioner) qui étaient en attente peuvent enfin être libérés :

Délivrés

Nous allons ensuite activer le Cluster Mesh :

cilium clustermesh enable --service-type NodePort --context kind-cmesh1
⚠️ Using service type NodePort may fail when nodes are removed from the cluster!
cilium clustermesh enable --service-type NodePort --context kind-cmesh2
⚠️ Using service type NodePort may fail when nodes are removed from the cluster!

À chaque fois on a un message d’avertissement un petit peu obscur. Explication.

Voilà ce qu’on a fait :

Création d’une API qui permet à un autre cluster d’avoir les données de l’etcd

Cilium Cluster Mesh Api récupère les données de l’etcd. Il est l’interface entre les agents cilium des autres clusters et l’etcd de son propre cluster. Cette communication se fait ici via un NodePort (défini précédemment dans la ligne de commande).

L’IP d’un des nœuds (pour le NodePort) est défini statiquement dans la configuration pour le Cluster Mesh. Ainsi si ce nœud tombe, l’IP ne sera plus disponible et le Cluster Mesh ne pourra plus se mettre à jour. Il est donc conseillé en production d’utiliser un service Load Balancer.

Cluster Mesh est donc activée mais ça ne fonctionne pas encore :

cilium clustermesh status --context kind-cmesh1 --wait
⚠️ Service type NodePort detected! Service may fail when nodes are removed from the cluster!
✅ Service "clustermesh-apiserver" of type "NodePort" found
✅ Cluster access information is available:
- 172.18.0.3:32379
✅ Deployment clustermesh-apiserver is ready
ℹ️ KVStoreMesh is disabled


🔌 No cluster connected

🔀 Global services: [ min:0 / avg:0.0 / max:0 ]
  • “No cluster connected”

Il ne reste plus qu’à connecter les deux clusters pour qu’ils soient au courant qu’ils existent :

cilium clustermesh connect --context kind-cmesh1 --destination-context kind-cmesh2
✨ Extracting access information of cluster kind-cmesh2...
🔑 Extracting secrets from cluster kind-cmesh2...
⚠️ Service type NodePort detected! Service may fail when nodes are removed from the cluster!
ℹ️ Found ClusterMesh service IPs: [172.18.0.5]
✨ Extracting access information of cluster kind-cmesh1...
🔑 Extracting secrets from cluster kind-cmesh1...
⚠️ Service type NodePort detected! Service may fail when nodes are removed from the cluster!
ℹ️ Found ClusterMesh service IPs: [172.18.0.3]
⚠️ Cilium CA certificates do not match between clusters. Multicluster features will be limited!
ℹ️ Configuring Cilium in cluster 'kind-cmesh1' to connect to cluster 'kind-cmesh2'
ℹ️ Configuring Cilium in cluster 'kind-cmesh2' to connect to cluster 'kind-cmesh1'
✅ Connected cluster kind-cmesh1 and kind-cmesh2!

Un nouveau message d’avertissement apparaît sur le certificat Cilium CA. Il devrait être le même sur les deux clusters si on veut utiliser les fonctionnalités de Hubble pour le Cluster Mesh. Ça serait mieux.

On voit alors que les deux clusters sont connectés :

cilium clustermesh status --wait --context kind-cmesh2
⚠️ Service type NodePort detected! Service may fail when nodes are removed from the cluster!
✅ Service "clustermesh-apiserver" of type "NodePort" found
✅ Cluster access information is available:
- 172.18.0.5:32379
✅ Deployment clustermesh-apiserver is ready
ℹ️ KVStoreMesh is disabled

✅ All 3 nodes are connected to all clusters [min:1 / avg:1.0 / max:1]

🔌 Cluster Connections:
- kind-cmesh1: 3/3 configured, 3/3 connected

🔀 Global services: [ min:0 / avg:0.0 / max:0 ]

Mission accomplie… Pour 2 clusters.

Les agents Cilium peuvent récupérer les informations de l’autre cluster

Pour aller plus loin

L’objet de l’article se concentre surtout sur le déploiement de la solution. Pour l’exploitation, je vous conseille :

Il y a également cet article avec Cluster Mesh et core DNS qui peut être à creuser :

Nettoyage

Il suffit de taper la commande suivante :

kind delete clusters cmesh1 cmesh2
Deleted nodes: ["cmesh1-control-plane" "cmesh1-worker" "cmesh1-worker2"]
Deleted nodes: ["cmesh2-worker" "cmesh2-worker2" "cmesh2-control-plane"]
Deleted clusters: ["cmesh1" "cmesh2"]

Automatisons

Pour pouvoir prétendre à le faire dans un temps raisonnable, il serait pertinent d’automatiser ce déploiement. Pour cela, nous allons utiliser OpenTofu et deux providers : kind et cilium (oui oui mon provider) :

Il suffit de taper :

git clone https://github.com/tf-cilium/terraform-kind-cilium-clustermesh
cd terraform-kind-cilium-clustermesh/
tofu init
tofu apply

Et quand on a fini de tester :

tofu destroy
En léger accéléré, ça a duré réellement 4 minutes

Vérification rapide que ça a bien marché :

Certains vont me dire : “c’est simple, il suffit de modifier le code pour avoir 511 clusters”.

Il y a différentes contraintes :

  • matériel : il faut une ou plusieurs très grosses machines ;
  • logiciel : quelle distribution Kubernetes prendre pour que ça fonctionne. Ce n’est pas sûr qu’on puisse créer 511 clusters Kind même si on a un serveur très puissant ;
  • code : avoir un code facile à exploiter (une variable “nombre de clusters” et ça déploie ce nombre de clusters serait bien) et parallélisable pour éviter que ça dure plus de 24 heures.
Création de 5 clusters EKS en Cilium Cluster Mesh avec Pulumi

Dans la prochaine partie, nous verrons plus en profondeur les différentes problématiques de cette scalabilité et tenter de répondre concrètement à cela.

--

--