Aller au contenu
Conteneurs & Orchestration medium

kubectl expose, port-forward et proxy : accéder à vos applications Kubernetes

15 min de lecture

logo kubernetes

Votre application tourne dans le cluster, mais vous ne pouvez pas y accéder. Kubernetes isole les pods du réseau extérieur par défaut — c’est voulu. Pour y accéder, vous disposez de 3 commandes complémentaires : kubectl expose crée un Service permanent, kubectl port-forward ouvre un tunnel temporaire vers un pod ou un service, et kubectl proxy donne accès à l’API Kubernetes via un proxy local. Ce guide vous aide à choisir la bonne commande et à l’utiliser correctement.

  • Choisir entre expose, port-forward et proxy selon votre besoin
  • Créer un Service avec kubectl expose en choisissant le bon type (ClusterIP, NodePort, LoadBalancer)
  • Rediriger un port local vers un pod ou un service pour le dev/debug
  • Accéder à l’API Kubernetes et aux dashboards internes via kubectl proxy
  • Diagnostiquer les problèmes de connectivité et de routage

Avant tout, identifiez votre besoin :

BesoinCommandeDuréeCe que ça fait
Rendre une app accessible dans le clusterkubectl expose --type=ClusterIPPermanentCrée un Service avec une IP interne stable
Rendre une app accessible hors du clusterkubectl expose --type=NodePort ou LoadBalancerPermanentCrée un Service avec accès externe
Accéder à un pod/service depuis ma machine (dev, debug)kubectl port-forwardTemporaire (durée de la commande)Tunnel direct local → pod/service
Explorer l’API Kubernetes ou accéder à un dashboardkubectl proxyTemporaire (durée de la commande)Proxy HTTP local vers l’API server

kubectl expose crée un objet Service qui devient le point d’entrée réseau permanent vers votre application. Le Service utilise les labels de la ressource ciblée pour trouver les pods à router.

Fenêtre de terminal
kubectl expose <type> <nom> --port=<port-service> --target-port=<port-conteneur> --type=<type-service>
  • --port : le port exposé par le Service (celui que les clients utiliseront)
  • --target-port : le port sur lequel le conteneur écoute (défini dans le pod)
  • --type : le type de Service à créer

Le Service reçoit une IP interne accessible uniquement depuis l’intérieur du cluster. C’est le choix par défaut et le plus courant pour la communication entre microservices.

Fenêtre de terminal
kubectl expose deploy api-gateway --port=80 --target-port=8080
service/api-gateway exposed

Vérification :

Fenêtre de terminal
kubectl get svc api-gateway
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
api-gateway ClusterIP 10.96.45.123 <none> 80/TCP 5s

Le Service est accessible depuis n’importe quel pod du cluster via api-gateway.default.svc.cluster.local:80 ou simplement api-gateway:80 dans le même namespace.

La confusion entre --port et --target-port est l’erreur la plus fréquente. Voici comment les distinguer :

Client → [Service:port] → [Pod:targetPort]
FlagCe qu’il définitExemple
--portLe port du Service (côté client)80 — les autres pods appellent api-gateway:80
--target-portLe port du conteneur (côté application)8080 — votre app écoute sur 8080

Si --target-port est omis, il prend la même valeur que --port.

Par défaut, le Service prend le nom de la ressource exposée. Pour choisir un autre nom :

Fenêtre de terminal
kubectl expose deploy api-gateway --port=80 --target-port=8080 --name=api-public
  1. Vérifiez que le Service existe et a des endpoints

    Fenêtre de terminal
    kubectl get svc api-gateway
    kubectl get endpoints api-gateway

    Si ENDPOINTS est vide, le Service ne trouve aucun pod correspondant à son selector.

  2. Comparez les selectors du Service avec les labels des pods

    Fenêtre de terminal
    # Selector du Service
    kubectl get svc api-gateway -o jsonpath='{.spec.selector}'
    # Labels des pods
    kubectl get pods --show-labels

    Les labels des pods doivent correspondre exactement au selector du Service.

  3. Testez la connectivité depuis un pod du cluster

    Fenêtre de terminal
    kubectl run test-curl --rm -it --image=curlimages/curl -- \
    curl -s http://api-gateway:80

kubectl port-forward : tunnel temporaire pour le dev

Section intitulée « kubectl port-forward : tunnel temporaire pour le dev »

