Services

Un service est un moyen de découvrir les pods qui réalise une tâche particulière. Attention à ne pas confondre avec Ingress qui est un composant gérant les connexions externes de type HTTP.

Les connexions HTTP peuvent aussi être géré par des services, mais il est recommander d'utiliser Ingress.

apiVersion: v1
kind: Service
metadata:
  name: my-service
spec:
  selector:
    app: MyApp
  ports:
    - protocol: TCP
      port: 80
      targetPort: 9376

Ce service s'appelle my-service, et pointe sur tous les pods avec l'étiquette app=MyApp sur le port 9376.

Kubernetes assigne une IP (appelé le ClusterIP) au service. Cette IP est utilisée comme IP proxy pour load-balancer les requêtes entre les différents pods pointés par le sélecteur.

Les services peuvent être découverts par différents moyens.

Chaque pods créé dans le même espace de nom qu'un service va avoir des variables défini sous les formes suivantes :

Variable Description Exemple
{svc_name}_SERVICE_HOST ClusterIP (IP du service) 10.0.0.11
{svc_name}_SERVICE_PORT Port du serice 6379
{svc_name}_PORT Adresse du service tcp:10.0.0.11:6379 | | {svc_name}_PORT_{svc_port}_{protocol} | Adresse du service | tcp:10.0.0.11:6379
{svc_name}_PORT_{svc_port}_{protocol}_PROTO Protocole du port tcp
{svc_name}_PORT_{svc_port}_{protocol}_PORT Port 6379
{svc_name}_PORT_{svc_port}_{protocol}_ADDR Adresse IP du service 10.0.0.11

Chaque service va avoir un enregistrement A sur le DNS du système sous la forme {svc-name}.{namespace}.svc.cluster.local. À savoir que dans un namespace, il y a un DNS search avec le nom du domaine. Les adresses suivantes sont donc valides :

  • {svc-name}
  • {svc-name}.{namespace}
  • {svc-name}.{namespace}.svc.cluster.local

Cette méthode ne permet pas de connaitre le port du service.

Les services ont aussi un enregistrement SRV. Cet enregistrement permet aussi la découverte du port. L'enregistrement SRV est sous la forme _{port-name}._{port-protocol}.{svc-name}.svc.cluster.local.

Le selector permet de découvrir la liste des pods vers lesquelles doit pointer le service. Si un sélecteur est défini, un objet endpoints sera automatiquement créé dynamiquement pour pointer vers ces pods.

Il est aussi possible de faire des services sans sélecteur. Dans ce cas particulier, les endpoints doivent être créé manuellement sur le service.

Le champs spec.type est le type de service. Le type de service par défaut est ClusterIP.

ClusterIP

Type de service par défaut. Le service se comportera comme un LoadBalancer entre les différentes cibles. Le service aura une IP virtuelle appelé le ClusterIP (IP du loadbalancer) sur laquelle attaqueront les programmes ayant besoin du service.

Ce type de service est accessible uniquement à l'intérieur du Cluster.

NodePort

Les services de type node port ouvre le port nodePort sur les noeuds du cluster sur lesquelles s'exécute les pods.

LoadBalancer

Les services LoadBalancer sont semblables aux services de type NodePort, mais utilisent un loadbalancer externe pour créer les routes vers les bons noeuds.

ExternalName

Ce type de service est permet de faire référence à un autre service. Il peut être dans le même namespace, un autre namespace mais aussi peut être un service externe au cluster.

Le champs spec.clusterIP est rempli par défaut par une IP disponible dans le système. Il est possible de forcer cette IP.

Dans le cas où il n'y a pas besoin de load-balancing, le champs spec.ClusterIP peut être défini à None. Il s'agit alors d'un service dit Headless, sans proxy en amont.

S'il y a un sélecteur, les enregistrements DNS du service renverront directement l'IP du pod. S'il n'y en a pas, les enregistrement pointeront vers l'IP défini dans l'objet endpoints ayant le même nom que le service.

Si le service est de type externalName, l'enregistrement DNS sera transformé en CNAME.

Le champs spec.ports est un tableau d'objets avec les éléments suivants :

Variable Valeur par défaut Description
.spec.ports[*].port Port du service (accès à l'interieur du cluster.
.spec.ports[*].name None Nom du port.
.spec.ports[*].protocol TCP Type de protocole.
.spec.ports[*].targetPort = port Port du pod vers lequel rediriger les connexions.
.spec.ports[*].nodePort None Port publique ouvert sur le noeud du pod.

Attention, le nodePort doit être compris entre 30000 et 32767.

Les protocoles supportés sont :

  • TCP (par défaut)
  • UDP
  • HTTP
  • Proxy protocol
  • SCTP (nécessite une activation)

Le service écoute sur le spec.ports[*].port et redirige le trafic vers le spec.ports[].targetPort. Par défaut, le targetPort est le même que le port.

Champs requis pour les services de type externalName.

C'est le FQDN vers lequel doit pointer le service.

Liste d'adresse IP de destination sur lesquelles le service sera accessible de l'extérieur.

Le champs spec.sessionAffinity est par défaut None.

Il s'agit de savoir si le loadBalancer du service doit toujours rediriger un client donné vers le même pod. Les valeurs possibles sont les suivantes :

Valeur Description
None Pas de persistance des sessions. Toute connexion est renvoyé vers un pod aléatoire.
ClientIP Une IP source sera toujours envoyé vers un même pod.

Si le champs est défini à ClientIP, un client est redirigé par défaut vers un seul pod donné durant 3h. Ce temps d'expiration de la session peut être modifié par le paramètre service.spec.sessionAffinityConfig.clientIP.timeoutSeconds.