Préparation à la CKA - 09 - Services - NodePort

Publié le 08/10/2024 par Ali Sanhaji

Services

Après avoir présenté le Service de type ClusterIP, nous avons vu qu’il n’est accessible que depuis le réseau interne du cluster.

Pour exposer une application au-delà de ce réseau interne, nous avons besoin d’un autre type de Service : le NodePort.

Pour aller plus loin, nous avons besoin d’un type de Service qui est accessible à partir de l’extérieur du cluster. Nous allons donc présenter le Service de type NodePort.

NodePort

Le Service de type NodePort permet d’utiliser les adresses IP des nœuds du cluster afin d’accéder à un pod dans le cluster. Donc, cela rend possible d’accéder à un service du cluster sans être sur un nœud du cluster. Il suffit d’être sur le même réseau que les nœuds. Par exemple, si les nœuds k8s sont déployés dans le réseau interne de l’entreprise.

Lorsqu’on crée un Service de type NodePort, Kubernetes réserve un port (généralement compris entre 30000 et 32767) qui est ouvert sur tous les nœuds du cluster.
Le trafic reçu sur ce port est ensuite redirigé vers les Pods backend via kube-proxy.

Voici tout cela avec un exemple.

Exemple Nous allons d’abord créer un déploiement avec deux replicas de l’image d’un serveur web Apache :

kubectl create deployment apache-nodeport --replicas=2 --image=bitnami/apache:latest
deployment.apps/apache-nodeport created

Les pods ont bien été déployés :

kubectl get pods
NAME                               READY   STATUS    RESTARTS   AGE
apache-nodeport-6f44c7686d-s8dgc   1/1     Running   0          4s
apache-nodeport-6f44c7686d-td76m   1/1     Running   0          4s

Pour exposer le déploiement avec un service de type NodePort, nous devons spécifier l’option —type=NodePort :

kubectl expose deployment apache-nodeport --port=8080 --target-port=8080 --type=NodePort
service/apache-nodeport exposed

Le service a bien été crée :

kubectl get service
NAME              TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
apache-nodeport   NodePort    10.104.155.25   <none>        8080:31750/TCP   11s

Regardons ce service de plus près :

kubectl describe service apache-nodeport
Name:                     apache-nodeport
Namespace:                default
Labels:                   app=apache-nodeport
Annotations:              <none>
Selector:                 app=apache-nodeport
Type:                     NodePort
IP Family Policy:         SingleStack
IP Families:              IPv4
IP:                       10.104.155.25
IPs:                      10.104.155.25
Port:                     <unset>  8080/TCP
TargetPort:               8080/TCP
NodePort:                 <unset>  31750/TCP
Endpoints:                10.244.1.34:8080,10.244.2.33:8080
Session Affinity:         None
External Traffic Policy:  Cluster

Nous voyons que le service a bien assigné un port spécifique à ce service qui est le port numéro 31750. Les NodePorts sont, par défaut, alloués dans la plage 30000–32767, sauf configuration différente du cluster. Nous pouvons voir aussi que le service possède aussi une adresse IP de type ClusterIP qui est la 10.104.155.25. Donc si on veut appeler le service depuis l’adressage interne (pour pods et services) du cluster, on peut appeler sur le port 8080 qu’on a spécifié: http://10.104.155.25:8080, si en revanche on veut appeler le service depuis l’adressage du réseau des noeuds, donc potentiellement de l’extérieur du cluster, il faudra appeler http://ADRESSE_IP_DU_NOEUD:31750.

Dans les deux cas, le trafic est redirigé vers les endpoints correspondant aux Pods Apache (10.244.1.34:8080,10.244.2.33:8080 ).

kubectl get pods -o wide
NAME                               READY   STATUS    RESTARTS   AGE   IP            NODE         NOMINATED NODE
apache-nodeport-6f44c7686d-s8dgc   1/1     Running   0          91s   10.244.2.33   k8s-node-2
apache-nodeport-6f44c7686d-td76m   1/1     Running   0          91s   10.244.1.34   k8s-node-1

Faisons donc les appels avec les NodePort. Nous pouvons récupérer les adresses IP de nos noeuds :

kubectl get nodes -o wide
NAME               STATUS   ROLES           AGE    VERSION   INTERNAL-IP   EXTERNAL-IP   OS-IMAGE             KERNEL-VERSION      CONTAINER-RUNTIME
k8s-controlplane   Ready    control-plane   237d   v1.24.3   172.16.1.11   <none>        Ubuntu 20.04.4 LTS   5.4.0-122-generic   containerd://1.6.6
k8s-node-1         Ready    <none>          237d   v1.24.3   172.16.1.21   <none>        Ubuntu 20.04.4 LTS   5.4.0-144-generic   containerd://1.6.6
k8s-node-2         Ready    <none>          237d   v1.24.3   172.16.1.22   <none>        Ubuntu 20.04.4 LTS   5.4.0-122-generic   containerd://1.6.6

Donc nous pouvons appeler le service via les adresses IP 172.16.1.11, 172.16.1.21 et 172.16.1.22, sur le port 31750 :

curl http://172.16.1.11:31750
<html><body><h1>It works!</h1></body></html>
curl http://172.16.1.21:31750
<html><body><h1>It works!</h1></body></html>
curl http://172.16.1.22:31750
<html><body><h1>It works!</h1></body></html>

Conclusion

Le Service de type NodePort permet d’exposer une application au niveau des adresses IP des nœuds du cluster, en ouvrant un port spécifique accessible depuis le réseau où se trouvent ces nœuds.

Ce mécanisme est utile pour des tests, des environnements internes ou des architectures simples.
Cependant, pour exposer une application directement sur Internet de manière standardisée, d’autres mécanismes tels que les Services de type LoadBalancer ou les Ingress sont généralement privilégiés.