K8S #01 : Flannel, MetalLB, Nginx
A voir si j’en fais une sĂ©rie⊠đ€
Chose promise, chose due ! Mon cluster Kubernetes installĂ© via Kubeadm commence lentement mais sĂ»rement Ă prendre forme ! đ
I) Découverte de K8S, et de la partie Networking
Alors pour un peu de contexte, je ne suis clairement pas un expert en K8S… je suis familier avec les notions de base (pods, nodes, namespaces, services, deployment…) et la CLI, mais j’ai encore clairement Ă©normĂ©ment de choses Ă apprendre.
En gĂ©nĂ©ral, quand je veux me former Ă une techno j’aime bien avoir un objectif, un projet. Bref, avoir un lab. C’est donc comme ça que je me suis mis Ă installer un p’tit cluster via Kubeadm composĂ© de 3 nĆuds sous UbuntuServer. J’avais fait deux prĂ©cĂ©dents articles oĂč via Packer/Terraform je crĂ©ais le template, puis je le clonais et prĂ©parer les hĂŽtes.
Une fois le tout setupĂ©, mon premier rĂ©flexe a Ă©tĂ© de mettre en place le rĂ©seau. Et dĂ©jĂ lĂ faut apprendre deux trois bricoles d’entrĂ©e de jeu !
J’utilise kubeadm pour setuper mon cluster, et j’ai choisi Flannel comme CNI par dĂ©faut. La commande utilisĂ©e pour crĂ©er le tout a donc ressemblĂ© Ă ceci :
# On initialise notre cluster, en renseignant le subnet utilisé par les pods. Par défaut, Flannel utilise 10.244.0.0/16
sudo kubeadm init --pod-network-cidr=10.244.0.0/16
Mais ensuite il faut l’installer, ce fameux CNI qu’est donc Flannel ! Et lĂ , avant d’aller plus loin, expliquons ce que c’est et Ă quoi ça sertâŠ
II) Les CNIs, Container Network Interface
Un CNI est donc un plugin pour K8S responsable de la gestion du réseau pour les pods dans un cluster. Il va permettre de gérer la connexion entre les pods grosso modo.
Il existe forcĂ©ment une looooongue liste de CNIs… parmi lesquels :
- Flannel, trĂšs simple et trĂšs lĂ©ger Ă utiliser. En gĂ©nĂ©ral c’est celui que beaucoup de personnes choisissent ;
- Calico, un chouilla plus complexe et plus avancé. Comme dit plus haut, je ne suis pas expert donc je ne saurai vous dire les vraies options supplémentaires comparé à Flannel ;
- WeaveNet, … ;
- Cilium, … ;
- … ;
Bref, vous l’aurez compris, ici je vais me concentrer sur mon premier choix. Voyons maintenant comment installer tout ça !
III) Installation de Flannel
Pour ce faire rien de plus simple, il suffit de tĂ©lĂ©charger et appliquer le manifeste. Un manifeste n’est ni plus ni moins qu’un fichier permettant de dĂ©crire l’Ă©tat d’une ressource, comme un Deployment, un Service, un ConfigMap… avec ses caractĂ©ristiques, comme le nombre de rĂ©plicas, le nom de l’image, ses labels… :
kubectl apply -f https://raw.githubusercontent.com/flannel-io/flannel/master/Documentation/kube-flannel.yml
Et c’est bon ! On peut vĂ©rifier que nos pods sont bien en running, en vĂ©rifiant ceux tournant dans le namespace kube-flannel :
kubectl get pods -n kube-flannel