kubectl port-forward crée un tunnel direct entre votre machine locale et un pod ou un service dans le cluster. Le tunnel reste actif tant que la commande tourne — coupez-la et l’accès disparaît.

  • Débugger une application qui n’est pas exposée à l’extérieur
  • Accéder à un dashboard (Grafana, Prometheus, Kibana) sans créer de Service dédié
  • Tester une API avant de la rendre accessible
  • Accéder à une base de données depuis un outil local (DBeaver, pgAdmin…)
Fenêtre de terminal
kubectl port-forward <type>/<nom> <port-local>:<port-distant> [-n namespace]
Fenêtre de terminal
kubectl port-forward pod/api-server-7d4b8c 8080:8080 -n prod
Forwarding from 127.0.0.1:8080 -> 8080

Ouvrez http://localhost:8080 dans votre navigateur.

Cibler un Service plutôt qu’un pod permet au port-forward de suivre automatiquement si le pod redémarre :

Fenêtre de terminal
kubectl port-forward svc/grafana 3000:3000 -n monitoring
Fenêtre de terminal
kubectl port-forward pod/mon-app-7d4b8c 8080:8080 9090:9090 -n prod

Par défaut, le tunnel n’écoute que sur 127.0.0.1. Pour le rendre accessible depuis d’autres machines de votre réseau :

Fenêtre de terminal
kubectl port-forward --address 0.0.0.0 svc/grafana 3000:3000 -n monitoring

Si le port 8080 est déjà pris sur votre machine :

Fenêtre de terminal
kubectl port-forward svc/api-gateway :8080 -n prod

Le :8080 (sans port local) laisse le système attribuer un port libre. La commande affiche le port choisi.

Workflow typique : accéder à un dashboard Prometheus

Section intitulée « Workflow typique : accéder à un dashboard Prometheus »
  1. Identifiez le Service Prometheus

    Fenêtre de terminal
    kubectl get svc -n monitoring | grep prometheus
    prometheus-server ClusterIP 10.96.12.45 <none> 9090/TCP 30d
  2. Ouvrez le tunnel

    Fenêtre de terminal
    kubectl port-forward svc/prometheus-server 9090:9090 -n monitoring
  3. Accédez au dashboard

    Ouvrez http://localhost:9090 dans votre navigateur.

  4. Coupez le tunnel quand vous avez terminé avec Ctrl+C.

kubectl proxy démarre un serveur proxy HTTP local qui authentifie automatiquement vos requêtes vers l’API server Kubernetes. Vous pouvez ensuite explorer l’API REST avec curl, un navigateur, ou n’importe quel outil HTTP.

  • Explorer l’API Kubernetes (lister les ressources, vérifier les autorisations)
  • Accéder aux dashboards exposés via l’API server (Kubernetes Dashboard)
  • Développer un outil qui interagit avec l’API Kubernetes
Fenêtre de terminal
kubectl proxy [--port=<port>] [--address=<adresse>]
Fenêtre de terminal
kubectl proxy --port=8001
Starting to serve on 127.0.0.1:8001

Le proxy reste actif tant que la commande tourne. Arrêtez-le avec Ctrl+C.

Une fois le proxy démarré, l’API Kubernetes est accessible sans token ni certificat :

Fenêtre de terminal
# Lister les API disponibles
curl -s http://localhost:8001/api | python3 -m json.tool
# Lister les nœuds
curl -s http://localhost:8001/api/v1/nodes | python3 -m json.tool
# Lister les pods d'un namespace
curl -s http://localhost:8001/api/v1/namespaces/prod/pods | python3 -m json.tool
# Obtenir un pod spécifique
curl -s http://localhost:8001/api/v1/namespaces/prod/pods/api-server-7d4b8c | python3 -m json.tool

Le proxy expose aussi les Services de votre cluster via un chemin formaté :

