Préparation à la CKA - 08 - Services - ClusterIP

Publié le 01/10/2024 par Ali Sanhaji

Services

Dans les articles précédents, nous avons vu comment déployer des applications conteneurisées sur Kubernetes en utilisant des Pods, puis des Deployments qui contrôlent ces pods via des ReplicaSets. On arrive donc à avoir nos conteneurs sur un cluster kubernetes. Maintenant, s’il s’agit d’une application web par exemple, il faut pouvoir y accéder. Comment fait-on sur Kubernetes ?

Nous passons par un objet de type Service, qui va recevoir la requête et la transmettre à un des pods en backend du deployment que l’on veut exposer. Ce Service nous donne au final une adresse IP sur laquelle nous connecter pour être redirigé vers l’un des pods en backend. Selon le type de Service que l’on utilise, on aura une adresse IP différente. Commençons par le plus basique, le Service de type ClusterIP.

ClusterIP

Lorsque nous avons créé notre cluster dans notre premier article de cette série (lien vers l’article), nous avons utilisé KubeADM auquel nous avons passé un argument —pod-network-cidr=10.244.0.0/16. Cette option nous permet de spécifier l’espace d’adressage dans lequel on va piocher des adresses IP afin de les assigner aux pods que l’on va créer sur le cluster.

Il existe plusieurs arguments à la commande KubeADM, parmi lesquels —service-cidr (que nous aurions pu spécifier) qui a pour valeur par défaut 10.96.0.0/12. C’est dans cet espace d’adressage que seront piochées les adresses qui seront attribuées aux objets Service de type ClusterIP que l’on va créer. Ils s’appellent justement ClusterIP car c’est une IP qui vient de l’espace d’adressage des services spécifié lors de la création du cluster k8s. Pour pouvoir accéder à ces adresses IP, il faut pouvoir accéder au réseau spécifié, donc soit y accéder en étant dans le même réseau, ou en ayant du routage vers ce réseau.

Exemple Voyant un exemple en déployant une application simple, un serveur web Apache, et en exposant ce déploiement avec un Service de type ClusterIP :

Tout d’abord, on créé le déploiement :

kubectl create deployment apache-clusterip --image=bitnami/apache:latest
deployment.apps/apache-clusterip created

Le pod a bien été déployé :

kubectl get pods
NAME                                READY   STATUS    RESTARTS   AGE
apache-clusterip-7c5f85d878-tpzkh   1/1     Running   0          6s

Nous allons mettre deux replicas sur ce déploiement pour voir le résultat sur le service :

kubectl scale deployment apache-clusterip --replicas=2
deployment.apps/apache-clusterip scaled
kubectl get pods
NAME                                READY   STATUS    RESTARTS   AGE
apache-clusterip-7c5f85d878-sfxhk   1/1     Running   0          4s
apache-clusterip-7c5f85d878-tpzkh   1/1     Running   0          29s

Pour exposer un déploiement avec un objet de type Service, on peut utiliser la sous-commande expose :

kubectl expose deployment apache-clusterip --port=8080 --target-port=8080 --type=ClusterIP
service/apache-clusterip exposed

Le —type=ClusterIP est optionnel car c’est la valeur par défaut de l’argument.

On peut alors voir qu’un service a bien été créé :

kubectl get service
NAME               TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
apache-clusterip   ClusterIP   10.110.74.224   <none>        8080/TCP   25s

Si on voit le détail du service :

kubectl describe svc apache-clusterip
Name:              apache-clusterip
Namespace:         default
Labels:            app=apache-clusterip
Annotations:       <none>
Selector:          app=apache-clusterip
Type:              ClusterIP
IP Family Policy:  SingleStack
IP Families:       IPv4
IP:                10.110.74.224
IPs:               10.110.74.224
Port:              <unset>  8080/TCP
TargetPort:        8080/TCP
Endpoints:         10.244.1.28:8080,10.244.2.27:8080
Session Affinity:  None
Events:            <none>

L’adresse 10.110.74.224 a été assignée à ce service, et c’est à partir de celle-ci qu’on va accéder au déploiement des serveurs Apache.

Ce service va écouter les appels vers l’adresse IP 10.110.74.224 sur le port 8080, et renvoyer vers l’un des deux endpoints 10.244.1.28:8080, 10.244.2.27:8080 sur le même port, comme nous l’avons spécifié avec —target-port, car l’image Apache qu’on a déployé écoute sur le port 8080.

Vous l’avez compris, les adresses IP des endpoints ne sont autres que celles des deux pods Apache que nous avons déployé tout à l’heure :

kubectl get pods -o wide
NAME                                READY   STATUS    RESTARTS   AGE     IP            NODE
apache-clusterip-7c5f85d878-sfxhk   1/1     Running   0          2m56s   10.244.2.27   k8s-node-2
apache-clusterip-7c5f85d878-tpzkh   1/1     Running   0          3m21s   10.244.1.28   k8s-node-1

Maintenant, nous pouvons tester l’accès au Service en appelant son adresse IP. On peut atteindre cette adresse si on fait l’appel depuis un des noeuds du cluster, par exemple celui du control plane :

ubuntu@k8s-controlplane:~$ curl http://10.110.74.224:8080
<html><body><h1>It works!</h1></body></html>

Conclusion

Nous avons vu comment exposer un déploiement via un objet de type Service. Mais nous avons vu uniquement le type de service basique qui est le ClusterIP. Dans le cas d’une architecture micro-service où plusieurs pods rendent un service particulier et d’avoir s’appeler les uns les autres, le service de type ClusterIP permet à un pod appartenant à un service A de contacter un service B via sa ClusterIP. L’appel sera renvoyé vers les endpoints, donc les pods, qui répondent à ce service B.

Malheureusement, le service ClusterIP à lui tout seul ne nous amène pas à grand-chose si nous voulons accéder à l’application depuis l’extérieur du cluster, par exemple à un site web que nous déployons sur kubernetes et auquel nous voulons donner accès à des utilisateurs externes.

Dans le prochain article, nous allons voir d’autres types de Services qui permettent d’ouvrir l’accès aux applications depuis l’extérieur du cluster.