Exposing Services in Kubernetes

Soutenez HackTricks et bénéficiez d'avantages !

Il existe différentes façons d'exposer des services dans Kubernetes afin que les points de terminaison internes et externes puissent y accéder. Cette configuration Kubernetes est assez critique car l'administrateur pourrait donner accès à des attaquants à des services auxquels ils ne devraient pas avoir accès.

Énumération automatique

Avant de commencer à énumérer les façons dont K8s offre pour exposer des services au public, sachez que si vous pouvez lister les espaces de noms, les services et les entrées, vous pouvez trouver tout ce qui est exposé au public avec :

kubectl get namespace -o custom-columns='NAME:.metadata.name' | grep -v NAME | while IFS='' read -r ns; do
    echo "Namespace: $ns"
    kubectl get service -n "$ns"
    kubectl get ingress -n "$ns"
    echo "=============================================="
    echo ""
    echo ""
done | grep -v "ClusterIP"
# Supprimez le dernier '| grep -v "ClusterIP"' pour voir également le type ClusterIP

ClusterIP

Un service ClusterIP est le service Kubernetes par défaut. Il vous donne un service à l'intérieur de votre cluster que d'autres applications à l'intérieur de votre cluster peuvent accéder. Il n'y a pas d'accès externe.

Cependant, cela peut être accessible en utilisant le proxy Kubernetes :

kubectl proxy --port=8080

Maintenant, vous pouvez naviguer dans l'API Kubernetes pour accéder aux services en utilisant ce schéma :

http://localhost:8080/api/v1/proxy/namespaces/<NAMESPACE>/services/<SERVICE-NAME>:<PORT-NAME>/

Par exemple, vous pourriez utiliser l'URL suivante :

http://localhost:8080/api/v1/proxy/namespaces/default/services/my-internal-service:http/

pour accéder à ce service :

apiVersion: v1
kind: Service
metadata:  
  name: my-internal-service
spec:
  selector:    
    app: my-app
  type: ClusterIP
  ports:  
  - name: http
    port: 80
    targetPort: 80
    protocol: TCP

Cette méthode nécessite que vous exécutiez kubectl en tant qu'utilisateur authentifié.

NodePort

NodePort ouvre un port spécifique sur tous les nœuds (les VM), et tout trafic envoyé à ce port est redirigé vers le service. C'est une option vraiment mauvaise en général.

Un exemple de spécification NodePort :

apiVersion: v1
kind: Service
metadata:  
  name: my-nodeport-service
spec:
  selector:    
    app: my-app
  type: NodePort
  ports:  
  - name: http
    port: 80
    targetPort: 80
    nodePort: 30036
    protocol: TCP

Si vous ne spécifiez pas le nodePort dans le yaml (c'est le port qui sera ouvert), un port dans la plage 30000-32767 sera utilisé.

LoadBalancer

Expose le service de manière externe en utilisant le load balancer du fournisseur de cloud. Sur GKE, cela fera tourner un Network Load Balancer qui vous donnera une seule adresse IP qui redirigera tout le trafic vers votre service.

Vous devez payer pour un LoadBalancer par service exposé, ce qui peut devenir cher.

ExternalName

Les services de type ExternalName cartographient un service sur un nom DNS, et non sur un sélecteur typique tel que my-service ou cassandra. Vous spécifiez ces services avec le paramètre spec.externalName.

Cette définition de service, par exemple, cartographie le service my-service dans l'espace de noms prod sur my.database.example.com :

apiVersion: v1
kind: Service
metadata:
  name: my-service
  namespace: prod
spec:
  type: ExternalName
  externalName: my.database.example.com

Lorsque vous recherchez l'hôte my-service.prod.svc.cluster.local, le service DNS de cluster renvoie un enregistrement CNAME avec la valeur my.database.example.com. L'accès à my-service fonctionne de la même manière que pour les autres services, mais avec la différence cruciale que la redirection se produit au niveau DNS plutôt que par proxy ou transfert.

Adresses IP externes

Le trafic qui entre dans le cluster avec l'adresse IP externe (en tant qu'adresse IP de destination), sur le port du service, sera routé vers l'un des points de terminaison du service. Les externalIPs ne sont pas gérés par Kubernetes et relèvent de la responsabilité de l'administrateur de cluster.

Dans la spécification du service, externalIPs peuvent être spécifiés avec n'importe quel des ServiceTypes. Dans l'exemple ci-dessous, "my-service" peut être accessible par les clients sur "80.11.12.10:80" (externalIP:port)

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

Ingress

Contrairement à tous les exemples ci-dessus, Ingress n'est PAS un type de service. Au lieu de cela, il se trouve devant plusieurs services et agit comme un "routeur intelligent" ou un point d'entrée dans votre cluster.

Vous pouvez faire beaucoup de choses différentes avec un Ingress, et il existe de nombreux types de contrôleurs Ingress qui ont des capacités différentes.

Le contrôleur d'entrée par défaut de GKE fera tourner un HTTP(S) Load Balancer pour vous. Cela vous permet

Dernière mise à jour