Comme quoi, pas si compliquĂ© que ça⊠maintenant passons Ă l’installation de MetalLB, et voyons en mĂȘme temps pourquoi nous en avons besoin.
IV) MetalLB, le « DHCP » pour LoadBalancers bare-metal
Comme dit en dĂ©but d’article, mon cluster est donc On-Premise, comprenez par lĂ qu’il n’est pas installĂ© sur un Cloud.
J’utilise aussi kubeadm pour setuper le tout, mais sachez qu’il existe plĂ©thore d’autres outils⊠alors ce n’est pas le sujet ici, mais par exemple il existe minikube, j’avais justement fait un article dessus il y a un sacrĂ© bout de temps. Bref, je digresse.
Tout ça pour dire qu’en gĂ©nĂ©ral, dans 90% du temps, on a son petit cluster K8S sur Azure/AWS/GCP, et nos services LoadBalancer rĂ©cupĂšrent une IP publique automatiquement. On a rien Ă configurer en CLI ou autre. Le bĂ©mol, c’est qu’ici, et beh c’est pas le cas.
Arrive alors MetalLB. Dans le titre je parle de « DHCP » mais c’est plus pour l’image ; en rĂ©alitĂ© c’est un contrĂŽleur de LoadBalancers pour Kubernetes, en tout cas c’est une des dĂ©finitions les plus probantes que j’ai pu trouvĂ©e.
En gros, on va l’installer sur notre cluster, lui renseigner une (ou plusieurs) plages d’adresses IPv4 (ou v6 !), et il va se charger de distribuer ces adresses Ă nos services LoadBalancer sur notre instance dĂšs que ceux-ci en auront besoin.
Bien, assez de blabla ! Pour l’installer, on a plusieurs choix (comme souvent avec K8S…) :
# Via un fichier manifeste, comme pour Flannel
kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.14.9/config/manifests/metallb-native.yaml
Soit via Helm, le « package manager » made in K8S :
helm repo add metallb https://metallb.github.io/metallb
helm install metallb metallb/metallb
Alors cet article commence dĂ©jĂ Ă devenir un peu long pour juste expliquer l’install’ de Flannel/MetalLB/Nginx Ingress Controller, donc je ne vais pas dĂ©crire prĂ©cisĂ©ment ce qu’est Helm, j’en ferai peut ĂȘtre un article dĂ©diĂ©. Sachez simplement qu’il permet d’installer/gĂ©rer des charts, des sortes d’applications K8S « prĂ©-packagĂ©s » dirons-nous.
Bref, qu’importe la façon que vous allez choisir, l’important est que ça tourne !

Une fois fait, il ne nous reste plus qu’Ă crĂ©er un petit fichier manifeste en Yaml qui va nous permettre de dĂ©finir notre fameuse plage d’IPs pour MetalLB :
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
name: example
namespace: metallb-system
spec:
addresses:
- 192.168.0.70-192.168.0.75
---
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
name: empty
namespace: metallb-system
Alors ici j’ai volontairement mis une petite plage, mais libre Ă vous d’adapter, en mettant par exemple :
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
name: example
namespace: metallb-system
spec:
addresses:
- 192.168.0.70-192.168.0.75 # Plage IPv4
- 2001:db8::10-2001:db8::15 # Plage IPv6
- 10.0.0.0/24 # Subnet IPv4 en notation CIDR
---
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
name: empty
namespace: metallb-system
Et il n’y a plus qu’Ă appliquer le tout !
# Ici mon fichier de config s'appelle donc metallb-config.yaml, et je l'ai créé dans un folder nommé metallb, histoire d'avoir un peu de clarté
kubectl apply -f metallb/metallb-config.yaml
Et pour tester la chose… si l’on appliquer ce fichier manifeste via un classique kubectl apply -f , et qui est un simple service web Apache avec un service de type LoadBalancer :
# Création du Namespace 'web'
apiVersion: v1
kind: Namespace
metadata:
name: web
---
# Déploiement d'un serveur web HTTP (Apache) dans le namespace 'web'
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-server
namespace: web
spec:
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
spec:
containers:
- name: httpd
image: httpd:2.4.48-alpine3.14 # Image du serveur web Apache
ports:
- containerPort: 80 # Le serveur web écoute sur le port 80
---
# Création d'un Service LoadBalancer pour exposer le serveur web à l'extérieur du cluster, et obtenir une IP de MetalLB justement
apiVersion: v1
kind: Service
metadata:
name: web-server-service
namespace: web
spec:
selector:
app: web # Sélectionne le Deployment avec l'étiquette 'app: web'
ports:
- protocol: TCP
port: 80 # Port du service exposé
targetPort: 80 # Port dans le conteneur
type: LoadBalancer # Type de service pour exposer à l'extérieur du cluster
Tadaaaaaa~ !

On voit bien ici que notre service dans le namespace web a bien reçu une external-ip ! Si c’est pas beau ça… đ„č
Maintenant qu’on a donc notre cluster avec Flannel d’installĂ©, MetalLB prĂȘt Ă distribuer des IPs pour nos services LoadBalancer… il ne reste qu’Ă installer notre cher Nginx Ingress Controller et on aura dĂ©jĂ une solide base pour faire mumuse !
*Nous n’aurons plus besoin de ce serveur web de test, donc autant supprimer le namespace entier. Comme ça, pas besoin de supprimer le Deployment et le Service manuellement.
kubectl delete namespace web
V) Nginx Ingress Controller
Alors initialement je comptais partir sur Traefik… j’avais fait quelques tests, et j’avais rĂ©ussi Ă setup l’accĂšs Ă l’interface web etc, mais pour une raison que j’ignore, impossible de faire du simple routage basĂ© sur un nom d’hĂŽte… ‘marche juste pĂŽ. J’ai cherchĂ© un peu mais plutĂŽt que de laisser le temps filer, je me suis dit qu’on pourrait trĂšs bien partir sur Nginx, qui est l’Ingress Controller de rĂ©fĂ©rence sur K8S đđ»ââïž
Bref ! On va donc utiliser Helm pour l’installer, en rajoutant en premier lieu le dĂ©pĂŽt :
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm repo update
Avant de procĂ©der Ă l’installation dans son namespace correspondant, on va rapidement rĂ©cupĂ©rer un fichier values.yaml et l’Ă©diter :
wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/refs/heads/main/charts/ingress-nginx/values.yaml
Et on s’assure que le paramĂštre hostNetwork soit bien Ă true :

