Les services permettent de publier l'accès aux Pods au sein du cluster ou à l'extérieur. Les conteneurs au sein d'un Pod partagent la même configuration réseau et sont donc accessible par la même IP interne au cluster.
Il y a plusieurs possibilité selon ce que l'on souhaite faire.
C'est le mode par défaut de Kubernetes lorsque l'on crée un service. Il permet d'exposer un port au sein du cluster uniquement.
Remarque L'IP n'est pas publiée en dehors du cluster. L'IP allouée ne sera accessible que par les nodes du cluster. A noter aussi que les ClusterIP sont assignées par des règles Iptables dans la table NAT.
Ci-dessous un fichier YAML pour démarrer un Pod nginx et son service :
vim pod_nginx_service.yml
Contenu :
apiVersion: v1 kind: Pod metadata: name: nginx labels: app: mywebapp spec: containers: - name: nginx image: nginx:stable ports: - containerPort: 80 # Ci-dessous on affecte un nom au port #name: http-web-svc --- apiVersion: v1 kind: Service metadata: name: nginx-service spec: # ClusterIP étant le mode par défaut, il n'est pas obligé de définir le type pour le créer. #type: ClusterIP selector: app: mywebapp ports: - name: mywebport protocol: TCP port: 8080 targetPort: 80 # Si un nom a été donné au port du conteneur on peut cibler le port par son nom. #targetPort: http-web-svc
Explications, nous avons un YAML pour créer 2 objets :
Création du pod et du service :
kubectl apply -f pod_nginx_service.yml
Listons le pods créé :
kubectl get pods
Résultat attendu :
NAME READY STATUS RESTARTS AGE nginx 1/1 Running 0 21s
Listons les services :
kubectl get services # Même commande en plus court #kubectl get svc
l'IP de cluster 10.110.183.49 a été affecté au service :
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 8d nginx-service ClusterIP 10.110.183.49 <none> 8080/TCP 27s
Pour tester l'accès au nginx :
curl http://10.110.183.49:8080
Ci-dessous, nous allons lister les points de terminsons :
kubectl get endpoints # Version courte #kubectl get ep
Ce que nous constatons, c'est le service nginx-service cible le pod qui à l'IP 192.168.1.105 sur le port 80 :
NAME ENDPOINTS AGE kubernetes 10.0.6.8:6443 8d nginx-service 192.168.1.105:80 37s
Déployons un autre pod qui sera accessible par le même service :
vim pod_nginx2.yml
Contenu :
apiVersion: v1 kind: Pod metadata: name: nginx2 labels: app: mywebapp spec: containers: - name: nginx image: nginx:stable ports: - containerPort: 80
Lancement du pod :
kubectl apply -f pod_nginx2.yml
Vérification des endpoints :
kubectl get endpoints
Ce que nous pouvons voir c'est le service cible nginx-service 2 pods sur le port 80 :
NAME ENDPOINTS AGE kubernetes 10.0.6.8:6443 8d nginx-service 192.168.1.105:80,192.168.1.106:80 7m37s
La requête ci-dessous sera alternativement redirigée vers 192.168.1.105:80 et 192.168.1.106:80 :
curl http://10.110.183.49:8080
La création d'un service de type NodePort créé aussi un service ClusterIP mais en plus un port sera publié à l'extérieur du cluster. Un port sera ouvert sur chacun des nodes (le serveur virtuel ou physique). Les ports qui peuvent être utilisés sont supérieur à 30000.
Comme pour la création d'un service ClusterIP plus haut, nous allons créer un service et lancer un Pod :
vim pod_nginx_service_nodeport.yml
Contenu :
apiVersion: v1 kind: Pod metadata: name: nginx labels: app: mywebapp spec: containers: - name: nginx image: nginx:stable ports: - containerPort: 80 --- apiVersion: v1 kind: Service metadata: name: nginx-service spec: type: NodePort selector: app: mywebapp ports: - name: mywebport protocol: TCP port: 8080 targetPort: 80 nodePort: 31000
On retrouve les mêmes éléments que pour la création d'un ClusterIP à la différence près que :
On liste les services :
kubectl get svc
Résultat :
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 8d nginx-service NodePort 10.110.183.49 <none> 8080:31000/TCP 47m
Explications : On constate que le service est de type NodePort. Le service dispose quand même d'un Cluster IP (10.110.183.49).
Techniquement le pods est accessible en depuis les nodes ainsi :
curl http://10.110.183.49:8080
Mais aussi depuis l'extérieur sur chacune des IP des nodes :
curl http://10.0.6.8:31000 curl http://10.0.4.248:31000
Liste des nodes :
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME k8s-master Ready control-plane 11d v1.28.2 10.0.6.8 <none> Debian GNU/Linux 12 (bookworm) 6.1.0-15-cloud-amd64 docker://24.0.7 k8s-node Ready <none> 11d v1.28.2 10.0.4.248 <none> Debian GNU/Linux 12 (bookworm) 6.1.0-15-cloud-amd64 docker://24.0.7
A approfondir
La création d'un service de type LoadBalancer créé aussi les services NodePort et ClusterIP. En revanche, il permet d'équilibrer la charge vers les nodes avec l'utilisation d'un service de LoadBalancer externe ou cloud.
Fichier YAML correspond (identique à NodePort mais le type change) :
apiVersion: v1 kind: Pod metadata: name: nginx labels: app: mywebapp spec: containers: - name: nginx image: nginx:stable ports: - containerPort: 80 --- apiVersion: v1 kind: Service metadata: name: nginx-service spec: type: LoadBalancer selector: app: mywebapp ports: - name: mywebport protocol: TCP port: 8080 targetPort: 80 nodePort: 31000