Dans la deuxième partie de cet article, nous avons vu comment Kube Proxy pilotait la répartition de charge et la persistance d'IP pour les Pods qui assurent réellement le service grâce à l'objet "Service" de Kubernetes et les "Endpoints".
Dans cette troisième partie, nous allons détailler les types de services fournis par K8s.
Les Services K8s
Un service représente une abstraction de répartition de charge au sein d'un cluster.
Il possède un type qui définit son rôle et son fonctionnement. Ces types sont essentiellement:
- Cluster IP
- Node Port
- Load Balancer
Cluster IP
C'est le type de service par défaut de Kubernetes. Il assigne une adresse IP à partir d'un pool d'adresse réservé par le cluster.
Il représente la base de la plupart des autres types de services. Le type Cluster IP permet de faire communiquer des Pods entre eux. Son usage est seulement interne au cluster.
Créons deux pods dans un cluster:
kubectl run nginx --image nginx
kubectl run nginx2 --image nginx
Les pods sont créés sans services, nous allons créer un service pour chaque pod:
kubectl expose pods nginx --port 80
kubectl expose pods nginx2 --port 80
Lorsque l'on exécute la commande kubectl get svc, on peut voir que chacun des pods est relié à un service de type cluster IP possédant une IP du pool prévu à cet usage dans le cluster.
kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
nginx ClusterIP 10.43.193.150 <none> 80/TCP 13m
nginx2 ClusterIP 10.43.45.159 <none> 80/TCP 13m
On peut constater la communication entre les pods en se connectant sur l'un deux et en exécutant un Curl vers le second.
kubectl exec -it ngninx -- bash
root@nginx:/# curl nginx2
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
Voici l'implémentation d'un service de type Cluster IP via un manifest YAML :
apiVersion: v1
kind: Service
metadata:
name: nginx
spec:
type: ClusterIP
ports:
- targetPort: 80
port: 80
selector:
app: nginx
Dans la partie 'spec', il est possible de configurer un attribut .spec.clusterIP avec une addresse IP spécifique afin de réutiliser une entrée DNS d'un système plus ancien (l'IP choisie doit être comprise dans le range CIDR service-cluster-ip-range). S'il n'est pas configuré, une adresse sera attribuée automatiquement. Il est possible, enfin, de le configurer avec la valeur "None", dans ce cas le service ne se verra assigner aucune adresse IP et deviendra un type Headless.
Il est possible d'utiliser un service headless pour s'interfacer avec d'autres mécanismes de découverte de service, sans être lié à l'implémentation de Kubernetes.
NodePort
Ce type de service crée un port externe au cluster dans un range spécifique, réservé par le cluster (30000-32767 par défaut) qui est proxifié vers un port interne coté service. En gros c'est du NAT/PAT destination qui permet de rentrer dans le cluster à destination d'un port cible sur une application. Le port est configuré sur tous les Nodes d'un cluster avec le même numéro.
Avec ce type de service, il est possible de configurer son propre service de Load Balancing externe ou même d'exposer directement un port sur un ou plusieurs Nodes.
Reprenons notre exemple précédent avec nos deux pods nginx, avec les services de type Cluster IP, il est possible de faire communiquer les deux pods entre eux à l'intérieur du cluster Kubernetes. Comment faire pour accéder à l'un des serveurs nginx depuis l'extérieur du cluster ?
Créons un service de type Node Port avec le manifest suivant :
apiVersion: v1
kind: Service
metadata:
name: np-nginx
spec:
type: NodePort
ports:
- targetPort: 80
port: 80
nodePort: 30080
selector:
run: nginx
il est alors possible d'accéder au pods nginx depuis l'extérieur du cluster via l'adresse IP d'un Node du cluster associé au port affecté : 30080. Tous les Nodes du cluster possèdent le même port pour accéder au Pod. L'usage d'un Node Port impose un Load Balancer externe pour distribuer la charge de travail vers les nœuds du cluster.
Load Balancer
Lorsqu'un Cloud Service Provider est utilisé pour faire tourner des clusters Kubernetes, il est possible de s'appuyer sur les load balancers externes intégrés, proposés par la plateforme Cloud.
Dans ce cas il possible d'utiliser le type Load Balancer dans un service Kubernetes.
apiVersion: v1
kind: Service
metadata:
name: lb-nginx
spec:
selector:
run: nginx
ports:
- port: 80
targetPort: 80
type: LoadBalancer
Lorsque que l'on utilise un service de type Load Balancer sur une infrastructure On Premise, la sortie de la commande kubectl get svc donne:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
lb-nginx LoadBalancer 10.43.8.237 <pending> 80:31509/TCP 12s
On peut voir l'adresse du Cluster IP qui permet d'accéder au service au sein du Cluster, mais l'External-IP, qui permet d'accéder au service depuis l'extérieur du Cluster reste sur pending.
On voit ici que sans un Load Balancer externe configuré, ce type de service est inutilisable.
Dans les prochains articles nous nous intéresserons aux différentes solutions qui permettent d'utiliser des services de type Load Balancing dans un environnement On Premise.