Services
Après avoir vu les services de base de type ClusterIP dans l’article précédent (Lien vers l’article), nous avons compris que pour accéder à un service depuis l’extérieur d’un cluster, le ClusterIP ne suffit pas. Car comme son nom l’indique, le ClusterIP expose une IP qui n’est accessible que depuis l’adressage interne du cluster (à ne pas confondre avec les adresses des nœuds du cluster qui sont accessibles depuis l’extérieur du cluster tant qu’on est dans le même réseau où sont déployés les nœuds).
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, k8s réserve un port que tous les nœuds du cluster vont écouter. Lorsqu’on fait un appel vers une adresse IP d’un des nœuds avec le port qui a été réservé par k8s, le service kube-proxy, qui se trouve sur tous les nœuds, renvoie vers le nœud où se trouve votre application.
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éé :
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. 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://ADRESSEIP_DUN_NOEUD:31750.
Que ce soit l’un ou l’autre, l’appel va être renvoyé vers les endpoints 10.244.1.34:8080,10.244.2.33:8080, qui sont les adresses de nos pods :
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 dans le même réseau que celui où se trouvent les nœuds de notre cluster. Il est donc utile lorsqu’on veut tester une application depuis le réseau interne de l’entreprise quand le cluster est déployé sur celui-ci, ou lorsqu’on veut exposer une application en “production” pour des usages internes à l’entreprise.
Mais dans le cas où nous voudrions exposer un service à l’extérieur de l’entreprise pour des clients externes, par exemple un site internet pour des achats en ligne etc., nous ne pouvons pas recourir à un service de type NodePort. Nous avons donc besoin d’un autre type de Service qui va nous permettre d’exposer nos applications sur internet. C’est ce que nous allons voir dans l’article suivant.