Les services permettent d'exposer une application fonctionnant comme un ensemble de pods.
Ils fournissent un moyen d'accéder à l'application sans tenir compte des pods (IPs, nombre...).
Chaque service à un type. Le type de service va permettre de définir comment et ou le service va exposer l'application. Il existe 4 types de service :
Expose une application dans le cluster uniquement. A utiliser quand l'application doit communiquer uniquement avec d'autres pods.
Pour tester le service de type ClusterIP nous allons créer un déploiement nginx :
apiVersion: apps/v1
kind: Deployment
metadata:
name: deployment-svc-example
spec:
replicas: 3
selector:
matchLabels:
app: svc-example
template:
metadata:
labels:
app: svc-example
spec:
containers:
- name: nginx
image: nginx:1.19.1
ports:
- containerPort: 80
On va maintenant créer un service de type ClusterIP :
apiVersion: v1
kind: Service
metadata:
name: svc-clusterip
spec:
type: ClusterIP
selector:
app: svc-example # Sélectionne le label crée au-dessus
ports:
- protocol: TCP
port: 80 # Port d'écoute sur l'IP du service
targetPort: 80 # Port d'écoute des pods
On va maintenant lister les services ainsi que tous les endpoints des pods :
$ kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 13d
svc-clusterip ClusterIP 10.111.131.195 <none> 80/TCP 5s
$ kubectl get endpoints svc-clusterip
NAME ENDPOINTS AGE
svc-clusterip 192.168.126.54:80,192.168.126.55:80,192.168.194.121:80 15s
On peut donc faire un curl sur l'IP du service ou sur les IPs des endpoints.
En accédant depuis un autre pod :
apiVersion: v1
kind: Pod
metadata:
name: pod-svc-test
spec:
containers:
- name: busybox
image: radial/busyboxplus:curl
command: ['sh', '-c', 'while true; do sleep 10; done']
On peut exécuter un curl via le commande kubectl exec :
$ kubectl exec pod-svc-test -- curl svc-clusterip:80
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
...
<h1>Welcome to nginx!</h1>
NodePort va exposer l'application en dehors du réseau du cluster. Utiliser quand l'application doit être accessible par des utilisateurs/applications en dehors du cluster.
apiVersion: v1
kind: Service
metadata:
name: svc-nodeport
spec:
type: NodePort
selector:
app: svc-example # Sélectionne le label crée au-dessus
ports:
- protocol: TCP
port: 80 # Port d'écoute du service
targetPort: 80 # Port d'écoute du pod
nodePort: 30080 # Port d'écoute du cluster
# Si non assigné, assigne un port automatiquement
On va récupérer l'IP du service :
$ kubectl get svc svc-nodeport
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
svc-nodeport NodePort 10.107.27.120 <none> 80:30080/TCP 64s
On va donc pouvoir y accéder de différentes manières :
# Port 80 du service
$ curl 10.107.27.120
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
...
# Directement depuis l'IP publique du cluster
$ curl 3.10.198.53:30080
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
...
LoadBalancer expose aussi des applications en dehors du réseau du cluster mais ils utilisent le load balancer d'un cloud provider (AWS, GCP...). Ce service fonctionner uniquement avec les cloud providers compatible.
Le DNS de Kubernetes assigne automatiquement un nom DNS aux Services. Ce qui permet aux applications dans le cluster de joindre le service via son nom.
Le format du nom DNS est le suivant : nom-service.nom-namespace.svc.cluster.local
Ce format fonctionne avec les pods qui ne sont pas dans le même namespace. Si les pods sont dans le même namespace il suffit de contacter via le nom de service mon-service
comme fait au-dessus.
Ingress est un objet kubernetes qui permet de gérer l'accès externe vers un service dans le cluster.
L'ingress permet plus de fonctionnalités qu'un simple NodePort comme le SSL, un load-balancing avancé... :
Dans un premier temps, il faut installer un Ingress controller qui nous permettra d'utiliser Ingress.
Les ingress vont définir des règles de routages. Chaque règle va définir des propriétés qui permettent d'indiquer à quels requêtes celà s'applique.
Chaque règle défini un chemin (path) associé à un backend. Les requêtes qui matcheront ce chemin seront routés au backend associé.
Voici un exemple d'Ingress :
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-ingress
spec:
rules:
- http:
paths:
- path: /wiki
pathType: Prefix
backend:
service:
name: svc-clusterip
port:
number: 80
Une requête http://<IP Service>/wiki
sera redirigée vers le service svc-clusterip sur le port 80.
Une fois appliqué :
$ kubectl describe ingress my-ingress
Name: my-ingress
Namespace: default
Address:
Default backend: default-http-backend:80 (<error: endpoints "default-http-backend" not found>)
Rules:
Host Path Backends
---- ---- --------
*
/wiki svc-clusterip:80 (192.168.126.56:80,192.168.126.57:80,192.168.194.123:80)
Annotations: <none>
Events: <none>
On peut aussi rediriger vers le nom du port :
apiVersion: v1
kind: Service
metadata:
name: svc-clusterip
spec:
type: ClusterIP
selector:
app: svc-example
ports:
- name: http
protocol: TCP
port: 80
targetPort: 80
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-ingress
spec:
rules:
- http:
paths:
- path: /wiki
pathType: Prefix
backend:
service:
name: svc-clusterip
port:
name: http