Retour au blog

Proxies pour le contrôleur Ingress Kubernetes : configuration complète dans un cluster K8s avec des exemples de configurations

Nous expliquons comment configurer correctement un serveur proxy dans le contrôleur Ingress de Kubernetes - de la configuration de base de NGINX à la rotation des IP résidentes pour contourner les blocages.

📅10 août 2026
```html

Si votre cluster K8s effectue des requêtes externes — vers des API partenaires, des places de marché, des plateformes publicitaires — tôt ou tard, vous serez confronté à des blocages par IP. L'Ingress Controller gère le trafic entrant, mais pour les requêtes sortantes via des pods, un schéma distinct avec un proxy est nécessaire. Dans cet article, nous examinons comment le configurer correctement : du choix du type de proxy aux configurations YAML spécifiques pour NGINX Ingress et Traefik.

Pourquoi un proxy dans Kubernetes : scénarios réels

Kubernetes est un orchestrateur, et la plupart des articles à son sujet parlent du trafic entrant : comment configurer l'Ingress, comment délivrer un certificat TLS, comment router les requêtes vers les services. Mais il y a un autre aspect : le trafic sortant des pods. C'est ici que surgissent les problèmes de blocages, de géo-restrictions et de limites par IP.

Examinons des tâches spécifiques où un proxy dans un cluster K8s devient une nécessité :

  • Parsing et surveillance des prix. Votre cluster exécute un CronJob toutes les 15 minutes et collecte des données de Wildberries, Ozon, Amazon. Sans rotation des IP, après 2–3 heures, vous recevrez un ban sur toute la plage IP de votre fournisseur de cloud.
  • Travail avec des API publicitaires. Facebook Marketing API, TikTok Ads API, Google Ads API — tous suivent la source des requêtes. Si des dizaines de pods envoient des requêtes depuis une seule IP de datacenter, c'est un déclencheur pour un blocage automatique.
  • Tests de géolocalisation. Votre service doit afficher un contenu différent pour les utilisateurs de différents pays. Via un proxy, les pods peuvent simuler des requêtes des régions nécessaires pour les tests automatiques.
  • Contourner les restrictions d'entreprise. Dans certaines infrastructures, tout le trafic sortant doit passer par un proxy d'entreprise — c'est une exigence de conformité.
  • Travail avec des API partenaires avec liste blanche d'IP. Lorsque le partenaire autorise les requêtes uniquement depuis des IP spécifiques, et que votre cluster se met à l'échelle et change d'adresses — un proxy avec des IP statiques résout le problème.

Il est important de comprendre la séparation architecturale : L'Ingress Controller gère le trafic entrant (des utilisateurs vers vos services), tandis qu'un proxy pour les requêtes sortantes est une tâche distincte. Néanmoins, ils sont liés : la configuration du proxy est souvent définie au niveau du même Ingress Controller ou via des annotations qu'il lit.

💡 Distinction clé

Dans cet article, nous examinons deux scénarios : (1) configurer l'Ingress Controller comme un proxy inverse pour des serveurs upstream externes, et (2) router le trafic sortant des pods via un serveur proxy externe. Les deux scénarios se rencontrent en production.

Quel type de proxy choisir pour un cluster K8s

Le choix du type de proxy influence directement la durée pendant laquelle votre cluster pourra fonctionner sans blocages. Les IP de datacenter sont les moins chères, mais elles sont faciles à identifier et à bloquer. Les IP résidentes et mobiles sont plus chères, mais beaucoup plus fiables pour les tâches où l'imitation d'un utilisateur réel est importante.

Type de proxy Vitesse Risque de blocage Meilleur scénario dans K8s
Datacenter Élevée Élevé APIs internes, conformité d'entreprise, intégrations partenaires avec liste blanche d'IP
Résidentiel Moyenne Faible Parsing de places de marché, travail avec des APIs publicitaires, tests géographiques
Mobile Moyenne Minimale Facebook Ads API, TikTok API, tâches à forte charge avec risque de ban

Pour la plupart des tâches dans un cluster K8s, liées au parsing ou au travail avec des plateformes publicitaires, le choix optimal est des proxies résidentiels avec rotation. Ils fournissent de vraies IP d'utilisateurs domestiques, et les algorithmes de protection des sites perçoivent ces requêtes comme un trafic de navigateur ordinaire.

En termes de protocole pour K8s, le plus universel est le proxy HTTP/HTTPS — il est pris en charge par tous les clients HTTP populaires dans n'importe quel langage de programmation via les variables d'environnement standard HTTP_PROXY et HTTPS_PROXY. SOCKS5 n'est nécessaire que pour des protocoles non standards ou lorsque vous devez proxyfier autre chose qu'HTTP.

Configuration du proxy via NGINX Ingress Controller

NGINX Ingress Controller est l'option la plus répandue dans K8s. Examinons deux scénarios : configurer NGINX comme un proxy inverse vers un upstream externe via un serveur proxy, et configurer globalement le proxy sortant pour le contrôleur lui-même.

Annotations pour proxyfier les requêtes vers l'upstream

NGINX Ingress prend en charge les annotations pour gérer le comportement du proxy. Si vous avez besoin que l'Ingress transmette des requêtes à un service externe via un proxy intermédiaire, utilisez un ConfigMap avec une configuration personnalisée :

apiVersion: v1
kind: ConfigMap
metadata:
  name: nginx-ingress-controller
  namespace: ingress-nginx
data:
  # Proxy HTTP global pour les requêtes sortantes NGINX
  http-snippet: |
    proxy_connect_timeout 10s;
    proxy_read_timeout 30s;
    proxy_send_timeout 30s;
  # Configuration de l'upstream via un proxy
  use-proxy-protocol: "false"
  proxy-real-ip-cidr: "0.0.0.0/0"

Ressource Ingress avec annotations pour le proxy

Pour une ressource Ingress distincte, vous pouvez définir les paramètres du proxy via des annotations. Cela est utile lorsque différents services nécessitent des délais d'attente et des configurations différents :

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: my-service-ingress
  namespace: production
  annotations:
    kubernetes.io/ingress.class: "nginx"
    # Délais d'attente du proxy
    nginx.ingress.kubernetes.io/proxy-connect-timeout: "10"
    nginx.ingress.kubernetes.io/proxy-read-timeout: "60"
    nginx.ingress.kubernetes.io/proxy-send-timeout: "60"
    # Taille du buffer
    nginx.ingress.kubernetes.io/proxy-buffer-size: "16k"
    nginx.ingress.kubernetes.io/proxy-buffers-number: "8"
    # Transmission de la vraie IP du client
    nginx.ingress.kubernetes.io/use-forwarded-headers: "true"
    nginx.ingress.kubernetes.io/forwarded-for-header: "X-Forwarded-For"
spec:
  rules:
  - host: myapp.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: my-service
            port:
              number: 80

Configuration d'un proxy externe pour les requêtes sortantes du pod NGINX

Si le NGINX Ingress Controller lui-même doit effectuer des requêtes sortantes via un proxy externe (par exemple, pour vérifier la santé des points de terminaison externes), vous devez définir des variables d'environnement dans le déploiement du contrôleur :

apiVersion: apps/v1
kind: Deployment
metadata:
  name: ingress-nginx-controller
  namespace: ingress-nginx
spec:
  template:
    spec:
      containers:
      - name: controller
        image: registry.k8s.io/ingress-nginx/controller:v1.9.4
        env:
        - name: HTTP_PROXY
          valueFrom:
            secretKeyRef:
              name: proxy-credentials
              key: http-proxy-url
        - name: HTTPS_PROXY
          valueFrom:
            secretKeyRef:
              name: proxy-credentials
              key: https-proxy-url
        - name: NO_PROXY
          value: "localhost,127.0.0.1,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16,.cluster.local"

Notez la variable NO_PROXY — elle est critique. Sans elle, tout le trafic intra-cluster passera également par le proxy externe, ce qui rompra l'interaction entre les services. Dans NO_PROXY, incluez toujours les plages RFC-1918 et le suffixe .cluster.local.

Configuration du proxy dans Traefik Ingress Controller

Traefik est une alternative populaire à NGINX Ingress, surtout en combinaison avec Helm et dans des clusters gérés (k3s, Docker Swarm, Nomad). Traefik a son propre système de configuration via CRD (Custom Resource Definitions) et des configurations statiques/dynamiques.

Configuration statique de Traefik avec proxy

apiVersion: v1
kind: ConfigMap
metadata:
  name: traefik-config
  namespace: traefik
data:
  traefik.yaml: |
    # Configuration statique de Traefik
    entryPoints:
      web:
        address: ":80"
      websecure:
        address: ":443"
    
    # Paramètres pour fonctionner derrière un proxy
    serversTransport:
      insecureSkipVerify: false
      maxIdleConnsPerHost: 200
      dialTimeout: 10s
      responseHeaderTimeout: 30s
    
    # Journalisation pour le diagnostic du proxy
    log:
      level: INFO
    
    accessLog:
      fields:
        headers:
          defaultMode: keep
          names:
            X-Forwarded-For: keep
            X-Real-IP: keep

Middleware pour ajouter des en-têtes de proxy

Dans Traefik, vous pouvez créer un Middleware qui ajoutera ou modifiera des en-têtes lors de la transmission des requêtes. Cela est utile pour transmettre correctement la vraie IP du client à travers la chaîne de proxies :

apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
  name: proxy-headers
  namespace: production
spec:
  headers:
    customRequestHeaders:
      X-Forwarded-Proto: "https"
    # Supprimez les en-têtes qui pourraient révéler l'infrastructure
    customResponseHeaders:
      X-Powered-By: ""
      Server: ""
---
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: my-app-route
  namespace: production
spec:
  entryPoints:
    - websecure
  routes:
  - match: Host(`myapp.example.com`)
    kind: Rule
    middlewares:
    - name: proxy-headers
    services:
    - name: my-service
      port: 80

Variables d'environnement pour le déploiement Traefik

De même que pour NGINX, pour Traefik, définissez des variables d'environnement via les valeurs Helm ou directement dans le déploiement. Lors de l'utilisation du chart Helm, cela se fait via values.yaml :

# values.yaml pour le chart Helm de Traefik
deployment:
  enabled: true
  kind: Deployment
  
env:
  - name: HTTP_PROXY
    valueFrom:
      secretKeyRef:
        name: proxy-credentials
        key: http-proxy-url
  - name: HTTPS_PROXY
    valueFrom:
      secretKeyRef:
        name: proxy-credentials
        key: https-proxy-url
  - name: NO_PROXY
    value: "localhost,127.0.0.1,10.96.0.0/12,10.244.0.0/16,.cluster.local,.svc"

Proxy via des variables d'environnement dans les pods

La manière la plus universelle de configurer un proxy sortant pour n'importe quel pod est via des variables d'environnement standard. Cette méthode fonctionne indépendamment du langage de programmation et du framework : Python requests, Go net/http, Node.js axios, Java HttpClient — tous lisent HTTP_PROXY et HTTPS_PROXY automatiquement.

Option 1 : Directement dans la spécification du pod

apiVersion: v1
kind: Pod
metadata:
  name: scraper-pod
  namespace: production
spec:
  containers:
  - name: scraper
    image: mycompany/scraper:latest
    env:
    - name: HTTP_PROXY
      value: "http://username:[email protected]:8080"
    - name: HTTPS_PROXY
      value: "http://username:[email protected]:8080"
    - name: NO_PROXY
      value: "localhost,127.0.0.1,10.0.0.0/8,.cluster.local"
    resources:
      requests:
        memory: "128Mi"
        cpu: "100m"
      limits:
        memory: "256Mi"
        cpu: "500m"

⚠️ Ne stockez pas les informations d'identification en clair !

L'exemple ci-dessus est montré pour des raisons de clarté. En production, les informations d'identification du proxy doivent toujours être stockées dans Kubernetes Secret et transmises via secretKeyRef. Plus de détails dans la section sur les Secrets ci-dessous.

Option 2 : Via ConfigMap pour plusieurs pods

Si plusieurs déploiements utilisent le proxy, il est pratique de déplacer les paramètres dans un ConfigMap et de les connecter via envFrom :

apiVersion: v1
kind: ConfigMap
metadata:
  name: proxy-config
  namespace: production
data:
  NO_PROXY: "localhost,127.0.0.1,10.0.0.0/8,172.16.0.0/12,.cluster.local,.svc.cluster.local"
  PROXY_TIMEOUT: "30"
  PROXY_MAX_RETRIES: "3"
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: price-monitor
  namespace: production
spec:
  replicas: 5
  selector:
    matchLabels:
      app: price-monitor
  template:
    metadata:
      labels:
        app: price-monitor
    spec:
      containers:
      - name: monitor
        image: mycompany/price-monitor:v2.1
        envFrom:
        - configMapRef:
            name: proxy-config
        - secretRef:
            name: proxy-credentials
        ports:
        - containerPort: 8080

Option 3 : Mutating WebhookAdmissionController

Pour les clusters d'entreprise, où tous les pods doivent utiliser un proxy, vous pouvez configurer un webhook d'admission mutateur qui ajoute automatiquement des variables d'environnement proxy à tous les pods créés. Cette solution est utilisée dans des infrastructures d'entreprise, où la conformité exige que tout le trafic sortant passe par un proxy d'entreprise. La mise en œuvre d'un tel webhook dépasse le cadre de cet article, mais il est bon d'en connaître l'existence.

Rotation des IP et gestion du pool de proxies dans K8s

Un proxy statique est bon pour la conformité d'entreprise, mais mauvais pour les tâches où il faut éviter les blocages. Si 50 de vos pods envoient des requêtes via la même IP, cette IP sera rapidement bloquée. La solution est la rotation des proxies.

Schéma avec Proxy Sidecar

Un des modèles consiste à exécuter un agent proxy en tant que conteneur sidecar à côté de l'application principale. Le sidecar reçoit des requêtes sur localhost:8080 et les redirige via un pool rotatif de proxies externes :

apiVersion: apps/v1
kind: Deployment
metadata:
  name: scraper-with-proxy-sidecar
  namespace: production
spec:
  replicas: 10
  selector:
    matchLabels:
      app: scraper
  template:
    metadata:
      labels:
        app: scraper
    spec:
      containers:
      # Application principale
      - name: scraper
        image: mycompany/scraper:latest
        env:
        - name: HTTP_PROXY
          value: "http://localhost:8080"
        - name: HTTPS_PROXY
          value: "http://localhost:8080"
        - name: NO_PROXY
          value: "localhost,127.0.0.1,.cluster.local"
      
      # Sidecar : agent proxy local avec rotation
      - name: proxy-rotator
        image: mycompany/proxy-rotator:latest
        ports:
        - containerPort: 8080
        env:
        - name: PROXY_LIST_URL
          valueFrom:
            secretKeyRef:
              name: proxy-credentials
              key: api-endpoint
        - name: ROTATION_INTERVAL
          value: "60"  # rotation toutes les 60 secondes
        resources:
          requests:
            memory: "64Mi"
            cpu: "50m"
          limits:
            memory: "128Mi"
            cpu: "200m"

Schéma avec un service Proxy central

Une approche alternative consiste à avoir un service Proxy unique à l'intérieur du cluster, auquel tous les pods se connectent. C'est plus facile à gérer : il suffit de mettre à jour un Secret avec les informations d'identification du proxy, et tous les pods commenceront automatiquement à utiliser les nouvelles données.

apiVersion: v1
kind: Service
metadata:
  name: proxy-gateway
  namespace: proxy-system
spec:
  selector:
    app: proxy-gateway
  ports:
  - name: http
    port: 8080
    targetPort: 8080
  - name: socks5
    port: 1080
    targetPort: 1080
  type: ClusterIP
---
# Les pods utilisent le proxy via le DNS interne
# HTTP_PROXY=http://proxy-gateway.proxy-system.svc.cluster.local:8080

Pour les tâches où l'anonymat est critique et le risque de blocages doit être minimisé (par exemple, le parsing de places de marché ou le travail avec des APIs publicitaires), nous recommandons d'utiliser des proxies résidentiels avec rotation — ils fournissent de vraies IP d'utilisateurs domestiques, ce qui rend le trafic de votre cluster indiscernable d'un trafic de navigateur ordinaire.

Stockage des informations d'identification du proxy dans Kubernetes Secrets

Le stockage sécurisé des informations d'identification est une exigence obligatoire pour tout cluster de production. Ne jamais insérer le login/mot de passe du proxy directement dans les manifests YAML qui sont stockés dans un dépôt Git.

Création d'un Secret pour le proxy

# Création via kubectl (les valeurs sont automatiquement encodées en base64)
kubectl create secret generic proxy-credentials \
  --namespace=production \
  --from-literal=http-proxy-url='http://user:[email protected]:8080' \
  --from-literal=https-proxy-url='http://user:[email protected]:8080' \
  --from-literal=socks5-proxy-url='socks5://user:[email protected]:1080'

# Vérification du Secret créé
kubectl get secret proxy-credentials -n production -o yaml

Manifest YAML du Secret

apiVersion: v1
kind: Secret
metadata:
  name: proxy-credentials
  namespace: production
  labels:
    app: proxy-config
    managed-by: ops-team
type: Opaque
# Les valeurs sont encodées en base64
# echo -n 'http://user:pass@proxy:8080' | base64
stringData:
  # stringData permet de spécifier des valeurs en clair
  # Kubernetes les encode automatiquement en base64
  http-proxy-url: "http://user:[email protected]:8080"
  https-proxy-url: "http://user:[email protected]:8080"
  proxy-host: "gate.proxycove.com"
  proxy-port: "8080"
  proxy-username: "user"
  proxy-password: "password"

Utilisation du Secret dans le déploiement

apiVersion: apps/v1
kind: Deployment
metadata:
  name: api-worker
  namespace: production
spec:
  replicas: 3
  selector:
    matchLabels:
      app: api-worker
  template:
    metadata:
      labels:
        app: api-worker
    spec:
      containers:
      - name: worker
        image: mycompany/api-worker:latest
        env:
        - name: HTTP_PROXY
          valueFrom:
            secretKeyRef:
              name: proxy-credentials
              key: http-proxy-url
        - name: HTTPS_PROXY
          valueFrom:
            secretKeyRef:
              name: proxy-credentials
              key: https-proxy-url
        - name: NO_PROXY
          value: "localhost,127.0.0.1,10.0.0.0/8,.cluster.local"
        # Pour les applications qui lisent l'hôte/le port séparément
        - name: PROXY_HOST
          valueFrom:
            secretKeyRef:
              name: proxy-credentials
              key: proxy-host
        - name: PROXY_PORT
          valueFrom:
            secretKeyRef:
              name: proxy-credentials
              key: proxy-port

Intégration avec des stockages secrets externes

Dans un environnement d'entreprise, il est recommandé d'utiliser External Secrets Operator pour synchroniser les secrets depuis HashiCorp Vault, AWS Secrets Manager ou Azure Key Vault. Cela permet de mettre à jour automatiquement les informations d'identification du proxy sans intervention manuelle et sans redémarrer les pods :

apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
  name: proxy-credentials-ext
  namespace: production
spec:
  refreshInterval: 1h
  secretStoreRef:
    name: vault-backend
    kind: ClusterSecretStore
  target:
    name: proxy-credentials
    creationPolicy: Owner
  data:
  - secretKey: http-proxy-url
    remoteRef:
      key: secret/proxy/proxycove
      property: http_proxy_url
  - secretKey: https-proxy-url
    remoteRef:
      key: secret/proxy/proxycove
      property: https_proxy_url

Diagnostic et erreurs courantes lors de la configuration du proxy dans K8s

Même avec une configuration correcte, des problèmes peuvent survenir. Examinons les plus fréquents et les moyens de les diagnostiquer.

Problème 1 : Le trafic intra-cluster passe par le proxy

Symptôme : les pods ne se voient plus, la résolution DNS à l'intérieur du cluster échoue, les services ne répondent pas. La cause — la variable NO_PROXY n'est pas configurée.

La valeur minimale requise pour NO_PROXY pour un cluster K8s standard :

NO_PROXY=localhost,127.0.0.1,::1,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16,.cluster.local,.svc,.svc.cluster.local,kubernetes.default.svc

Problème 2 : Le proxy ne s'applique pas à un pod spécifique

Diagnostic : entrez dans le pod et vérifiez les variables d'environnement :

# Vérification des variables d'environnement dans le pod
kubectl exec -it <pod-name> -n production -- env | grep -i proxy

# Test de connexion via le proxy depuis le pod
kubectl exec -it <pod-name> -n production -- curl -v --proxy http://proxy:8080 https://httpbin.org/ip

# Vérification que le Secret est monté correctement
kubectl exec -it <pod-name> -n production -- env | grep PROXY

Problème 3 : Erreurs TLS lors de l'utilisation de proxies HTTPS

Si le proxy utilise un certificat auto-signé ou un CA d'entreprise, les applications recevront des erreurs de vérification TLS. La solution consiste à ajouter le certificat CA du proxy aux approuvés :

# Création d'un ConfigMap avec le certificat CA
kubectl create configmap proxy-ca-cert \
  --from-file=proxy-ca.crt=./proxy-ca.crt \
  -n production

# Montage dans le pod
spec:
  containers:
  - name: app
    volumeMounts:
    - name: proxy-ca
      mountPath: /etc/ssl/certs/proxy-ca.crt
      subPath: proxy-ca.crt
  volumes:
  - name: proxy-ca
    configMap:
      name: proxy-ca-cert

Problème 4 : Requêtes lentes via le proxy

Si les requêtes via le proxy sont significativement plus lentes que les directes — vérifiez :

  • Résolution DNS : assurez-vous que les requêtes DNS ne passent pas par le proxy (ajoutez-les à NO_PROXY)
  • Connexions Keep-alive : configurez le pool de connexions vers le serveur proxy
  • Localisation géographique : le serveur proxy doit être physiquement proche de la ressource cible
  • Type de proxy : pour des tâches à haute vitesse, envisagez des proxies de datacenter — ils offrent une latence minimale

Commandes utiles pour le diagnostic

# Vérifier les logs de l'Ingress Controller
kubectl logs -n ingress-nginx -l app.kubernetes.io/name=ingress-nginx --tail=100

# Vérifier les événements du pod
kubectl describe pod <pod-name> -n production

# Tester la connexion proxy depuis le pod
kubectl run test-proxy --image=curlimages/curl --rm -it --restart=Never -- \
  curl -x http://user:pass@proxy:8080 -v https://httpbin.org/ip

# Vérifier que le Secret existe et contient les clés nécessaires
kubectl get secret proxy-credentials -n production -o jsonpath='{.data}' | python3 -c "
import sys, json, base64
data = json.load(sys.stdin)
for k, v in data.items():
    print(f'{k}: {base64.b64decode(v).decode()[:20]}...')
"

Conclusion et recommandations

La configuration du proxy dans Kubernetes n'est pas une tâche ponctuelle, mais fait partie de l'architecture de sécurité réseau du cluster. Résumons :

  • Pour NGINX Ingress Controller — utilisez des annotations pour configurer les paramètres du proxy au niveau des ressources Ingress individuelles, et des variables d'environnement dans le déploiement pour les paramètres globaux du trafic sortant.
  • Pour Traefik — combinez la configuration statique via ConfigMap avec Middleware pour gérer les en-têtes.
  • Pour les pods — les variables standard HTTP_PROXY / HTTPS_PROXY via Secrets — c'est l'approche la plus universelle et sécurisée.
  • Configurez toujours NO_PROXY — sinon, le trafic intra-cluster sera rompu.
  • Ne stockez jamais les informations d'identification du proxy en clair dans les manifests ou dans Git.
  • Pour la production — utilisez External Secrets Operator pour la rotation automatique des informations d'identification.

Si votre cluster K8s effectue des tâches où la stabilité des IP et le risque minimal de blocages sont critiques — parsing, travail avec des APIs publicitaires, tests géographiques — nous recommandons d'utiliser des proxies résidentiels. Ils fournissent de vraies IP d'utilisateurs domestiques, que les algorithmes de protection perçoivent comme un trafic légitime. Pour les tâches avec des exigences élevées en matière de vitesse et un risque minimal de blocages de la part des plateformes mobiles, les proxies mobiles sont idéaux — ils fonctionnent via de véritables réseaux 4G/5G d'opérateurs.

```