Torna al blog

Proxy per Kubernetes Ingress Controller: guida completa alla configurazione in un cluster K8s con esempi di configurazione

Analizziamo come configurare correttamente un server proxy nel Kubernetes Ingress Controller, dalla configurazione di base di NGINX alla rotazione degli IP residenziali per aggirare i blocchi.

📅10 agosto 2026
```html

Se il tuo cluster K8s effettua richieste esterne — a API di partner, marketplace, piattaforme pubblicitarie — prima o poi ti troverai di fronte a blocchi per IP. L'Ingress Controller gestisce il traffico in entrata, ma per le richieste in uscita attraverso i pod è necessaria una configurazione separata con un proxy. In questo articolo analizziamo come configurarlo correttamente: dalla scelta del tipo di proxy a configurazioni YAML specifiche per NGINX Ingress e Traefik.

Perché un proxy in Kubernetes: scenari reali

Kubernetes è un orchestratore, e la maggior parte degli articoli su di esso parla del traffico in entrata: come configurare l'Ingress, come emettere un certificato TLS, come instradare le richieste ai servizi. Ma c'è un altro lato: il traffico in uscita dai pod. È proprio qui che sorgono problemi con i blocchi, le restrizioni geografiche e i limiti per IP.

Consideriamo compiti specifici in cui un proxy nel cluster K8s diventa una necessità:

  • Parsing e monitoraggio dei prezzi. Il tuo cluster esegue un CronJob ogni 15 minuti e raccoglie dati da Wildberries, Ozon, Amazon. Senza rotazione degli IP, dopo 2-3 ore riceverai un ban su tutto l'intervallo di IP del tuo fornitore di cloud.
  • Interazione con API pubblicitarie. Facebook Marketing API, TikTok Ads API, Google Ads API — tutte monitorano la fonte delle richieste. Se decine di pod inviano richieste da un solo IP del data center, questo è un trigger per il blocco automatico.
  • Testing geolocalizzato. Il tuo servizio deve mostrare contenuti diversi per utenti di paesi diversi. Tramite un proxy, i pod possono simulare richieste dalle regioni desiderate per i test automatici.
  • Elusione delle restrizioni aziendali. In alcune infrastrutture, tutto il traffico in uscita deve passare attraverso un proxy aziendale — questo è un requisito di conformità.
  • Interazione con API partner con whitelist di IP. Quando un partner consente richieste solo da IP specifici, e il tuo cluster si espande e cambia indirizzi — un proxy con IP statici risolve il problema.

È importante comprendere la separazione architettonica: L'Ingress Controller gestisce il traffico in entrata (dagli utenti ai tuoi servizi), mentre il proxy per le richieste in uscita è un compito separato. Tuttavia, sono collegati: la configurazione del proxy è spesso impostata a livello dello stesso Ingress Controller o tramite annotazioni che legge.

💡 Chiarimento chiave

In questo articolo analizziamo due scenari: (1) configurazione dell'Ingress Controller come reverse proxy per server upstream esterni, e (2) instradamento del traffico in uscita dai pod attraverso un server proxy esterno. Entrambi gli scenari si incontrano in produzione.

Quale tipo di proxy scegliere per il cluster K8s

La scelta del tipo di proxy influisce direttamente su quanto a lungo il tuo cluster potrà funzionare senza blocchi. Gli IP dei data center sono i più economici, ma sono facili da identificare e bloccare. Gli IP residenziali e mobili sono più costosi, ma significativamente più affidabili per compiti in cui è importante simulare un utente reale.

Tipo di proxy Velocità Rischio di blocco Miglior scenario in K8s
Data center Alta Alta API interne, conformità aziendale, integrazioni partner con whitelist di IP
Residenziali Media Basso Parsing di marketplace, interazione con API pubblicitarie, geotesting
Mobili Media Minimo Facebook Ads API, TikTok API, compiti ad alta intensità con rischio di ban

Per la maggior parte dei compiti nel cluster K8s, legati al parsing o all'interazione con piattaforme pubblicitarie, la scelta ottimale è proxy residenziali con rotazione. Forniscono IP reali di utenti domestici, e gli algoritmi di protezione dei siti percepiscono tali richieste come traffico normale da browser.

Dal punto di vista del protocollo, per K8s il più universale è proxy HTTP/HTTPS — supportato da tutti i client HTTP popolari in qualsiasi linguaggio di programmazione tramite le variabili d'ambiente standard HTTP_PROXY e HTTPS_PROXY. SOCKS5 è necessario solo per protocolli non standard o quando è richiesto di proxyare non solo HTTP.

Configurazione del proxy tramite NGINX Ingress Controller

NGINX Ingress Controller è l'opzione più comune in K8s. Consideriamo due scenari: configurazione di NGINX come reverse proxy per un upstream esterno tramite un server proxy, e configurazione globale del proxy in uscita per lo stesso controller.

Annotazioni per il proxying delle richieste verso upstream

NGINX Ingress supporta annotazioni per gestire il comportamento del proxy. Se hai bisogno che l'Ingress inoltri le richieste a un servizio esterno tramite un proxy intermedio, utilizza un ConfigMap con una configurazione personalizzata:

apiVersion: v1
kind: ConfigMap
metadata:
  name: nginx-ingress-controller
  namespace: ingress-nginx
data:
  # Proxy HTTP globale per le richieste in uscita di NGINX
  http-snippet: |
    proxy_connect_timeout 10s;
    proxy_read_timeout 30s;
    proxy_send_timeout 30s;
  # Configurazione upstream tramite proxy
  use-proxy-protocol: "false"
  proxy-real-ip-cidr: "0.0.0.0/0"

Risorsa Ingress con annotazioni per il proxy

Per una singola risorsa Ingress, puoi impostare i parametri del proxy tramite annotazioni. Questo è utile quando diversi servizi richiedono timeout e configurazioni diverse:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: my-service-ingress
  namespace: production
  annotations:
    kubernetes.io/ingress.class: "nginx"
    # Timeout del 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"
    # Dimensione del buffer
    nginx.ingress.kubernetes.io/proxy-buffer-size: "16k"
    nginx.ingress.kubernetes.io/proxy-buffers-number: "8"
    # Trasmissione del reale IP del 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

Configurazione di un proxy esterno per le richieste in uscita del pod NGINX

Se lo stesso NGINX Ingress Controller deve effettuare richieste in uscita tramite un proxy esterno (ad esempio, per il controllo dello stato degli endpoint esterni), è necessario impostare le variabili d'ambiente nel Deployment del controller:

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"

Fai attenzione alla variabile NO_PROXY — è critica. Senza di essa, tutto il traffico intra-cluster passerà anche attraverso il proxy esterno, il che romperà l'interazione tra i servizi. In NO_PROXY includi sempre i range RFC-1918 e il suffisso .cluster.local.

Configurazione del proxy in Traefik Ingress Controller

Traefik è un'alternativa popolare a NGINX Ingress, specialmente in combinazione con Helm e in cluster gestiti (k3s, Docker Swarm, Nomad). Traefik ha il suo sistema di configurazione tramite CRD (Custom Resource Definitions) e configurazioni statiche/dinamiche.

Configurazione statica di Traefik con proxy

apiVersion: v1
kind: ConfigMap
metadata:
  name: traefik-config
  namespace: traefik
data:
  traefik.yaml: |
    # Configurazione statica di Traefik
    entryPoints:
      web:
        address: ":80"
      websecure:
        address: ":443"
    
    # Impostazioni per funzionare dietro un proxy
    serversTransport:
      insecureSkipVerify: false
      maxIdleConnsPerHost: 200
      dialTimeout: 10s
      responseHeaderTimeout: 30s
    
    # Logging per la diagnostica del proxy
    log:
      level: INFO
    
    accessLog:
      fields:
        headers:
          defaultMode: keep
          names:
            X-Forwarded-For: keep
            X-Real-IP: keep

Middleware per aggiungere intestazioni del proxy

In Traefik puoi creare un Middleware che aggiunge o modifica le intestazioni durante l'inoltro delle richieste. Questo è utile per la corretta trasmissione del reale IP del client attraverso la catena di proxy:

apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
  name: proxy-headers
  namespace: production
spec:
  headers:
    customRequestHeaders:
      X-Forwarded-Proto: "https"
    # Rimuoviamo intestazioni che potrebbero rivelare l'infrastruttura
    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

Variabili d'ambiente per il Deployment di Traefik

Analogamente a NGINX, per Traefik impostiamo le variabili d'ambiente tramite i valori di Helm o direttamente nel Deployment. Quando si utilizza il chart di Helm, ciò avviene tramite values.yaml:

# values.yaml per il chart Helm di 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 tramite variabili d'ambiente nei pod

Il modo più universale per configurare un proxy in uscita per qualsiasi pod è tramite variabili d'ambiente standard. Questo metodo funziona indipendentemente dal linguaggio di programmazione e dal framework: Python requests, Go net/http, Node.js axios, Java HttpClient — tutti leggono automaticamente HTTP_PROXY e HTTPS_PROXY.

Opzione 1: Direttamente nello Spec del 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"

⚠️ Non memorizzare le credenziali in chiaro!

L'esempio sopra è mostrato a scopo dimostrativo. In produzione, le credenziali del proxy devono sempre essere memorizzate in Kubernetes Secret e passate tramite secretKeyRef. Maggiori dettagli nella sezione sui Secrets qui sotto.

Opzione 2: Tramite ConfigMap per più pod

Se più Deployment utilizzano il proxy, è conveniente estrarre le impostazioni in un ConfigMap e collegarlo tramite 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

Opzione 3: Mutating WebhookAdmissionController

Per cluster aziendali, dove tutti i pod devono utilizzare un proxy, è possibile configurare un mutating admission webhook che aggiunge automaticamente le variabili d'ambiente del proxy a tutti i pod creati. Questa soluzione è utilizzata in infrastrutture enterprise, dove la conformità richiede che tutto il traffico in uscita passi attraverso un proxy aziendale. L'implementazione di tale webhook va oltre lo scopo di questo articolo, ma vale la pena sapere della sua esistenza.

Rotazione IP e gestione del pool di proxy in K8s

Un proxy statico è buono per la conformità aziendale, ma cattivo per compiti in cui è necessario evitare blocchi. Se 50 dei tuoi pod inviano richieste tramite lo stesso IP, questo IP verrà bloccato molto rapidamente. La soluzione è la rotazione del proxy.

Schema con Proxy Sidecar

Uno dei pattern è eseguire un agente proxy come container sidecar accanto all'applicazione principale. Il sidecar riceve le richieste su localhost:8080 e le inoltra tramite un pool rotante di proxy esterni:

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:
      # Applicazione 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: agente proxy locale con rotazione
      - 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"  # rotazione ogni 60 secondi
        resources:
          requests:
            memory: "64Mi"
            cpu: "50m"
          limits:
            memory: "128Mi"
            cpu: "200m"

Schema con Proxy Service centrale

Un approccio alternativo è un unico Proxy Service all'interno del cluster, a cui si rivolgono tutti i pod. Questo è più semplice da gestire: è sufficiente aggiornare un Secret con le credenziali del proxy, e tutti i pod inizieranno automaticamente a utilizzare i nuovi dati.

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
---
# I pod utilizzano il proxy tramite DNS interno
# HTTP_PROXY=http://proxy-gateway.proxy-system.svc.cluster.local:8080

Per compiti in cui l'anonimato e il rischio minimo di blocchi sono critici (ad esempio, parsing di marketplace o interazione con API pubblicitarie), raccomandiamo di utilizzare proxy residenziali con rotazione — forniscono IP reali di utenti domestici, rendendo il traffico dal tuo cluster indistinguibile da quello normale da browser.

Archiviazione delle credenziali del proxy in Kubernetes Secrets

La memorizzazione sicura delle credenziali è un requisito obbligatorio per qualsiasi cluster di produzione. Non inserire mai nome utente/password del proxy direttamente nei manifest YAML che vengono memorizzati nel repository Git.

Creazione di un Secret per il proxy

# Creazione tramite kubectl (i valori vengono codificati in base64 automaticamente)
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'

# Verifica del Secret creato
kubectl get secret proxy-credentials -n production -o yaml

Manifest YAML del Secret

apiVersion: v1
kind: Secret
metadata:
  name: proxy-credentials
  namespace: production
  labels:
    app: proxy-config
    managed-by: ops-team
type: Opaque
# I valori sono codificati in base64
# echo -n 'http://user:pass@proxy:8080' | base64
stringData:
  # stringData consente di specificare valori in chiaro
  # Kubernetes li codifica automaticamente in 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"

Utilizzo del Secret nel Deployment

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"
        # Per applicazioni che leggono host/port separatamente
        - name: PROXY_HOST
          valueFrom:
            secretKeyRef:
              name: proxy-credentials
              key: proxy-host
        - name: PROXY_PORT
          valueFrom:
            secretKeyRef:
              name: proxy-credentials
              key: proxy-port

Integrazione con archivi di segreti esterni

In un ambiente enterprise, si consiglia di utilizzare l'External Secrets Operator per sincronizzare i segreti da HashiCorp Vault, AWS Secrets Manager o Azure Key Vault. Questo consente di aggiornare automaticamente le credenziali del proxy senza intervento manuale e senza riavviare i pod:

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

Diagnostica e errori comuni nella configurazione del proxy in K8s

Anche con una configurazione corretta, possono sorgere problemi. Analizziamo i più comuni e i modi per diagnosticarli.

Problema 1: Il traffico intra-cluster passa attraverso il proxy

Sintomo: i pod smettono di vedersi, la risoluzione DNS all'interno del cluster si rompe, i servizi non rispondono. La causa è che la variabile NO_PROXY non è impostata.

Il valore minimo necessario per NO_PROXY per 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

Problema 2: Il proxy non si applica a un pod specifico

Diagnostica: accedi al pod e controlla le variabili d'ambiente:

# Controlla le variabili d'ambiente nel pod
kubectl exec -it <pod-name> -n production -- env | grep -i proxy

# Test di connessione tramite proxy dal pod
kubectl exec -it <pod-name> -n production -- curl -v --proxy http://proxy:8080 https://httpbin.org/ip

# Verifica che il Secret sia montato correttamente
kubectl exec -it <pod-name> -n production -- env | grep PROXY

Problema 3: Errori TLS quando si utilizza un proxy HTTPS

Se il proxy utilizza un certificato autofirmato o un CA aziendale, le applicazioni riceveranno errori di verifica TLS. La soluzione è aggiungere il certificato CA del proxy ai trusted:

# Creazione di un ConfigMap con il certificato CA
kubectl create configmap proxy-ca-cert \
  --from-file=proxy-ca.crt=./proxy-ca.crt \
  -n production

# Montaggio nel 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

Problema 4: Richieste lente tramite proxy

Se le richieste tramite proxy sono significativamente più lente delle dirette — controlla:

  • Risoluzione DNS: assicurati che le richieste DNS non passino attraverso il proxy (aggiungi a NO_PROXY)
  • Connessioni Keep-alive: configura un pool di connessioni al server proxy
  • Posizione geografica: il server proxy deve essere fisicamente vicino alla risorsa target
  • Tipo di proxy: per compiti ad alta velocità considera proxy dei data center — forniscono la minima latenza

Comandi utili per la diagnostica

# Controlla i log dell'Ingress Controller
kubectl logs -n ingress-nginx -l app.kubernetes.io/name=ingress-nginx --tail=100

# Controlla gli eventi del pod
kubectl describe pod <pod-name> -n production

# Test di connessione proxy dal pod
kubectl run test-proxy --image=curlimages/curl --rm -it --restart=Never -- \
  curl -x http://user:pass@proxy:8080 -v https://httpbin.org/ip

# Controlla che il Secret esista e contenga le chiavi necessarie
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]}...')
"

Conclusione e raccomandazioni

La configurazione del proxy in Kubernetes non è un compito una tantum, ma parte dell'architettura della sicurezza di rete del cluster. Riassumiamo:

  • Per NGINX Ingress Controller — utilizza annotazioni per configurare i parametri del proxy a livello di singole risorse Ingress, e variabili d'ambiente nel Deployment per le impostazioni globali del traffico in uscita.
  • Per Traefik — combina la configurazione statica tramite ConfigMap con Middleware per gestire le intestazioni.
  • Per i pod — le variabili standard HTTP_PROXY / HTTPS_PROXY tramite Secrets — l'approccio più universale e sicuro.
  • Imposta sempre NO_PROXY — altrimenti il traffico intra-cluster si romperà.
  • Non memorizzare mai le credenziali del proxy in chiaro nei manifest o in Git.
  • Per la produzione — utilizza l'External Secrets Operator per la rotazione automatica delle credenziali.

Se il tuo cluster K8s esegue compiti in cui la stabilità dell'IP e il rischio minimo di blocchi sono critici — parsing, interazione con API pubblicitarie, geotesting — raccomandiamo di utilizzare proxy residenziali. Forniscono IP reali di utenti domestici, che gli algoritmi di protezione percepiscono come traffico legittimo. Per compiti con elevate esigenze di velocità e rischi minimi di blocchi da parte delle piattaforme mobili, sono ottimi proxy mobili — funzionano attraverso reti 4G/5G reali degli operatori.

```