http://localhost:8001/api/v1/namespaces/<namespace>/services/<service>[:<port>]/proxy/
Fenêtre de terminal
# Accéder au dashboard Kubernetes
curl http://localhost:8001/api/v1/namespaces/kubernetes-dashboard/services/https:kubernetes-dashboard:/proxy/
# Accéder à Grafana
curl http://localhost:8001/api/v1/namespaces/monitoring/services/grafana:3000/proxy/
Critèrekubectl proxykubectl port-forward
Ce qui est exposéL’API Kubernetes complèteUn pod ou service spécifique
ProtocoleHTTP uniquementTCP (n’importe quel protocole)
AuthAutomatique (le proxy s’authentifie)Automatique (kubectl s’authentifie)
UsageExplorer l’API, accéder aux dashboards via l’APIDebug/dev, accéder à une app spécifique
URL d’accèshttp://localhost:8001/api/v1/...http://localhost:<port-local>
TCP brut (BD, gRPC…)❌ Non (HTTP only)✅ Oui
EnvironnementType recommandéPourquoi
Communication entre microservicesClusterIPPas besoin d’accès externe, routage interne
Cluster de dev/test, accès depuis le réseau localNodePortSimple, pas de dépendance cloud
Production, accès publicLoadBalancerIP stable, health checks, intégration cloud
Production avec routing avancé (TLS, path-based)ClusterIP + IngressPlus flexible qu’un LB par Service
  • Utilisez svc/ plutôt que pod/ — le Service survit aux redémarrages de pods
  • Ne laissez pas tourner un port-forward oublié — il consomme une connexion API server
  • Pour un accès régulier, créez un Service ou un Ingress plutôt que de relancer un port-forward chaque jour
  • Documentez les commandes port-forward fréquentes dans le README du projet
  • Jamais --address 0.0.0.0 sur un réseau public (ni pour proxy, ni pour port-forward)
  • kubectl proxy = accès complet au cluster avec vos droits. Traitez-le comme un accès admin
  • En production, préférez un Ingress Controller avec TLS plutôt qu’un NodePort ou proxy
SymptômeCause probableSolution
error: no resources found (expose)La ressource n’existe pas ou mauvais namespaceVérifiez avec kubectl get <type> -n <ns>
service already exists (expose)Un Service du même nom existe déjàSupprimez-le avec kubectl delete svc <nom> ou choisissez un autre nom (--name)
Service créé mais pas d’endpointsLe selector du Service ne matche aucun podComparez kubectl get svc <nom> -o jsonpath='{.spec.selector}' avec les labels des pods
unable to listen on port (port-forward)Le port local est déjà utiliséChangez le port local : 9090:8080 ou utilisez :8080 pour un port aléatoire
error forwarding port (port-forward)Le pod n’est pas en état RunningVérifiez kubectl get pod <nom> -n <ns> — attendez qu’il soit prêt
Port-forward se coupe tout seulLe pod a redémarré ou a été suppriméCiblez le Service (svc/) plutôt que le pod. Relancez la commande
address already in use (proxy)Un autre processus utilise le port 8001Changez de port : kubectl proxy --port=8002
unauthorized (proxy)Kubeconfig invalide ou expiréVérifiez avec kubectl cluster-info. Renouvelez vos credentials si nécessaire
Proxy : accès au Service retourne 503Le Service n’a pas d’endpoints ou le pod n’est pas prêtVérifiez kubectl get endpoints <svc> -n <ns>
  • kubectl expose crée un Service permanent — choisissez le bon type : ClusterIP (interne), NodePort (dev/test), LoadBalancer (prod cloud).
  • kubectl port-forward crée un tunnel temporaire local → pod/service — parfait pour le dev et le debug, mais pas pour la production.
  • kubectl proxy expose l’API Kubernetes en HTTP local — puissant pour l’exploration, mais dangereux si exposé sur le réseau.
  • --port = port du Service (côté client), --target-port = port du conteneur (côté application).
  • Ciblez un Service (svc/) plutôt qu’un pod pour un port-forward résilient aux redémarrages.
  • En production, préférez un Ingress Controller avec TLS plutôt que des NodePort ou des proxy.
  • Pour un accès régulier, créez un Service ou un Ingress — ne compensez pas avec un port-forward quotidien.

Ce site vous est utile ?

Sachez que moins de 1% des lecteurs soutiennent ce site.

Je maintiens +700 guides gratuits, sans pub ni tracing. Aujourd'hui, ce site ne couvre même pas mes frais d'hébergement, d'électricité, de matériel, de logiciels, mais surtout de cafés.

Un soutien régulier, même symbolique, m'aide à garder ces ressources gratuites et à continuer de produire des guides de qualité. Merci pour votre appui.

Abonnez-vous et suivez mon actualité DevSecOps sur LinkedIn