Cette page décrit les services Kubernetes et leur utilisation dans Google Kubernetes Engine (GKE). Il existe différents types de services, que vous pouvez utiliser pour regrouper un ensemble de points de terminaison de pod en une seule ressource. Pour apprendre à créer un service, consultez la page Exposer des applications à l'aide de services.
Qu'est-ce qu'un service Kubernetes ?
Dans l'idée, un service consiste à regrouper un ensemble de points de terminaison de pod dans une seule ressource. Vous pouvez configurer différents types d'accès à ce regroupement. Par défaut, vous obtenez une adresse IP de cluster stable que les clients du cluster peuvent utiliser afin de contacter les pods du service. Un client envoie une requête à l'adresse IP stable, et la requête est acheminée vers l'un des pods du service.
Un service identifie ses pods membres à l'aide d'un sélecteur. Pour qu'un pod soit membre du service, il doit comporter tous les libellés spécifiés dans le sélecteur. Un libellé est une paire clé/valeur arbitraire associée à un objet.
Le fichier manifeste du service ci-dessous a un sélecteur qui spécifie deux libellés. Le champ selector
indique que tous les pods comportant les libellés app: metrics
et department:engineering
sont membres de ce service.
apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
selector:
app: metrics
department: engineering
ports:
...
Pourquoi utiliser un service Kubernetes ?
Dans un cluster Kubernetes, chaque pod dispose d'une adresse IP interne. Cependant, les pods d'un déploiement vont et viennent et leurs adresses IP changent. Il n'est donc pas logique d'utiliser directement les adresses IP des pods. Avec un service, vous obtenez une adresse IP stable qui dure toute la vie du service, même lorsque les adresses IP des pods membres changent.
Un service fournit également un équilibrage de charge. Les clients appellent une seule adresse IP stable, et leurs requêtes sont équilibrées entre les pods membres du service.
Types de services Kubernetes
Il existe cinq types de services :
ClusterIP (valeur par défaut) : les clients internes envoient des requêtes à une adresse IP interne stable.
NodePort : les clients envoient des requêtes à l'adresse IP d'un nœud sur une ou plusieurs valeurs
nodePort
spécifiées par le service.LoadBalancer : les clients envoient des requêtes à l'adresse IP d'un équilibreur de charge réseau.
ExternalName : les clients internes utilisent le nom DNS d'un service comme alias pour un nom DNS externe.
Sans adresse IP de cluster : un service sans adresse IP de cluster vous permet de regrouper des pods sans disposer d'une adresse IP stable.
Le type NodePort
est une extension du type ClusterIP
. Ainsi, un service de type NodePort
a une adresse IP de cluster.
Le type LoadBalancer
est une extension du type NodePort
. Ainsi, un service de type LoadBalancer
a une adresse IP de cluster ainsi qu'une ou plusieurs valeurs nodePort
.
Services de type ClusterIP
Lorsque vous créez un service de type ClusterIP
, Kubernetes crée une adresse IP stable accessible à partir des nœuds du cluster.
Voici le fichier manifeste d'un service de type ClusterIP :
apiVersion: v1
kind: Service
metadata:
name: my-cip-service
spec:
selector:
app: metrics
department: sales
type: ClusterIP
ports:
- protocol: TCP
port: 80
targetPort: 8080
Vous pouvez créer le service à l'aide de la commande kubectl apply -f [MANIFEST_FILE]
. Après avoir créé le service, vous pouvez utiliser kubectl get service
pour afficher l'adresse IP stable :
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S)
my-cip-service ClusterIP 10.11.247.213 none 80/TCP
Les clients du cluster appellent le service à l'aide de l'adresse IP du cluster et du port TCP spécifié dans le champ port
du fichier manifeste du service. La requête est transmise à l'un des pods membres du port TCP spécifié dans le champ targetPort
. Dans l'exemple précédent, un client appelle le service à l'adresse 10.11.247.213
sur le port TCP 80. La requête est transmise à l'un des pods membres sur le port TCP 8080. Le pod membre doit disposer d'un conteneur qui écoute sur le port TCP 8080. Si aucun conteneur n'écoute sur le port 8080, les clients verront un message du type "Échec de la connexion" ou "Ce site est inaccessible".
Services de type NodePort
Lorsque vous créez un service de type NodePort
, Kubernetes vous attribue une valeur nodePort
. Le service est ensuite accessible en utilisant l'adresse IP de n'importe quel nœud ainsi que la valeur nodePort
.
Voici le fichier manifeste d'un service de type NodePort
:
apiVersion: v1
kind: Service
metadata:
name: my-np-service
spec:
selector:
app: products
department: sales
type: NodePort
ports:
- protocol: TCP
port: 80
targetPort: 8080
Après avoir créé le service, vous pouvez consulter sa spécification et voir la valeur nodePort
à l'aide de la commande kubectl get service -o yaml
.
spec:
clusterIP: 10.11.254.114
externalTrafficPolicy: Cluster
ports:
- nodePort: 32675
port: 80
protocol: TCP
targetPort: 8080
Les clients externes appellent le service en utilisant l'adresse IP externe d'un nœud ainsi que le port TCP spécifié par nodePort
. La demande est transmise à l'un des pods membres du port TCP spécifié dans le champ targetPort
.
Par exemple, supposons que l'adresse IP externe de l'un des nœuds du cluster soit 203.0.113.2
. Ensuite, pour l'exemple précédent, le client externe appelle le service à l'adresse 203.0.113.2
sur le port TCP 32675. La requête est transmise à l'un des pods membres sur le port TCP 8080. Le pod membre doit avoir un conteneur à l'écoute sur le port TCP 8080.
Le type de service NodePort
est une extension du type de service ClusterIP
. Les clients internes ont donc deux moyens d'appeler le service :
- Utiliser
clusterIP
etport
- Utiliser l'adresse IP d'un nœud et
nodePort
Pour certaines configurations de cluster, l'équilibreur de charge d'application externe utilise un service de type NodePort
.
Un équilibreur de charge d'application externe est un serveur proxy qui, en tant que tel, diffère fondamentalement de l'équilibreur de charge réseau externe à stratégie directe décrit dans cette rubrique sous Services de type LoadBalancer.
Services de type LoadBalancer
Pour en savoir plus sur les services de type LoadBalancer, consultez la page Concepts de services LoadBalancer.
Services de type ExternalName
Un service de type ExternalName
fournit un alias interne à un nom DNS externe. Les clients internes effectuent des requêtes à l'aide du nom DNS interne, qui sont redirigées vers le nom externe.
Voici le fichier manifeste d'un service de type ExternalName
:
apiVersion: v1
kind: Service
metadata:
name: my-xn-service
spec:
type: ExternalName
externalName: example.com
Lorsque vous créez un service, Kubernetes crée un nom DNS qui peut permettre aux clients internes d'appeler le service. Pour l'exemple précédent, le nom DNS est my-xn-service.default.svc.cluster.local. Lorsqu'un client interne envoie une requête à my-xn-service.default.svc.cluster.local, celle-ci est redirigée vers example.com.
Le type de service ExternalName
est fondamentalement différent des autres types de service. En fait, un service de type ExternalName
ne correspond pas à la définition du service donnée au début de cette page. Un service de type ExternalName
n'est pas associé à un ensemble de pods et n'a pas d'adresse IP stable. À la place, un service de type ExternalName
est le mappage entre un nom DNS interne et un nom DNS externe.
Service sans adresse IP de cluster
Un service sans adresse IP de cluster est un type de service Kubernetes qui n'alloue pas d'adresse IP de cluster. À la place, un service sans adresse IP de cluster utilise le DNS pour exposer les adresses IP des pods associés au service. Cela vous permet de vous connecter directement aux pods au lieu de passer par un proxy.
Les services sans adresse IP de cluster sont utiles dans de nombreux cas de figure. En voici quelques exemples :
Équilibrage de charge entre les pods : vous pouvez utiliser des services sans adresse IP de cluster pour équilibrer la charge sur les pods. Pour ce faire, créez un service avec un sélecteur correspondant aux pods pour lesquels vous souhaitez équilibrer la charge. Le service répartit alors le trafic de manière uniforme entre tous les pods correspondant au sélecteur.
Détection de services : vous pouvez utiliser un service sans adresse IP de cluster pour mettre en œuvre la détection de services. Pour ce faire, créez un service avec un nom et un sélecteur. L'enregistrement DNS du service sans adresse IP de cluster contient toutes les adresses IP des pods derrière le service qui correspondent au sélecteur. Les clients peuvent utiliser ces enregistrements DNS pour trouver les adresses IP des pods associés au service.
Accès direct aux pods : les clients peuvent se connecter directement aux pods associés à un service sans adresse IP de cluster, ce qui peut être utile pour les services nécessitant un accès direct aux pods sous-jacents, tels que les équilibreurs de charge et les serveurs DNS.
Flexibilité : les services sans adresse IP de cluster peuvent servir à créer diverses topologies, telles que des équilibreurs de charge, des serveurs DNS et des bases de données distribuées.
Si vous avez des exigences réseau particulières pour vos charges de travail qui ne peuvent pas être résolues en utilisant des services sans adresse IP de cluster avec des sélecteurs, il est également possible d'utiliser des services sans adresse IP de cluster sans sélecteurs. Les services sans adresse IP de cluster sont un outil utile pour accéder aux services qui ne se trouvent pas dans le cluster Kubernetes, car le plan de contrôle ne crée pas d'objets EndpointSlice. Consultez la section Service sans sélecteurs pour en savoir plus.
L'exemple suivant est un fichier manifeste pour un service sans adresse IP de cluster :
apiVersion: v1
kind: Service
metadata:
name: nginx
spec:
clusterIP: None
selector:
app: nginx
ports:
- name: http
port: 80
targetPort: 80
Une fois que vous avez créé un service sans adresse IP de cluster, vous pouvez rechercher les adresses IP des pods associés au service en interrogeant le DNS. Par exemple, la commande suivante répertorie les adresses IP des pods associés au service nginx :
dig +short nginx.default.svc.cluster.local
Autre exemple utilisant l'extension des requêtes Kubernetes :
dig +short +search nginx
Vous pouvez créer un service sans adresse IP de cluster avec une seule commande, et les services sans adresse IP de cluster sont faciles à mettre à jour et à faire évoluer.
kubectl create service clusterip my-svc --clusterip="None" --dry-run=client -o yaml > [file.yaml]
Abstraction de service
Un service est une abstraction dans le sens où il ne s'agit pas d'un processus à l'écoute d'une interface réseau. Une partie de l'abstraction est appliquée dans les règles iptables des nœuds du cluster. Selon le type de service, d'autres parties de l'abstraction sont mises en œuvre par un équilibreur de charge réseau externe à stratégie directe ou un équilibreur de charge d'application externe.
Ports de services arbitraires
La valeur du champ port
dans un fichier manifeste de service est arbitraire. La valeur de targetPort
, quant à elle, ne l'est pas. Chaque pod membre doit avoir un conteneur à l'écoute sur targetPort
.
Voici un service, de type LoadBalancer
, dont le champ port
a une valeur de 50000 :
apiVersion: v1
kind: Service
metadata:
name: my-ap-service
spec:
clusterIP: 10.11.241.93
externalTrafficPolicy: Cluster
ports:
- nodePort: 30641
port: 50000
protocol: TCP
targetPort: 8080
selector:
app: parts
department: engineering
sessionAffinity: None
type: LoadBalancer
status:
loadBalancer:
ingress:
- ip: 203.0.113.200
Un client appelle le service à l'adresse 203.0.113.200
sur le port TCP 50000. La requête est transmise à l'un des pods membres sur le port TCP 8080.
Plusieurs ports
Le champ ports
d'un service est un tableau d'objets ServicePort. L'objet ServicePort comporte les champs suivants :
name
protocol
port
targetPort
nodePort
Si vous avez plusieurs objets ServicePort, chacun d'eux doit avoir un nom unique.
Voici un service, de type LoadBalancer
, qui comporte deux objets ServicePort
:
apiVersion: v1
kind: Service
metadata:
name: my-tp-service
spec:
clusterIP: 10.11.242.196
externalTrafficPolicy: Cluster
ports:
- name: my-first-service-port
nodePort: 31233
port: 60000
protocol: TCP
targetPort: 50000
- name: my-second-service-port
nodePort: 31081
port: 60001
protocol: TCP
targetPort: 8080
selector:
app: tests
department: engineering
sessionAffinity: None
type: LoadBalancer
status:
loadBalancer:
ingress:
- ip: 203.0.113.201
Dans l'exemple précédent, si un client appelle le service à l'adresse 203.0.113.201
sur le port TCP 60000, la requête est transmise à un pod membre sur le port TCP 50000. Cependant, si un client appelle le service à l'adresse 203.0.113.201
sur le port TCP 60001, la requête est transmise à un pod membre sur le port TCP 8080.
Chaque pod membre doit avoir un conteneur d'écoute sur le port TCP 50000 et un conteneur d'écoute sur le port TCP 8080. Il peut s'agir d'un conteneur unique avec deux threads ou de deux conteneurs s'exécutant dans le même pod.
Points de terminaison d'un service
Lorsque vous créez un service, Kubernetes crée un objet Endpoints avec un nom identique à celui de votre service. Kubernetes utilise l'objet Endpoints dans le but de savoir quels pods sont membres du service.
Services à pile unique et à double pile
Vous pouvez créer un service IPv6 de type ClusterIP
ou NodePort
.
GKE est compatible avec les services à deux piles de type LoadBalancer
pendant le preview, qui ne bénéficie d'aucun contrat de niveau de service ni d'aucune assistance technique.
Pour chacun de ces types de service, vous pouvez définir les champs ipFamilies
et ipFamilyPolicy
en tant que service IPv4, IPv6 ou à double pile.
Étapes suivantes
- En savoir plus sur les services Kubernetes
- Exposer des applications à l'aide de services
- En savoir plus sur les objets StatefulSet
- En savoir plus sur Ingress