Contactez-nous

Ecriture du manifeste YAML pour un Service (type NodePort)

Découvrez comment écrire un manifeste YAML pour un Service Kubernetes de type NodePort afin d'exposer votre application déployée et la rendre accessible depuis l'extérieur du cluster.

Pourquoi avons-nous besoin d'un Service ?

Dans l'étape précédente, nous avons créé un Déploiement qui gère nos Pods Nginx. Cependant, les Pods dans Kubernetes sont éphémères : ils peuvent être créés, détruits, remplacés, et leurs adresses IP changent constamment. Il est donc impossible de se fier directement à l'IP d'un Pod pour accéder à l'application de manière stable.

C'est là qu'intervient le Service Kubernetes. Un Service agit comme un point d'entrée stable et abstrait pour un ensemble de Pods fonctionnellement identiques. Il possède sa propre adresse IP (interne au cluster, appelée ClusterIP par défaut) et un nom DNS, qui ne changent pas tant que le Service existe. Le Service découvre automatiquement les Pods correspondants (grâce aux labels) et répartit le trafic entrant entre eux (load balancing).

Pour rendre notre application Nginx accessible depuis l'extérieur de notre cluster local (par exemple, depuis notre navigateur sur notre machine hôte), nous avons besoin d'un type de Service spécifique. Bien qu'il existe plusieurs types (ClusterIP, LoadBalancer, ExternalName), nous allons utiliser le type `NodePort` dans cet exercice, car il est simple à mettre en oeuvre dans un environnement de développement local comme Minikube ou Kind.

Structure d'un manifeste de Service et type NodePort

Comme pour le Déploiement, nous définissons un Service à l'aide d'un manifeste YAML. La structure de base est similaire : `apiVersion` (généralement `v1` pour les Services), `kind` (ici, `Service`), `metadata` (avec un `name` et éventuellement des `labels` pour le Service lui-même), et `spec`.

La section `spec` d'un Service est cruciale. Elle contient principalement :

  • `selector` : C'est la clé pour lier le Service aux Pods. Il contient des paires clé-valeur (comme `app: nginx`) qui doivent correspondre aux labels définis dans le `template.metadata.labels` du Déploiement. Le Service dirigera le trafic uniquement vers les Pods qui possèdent ces labels.
  • `type` : Définit comment le Service est exposé. Pour notre cas, nous spécifions `NodePort`. Cela signifie que Kubernetes allouera un port statique (par défaut dans la plage 30000-32767) sur chaque Noeud du cluster. Le Service sera accessible via l'adresse IP de n'importe quel Noeud sur ce port spécifique.
  • `ports` : Un tableau définissant les mappages de ports.

Le type `NodePort` est particulièrement utile pour les environnements locaux ou de test où l'on n'a pas forcément accès à un fournisseur de cloud pour provisionner un `LoadBalancer` externe. Il offre un moyen simple d'atteindre l'application depuis l'extérieur du cluster via l'IP du noeud (ou l'IP de la machine virtuelle Minikube/Kind) et le port alloué.

Configuration des ports dans un Service NodePort

La section `ports` dans `spec` nécessite une attention particulière. Chaque entrée dans ce tableau définit un mappage de port et contient généralement trois champs :

  • `port` : C'est le port sur lequel le Service lui-même écoute à l'intérieur du cluster (sur son adresse ClusterIP). D'autres Pods dans le cluster pourraient communiquer avec ce Service via ce port.
  • `targetPort` : C'est le port sur lequel l'application écoute à l'intérieur des conteneurs des Pods cibles. Le Service redirigera le trafic reçu sur son `port` vers le `targetPort` des Pods correspondants. Ce champ doit correspondre au `containerPort` que vous avez défini dans le manifeste du Déploiement.
  • `nodePort` : Ce champ est spécifique au type `NodePort` (et `LoadBalancer`). C'est le port statique (entre 30000 et 32767 par défaut) qui sera ouvert sur l'adresse IP de chaque Noeud du cluster. Si vous ne spécifiez pas de `nodePort`, Kubernetes en choisira un automatiquement dans la plage autorisée. Pour des raisons de prévisibilité dans cet exercice, nous pouvons en fixer un nous-mêmes (par exemple, 30080), à condition qu'il soit dans la plage valide et non déjà utilisé.

Il est essentiel que le `targetPort` du Service corresponde exactement au `containerPort` exposé par les conteneurs dans les Pods gérés par le Déploiement, sinon le trafic n'atteindra jamais l'application.

Exemple concret : un Service NodePort pour Nginx

Créons maintenant le fichier `nginx-service.yaml` pour exposer notre `nginx-deployment`. Nous allons utiliser le type `NodePort` et mapper le port externe du Noeud au port 80 du Service, qui lui-même cible le port 80 de nos conteneurs Nginx.

Voici le contenu du fichier `nginx-service.yaml` :

apiVersion: v1
kind: Service
metadata:
  name: nginx-service # Nom du service
spec:
  type: NodePort # Type de service pour exposition externe simple
  selector:
    app: nginx # Doit correspondre aux labels des Pods (template.metadata.labels du Déploiement)
  ports:
    - protocol: TCP
      port: 80 # Port sur lequel le Service écoute (interne au cluster)
      targetPort: 80 # Port sur lequel le conteneur écoute (doit correspondre au containerPort)
      nodePort: 30080 # Port statique ouvert sur chaque Noeud (dans la plage 30000-32767)

Dans cet exemple :

  • Le `selector` `app: nginx` garantit que ce Service ne dirigera le trafic que vers les Pods créés par notre `nginx-deployment` (qui ont ce label).
  • `type: NodePort` indique à Kubernetes d'ouvrir un port sur les Noeuds.
  • La section `ports` définit que le trafic arrivant sur le `nodePort` 30080 de n'importe quel Noeud sera envoyé au `port` 80 du Service. Le Service, à son tour, transférera ce trafic au `targetPort` 80 des Pods correspondants.

Avec ces deux fichiers YAML (`nginx-deployment.yaml` et `nginx-service.yaml`), nous avons maintenant une description complète de notre application simple et de la manière de l'exposer. La prochaine étape consistera à appliquer ces manifestes à notre cluster Kubernetes.