Et enfin on peut crĂ©er notre namespace puis l’installer dans ce dernier !
kubectl create namespace nginx-controller
helm install ingress-nginx ingress-nginx/ingress-nginx -f values.yaml -n nginx-controller

Il rĂ©cupĂšre bien son IP ! Maintenant crĂ©ons rapidement un fichier manifeste pour un serveur web Apache, avec une IngressRoute nous permettant d’y accĂ©der via son FQDN, Ă savoir apache.tips4tech.local.
Bien-entendu, il vous faudra crĂ©er une entrĂ©e dans votre DNS. Ici, je fais donc pointer mon FQDN vers l’IP rĂ©cupĂ©rĂ©e par mon contrĂŽleur Nginx :
apache.tips4tech.local => 192.168.0.70
VoilĂ le manifeste pour Apache :
apiVersion: apps/v1
kind: Deployment
metadata:
name: apache-deployment
spec:
replicas: 3
selector:
matchLabels:
app: apache
template:
metadata:
labels:
app: apache
spec:
containers:
- name: apache
image: apache:latest
ports:
- containerPort: 80
resources:
requests:
memory: "64Mi"
cpu: "250m"
limits:
memory: "128Mi"
cpu: "500m"
---
apiVersion: v1
kind: Service
metadata:
name: apache-service
spec:
selector:
app: apache
ports:
- protocol: TCP
port: 80
targetPort: 80
type: ClusterIP
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: apache
annotations:
kubernetes.io/ingress.class: nginx
spec:
rules:
- host: apache.tips4tech.local
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: apache-service
port:
number: 80
On le démarre via un simple kubectl apply -f deploy-apache.yaml et on vérifie ça !


Parfait ! đ
On a dĂ©sormais rĂ©ussi Ă mettre en place Flannel, MetalLB, et notre Ingress Controller Nginx avec en prime le test d’un p’tit serveur web ! Pas mal comme dĂ©but !
VI) Conclusion
Comme dit en dĂ©but d’article, je ne suis (pas encore ?) un expert en K8S ! C’est pourquoi si certains abus de langage/petites coquilles se sont glissĂ©s dans cet article, n’hĂ©sitez clairement pas en commentaires đ«Ą.
J’ai dĂ©cidĂ© de partir pour le moment sur Nginx comme dĂ©jĂ dit aussi, car visiblement j’ai quelques p’tits soucis avec Traefik… rien d’insurmontable, un truc qui m’Ă©chappe et ça viendra vite. Mais voilĂ , je prĂ©fĂ©rai tout de mĂȘme avancer et ne pas rester bloquĂ© trop longtemps dessus.
Je ne sais pas non plus si je ferai une « SĂ©rie Kubernetes« , on verra. LĂ l’objectif, aprĂšs avoir setupĂ© toute la partie Network, ce serait de :
- Checker pour la partie Storage avec un grand S, c’est-Ă -dire montages NFS, voir du GlusterFS si j’me sens motivĂ©… j’ai justement retrouvĂ© dans mes brouillons un article traitant de cette techno… ‘article datant d’il y a 4 ans đ

- Checker pour installer Harbor, histoire d’avoir mon propre petit registre d’images Docker ;
- Revenir sur la partie Networking pour setup du HTTPs… en gĂ©nĂ©ral on peut utiliser Let’s Encrypt qui est super simple Ă setuper sur Traefik/Nginx, mais ici j’aimerai pousser le vice et utiliser ma propre PKI interne… et puis vu que c’est du On-Prem isolĂ©, pas possible d’utiliser Let’s Encrypt ici ;
- … ;
Bref, ce n’est que le dĂ©but, mais ça peut s’annoncer bien sympatoche ! Je vous tiens au courant de tout ça.
Sur ce, j’espĂšre encore et toujours vous avoir appris quelques bricoles, et vous souhaite une bonne journĂ©e/soirĂ©e ! Ciao !




2 comments