Назад к блогу

Прокси для Kubernetes Ingress Controller: полная настройка в K8s кластере с примерами конфигов

Разбираем, как правильно настроить прокси-сервер в Kubernetes Ingress Controller — от базовой конфигурации NGINX до ротации резидентных IP для обхода блокировок.

📅10 августа 2026 г.

Если ваш K8s-кластер делает внешние запросы — к API партнёров, к маркетплейсам, к рекламным платформам — рано или поздно вы столкнётесь с блокировками по IP. Ingress Controller сам по себе управляет входящим трафиком, но для исходящих запросов через поды нужна отдельная схема с прокси. В этой статье разбираем, как это настроить правильно: от выбора типа прокси до конкретных YAML-конфигов для NGINX Ingress и Traefik.

Зачем прокси в Kubernetes: реальные сценарии

Kubernetes — это оркестратор, и большинство статей про него говорят про входящий трафик: как настроить Ingress, как выдать TLS-сертификат, как маршрутизировать запросы к сервисам. Но есть другая сторона: исходящий трафик из подов. Именно здесь возникают проблемы с блокировками, геоограничениями и лимитами по IP.

Рассмотрим конкретные задачи, где прокси в K8s-кластере становится необходимостью:

  • Парсинг и мониторинг цен. Ваш кластер запускает CronJob каждые 15 минут и собирает данные с Wildberries, Ozon, Amazon. Без ротации IP через 2–3 часа вы получите бан по всему диапазону IP вашего облачного провайдера.
  • Работа с рекламными API. Facebook Marketing API, TikTok Ads API, Google Ads API — все они отслеживают источник запросов. Если десятки подов шлют запросы с одного IP дата-центра, это триггер для автоматической блокировки.
  • Геолокационное тестирование. Ваш сервис должен показывать разный контент для пользователей из разных стран. Через прокси поды могут имитировать запросы из нужных регионов для автотестов.
  • Обход корпоративных ограничений. В некоторых инфраструктурах весь исходящий трафик должен идти через корпоративный прокси — это требование compliance.
  • Работа с партнёрскими API с белым списком IP. Когда партнёр разрешает запросы только с конкретных IP, а ваш кластер масштабируется и меняет адреса — прокси со статическими IP решает проблему.

Важно понимать архитектурное разделение: Ingress Controller управляет входящим трафиком (от пользователей к вашим сервисам), а прокси для исходящих запросов — это отдельная задача. Тем не менее, они связаны: конфигурация прокси часто задаётся на уровне того же Ingress Controller или через аннотации, которые он читает.

💡 Ключевое разграничение

В этой статье мы разбираем два сценария: (1) настройка Ingress Controller как обратного прокси для внешних upstream-серверов, и (2) маршрутизация исходящего трафика из подов через внешний прокси-сервер. Оба сценария встречаются в продакшне.

Какой тип прокси выбрать для K8s-кластера

Выбор типа прокси напрямую влияет на то, насколько долго ваш кластер сможет работать без блокировок. Дата-центровые IP — самые дешёвые, но их легко идентифицировать и заблокировать. Резидентные и мобильные IP — дороже, но значительно надёжнее для задач, где важна имитация реального пользователя.

Тип прокси Скорость Риск блокировки Лучший сценарий в K8s
Дата-центровые Высокая Высокий Внутренние API, корпоративный compliance, партнёрские интеграции с белым списком IP
Резидентные Средняя Низкий Парсинг маркетплейсов, работа с рекламными API, геотестирование
Мобильные Средняя Минимальный Facebook Ads API, TikTok API, высоконагруженные задачи с риском бана

Для большинства задач в K8s-кластере, связанных с парсингом или работой с рекламными платформами, оптимальный выбор — резидентные прокси с ротацией. Они предоставляют реальные IP домашних пользователей, и алгоритмы защиты сайтов воспринимают такие запросы как обычный браузерный трафик.

С точки зрения протокола для K8s наиболее универсален HTTP/HTTPS-прокси — его поддерживают все популярные HTTP-клиенты в любом языке программирования через стандартные переменные окружения HTTP_PROXY и HTTPS_PROXY. SOCKS5 нужен только для нестандартных протоколов или когда требуется проксировать не только HTTP.

Настройка прокси через NGINX Ingress Controller

NGINX Ingress Controller — самый распространённый вариант в K8s. Рассмотрим два сценария: настройка NGINX как обратного прокси к внешнему upstream через прокси-сервер, и глобальная настройка исходящего прокси для самого контроллера.

Аннотации для проксирования запросов к upstream

NGINX Ingress поддерживает аннотации для управления поведением прокси. Если вам нужно, чтобы Ingress передавал запросы к внешнему сервису через промежуточный прокси, используйте ConfigMap с кастомным конфигом:

apiVersion: v1
kind: ConfigMap
metadata:
  name: nginx-ingress-controller
  namespace: ingress-nginx
data:
  # Глобальный HTTP-прокси для исходящих запросов NGINX
  http-snippet: |
    proxy_connect_timeout 10s;
    proxy_read_timeout 30s;
    proxy_send_timeout 30s;
  # Настройка upstream через прокси
  use-proxy-protocol: "false"
  proxy-real-ip-cidr: "0.0.0.0/0"

Ingress-ресурс с аннотациями для прокси

Для отдельного Ingress-ресурса можно задать параметры прокси через аннотации. Это полезно, когда разные сервисы требуют разных таймаутов и настроек:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: my-service-ingress
  namespace: production
  annotations:
    kubernetes.io/ingress.class: "nginx"
    # Таймауты прокси
    nginx.ingress.kubernetes.io/proxy-connect-timeout: "10"
    nginx.ingress.kubernetes.io/proxy-read-timeout: "60"
    nginx.ingress.kubernetes.io/proxy-send-timeout: "60"
    # Размер буфера
    nginx.ingress.kubernetes.io/proxy-buffer-size: "16k"
    nginx.ingress.kubernetes.io/proxy-buffers-number: "8"
    # Передача реального IP клиента
    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

Настройка внешнего прокси для исходящих запросов NGINX-пода

Если сам NGINX Ingress Controller должен делать исходящие запросы через внешний прокси (например, для health-check внешних эндпоинтов), нужно задать переменные окружения в Deployment контроллера:

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"

Обратите внимание на переменную NO_PROXY — она критически важна. Без неё весь внутрикластерный трафик тоже пойдёт через внешний прокси, что сломает взаимодействие между сервисами. В NO_PROXY всегда включайте RFC-1918 диапазоны и суффикс .cluster.local.

Настройка прокси в Traefik Ingress Controller

Traefik — популярная альтернатива NGINX Ingress, особенно в связке с Helm и в managed-кластерах (k3s, Docker Swarm, Nomad). Traefik имеет свою систему конфигурации через CRD (Custom Resource Definitions) и статический/динамический конфиги.

Статическая конфигурация Traefik с прокси

apiVersion: v1
kind: ConfigMap
metadata:
  name: traefik-config
  namespace: traefik
data:
  traefik.yaml: |
    # Статическая конфигурация Traefik
    entryPoints:
      web:
        address: ":80"
      websecure:
        address: ":443"
    
    # Настройки для работы за прокси
    serversTransport:
      insecureSkipVerify: false
      maxIdleConnsPerHost: 200
      dialTimeout: 10s
      responseHeaderTimeout: 30s
    
    # Логирование для диагностики прокси
    log:
      level: INFO
    
    accessLog:
      fields:
        headers:
          defaultMode: keep
          names:
            X-Forwarded-For: keep
            X-Real-IP: keep

Middleware для добавления заголовков прокси

В Traefik можно создать Middleware, который будет добавлять или модифицировать заголовки при передаче запросов. Это полезно для корректной передачи реального IP клиента через цепочку прокси:

apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
  name: proxy-headers
  namespace: production
spec:
  headers:
    customRequestHeaders:
      X-Forwarded-Proto: "https"
    # Удаляем заголовки, которые могут раскрыть инфраструктуру
    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

Переменные окружения для Traefik Deployment

Аналогично NGINX, для Traefik задаём переменные окружения через Helm values или напрямую в Deployment. При использовании Helm-чарта это делается через values.yaml:

# values.yaml для Traefik Helm chart
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"

Прокси через переменные окружения в подах

Самый универсальный способ настроить исходящий прокси для любого пода — через стандартные переменные окружения. Этот метод работает независимо от языка программирования и фреймворка: Python requests, Go net/http, Node.js axios, Java HttpClient — все они читают HTTP_PROXY и HTTPS_PROXY автоматически.

Вариант 1: Прямо в Pod Spec

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"

⚠️ Не храните учётные данные в открытом виде!

Пример выше показан для наглядности. В продакшне учётные данные прокси всегда должны храниться в Kubernetes Secret и передаваться через secretKeyRef. Подробнее — в разделе про Secrets ниже.

Вариант 2: Через ConfigMap для нескольких подов

Если прокси используют несколько Deployment, удобно вынести настройки в ConfigMap и подключать его через 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

Вариант 3: Мутирующий WebhookAdmissionController

Для корпоративных кластеров, где все поды обязаны использовать прокси, можно настроить мутирующий admission webhook, который автоматически добавляет переменные окружения прокси ко всем создаваемым подам. Это решение используется в enterprise-инфраструктурах, где compliance требует, чтобы весь исходящий трафик шёл через корпоративный прокси. Реализация такого webhook выходит за рамки этой статьи, но стоит знать о его существовании.

Ротация IP и управление прокси-пулом в K8s

Статический прокси — это хорошо для корпоративного compliance, но плохо для задач, где нужно избегать блокировок. Если 50 ваших подов шлют запросы через один и тот же IP, этот IP заблокируют очень быстро. Решение — ротация прокси.

Схема с Proxy Sidecar

Один из паттернов — запускать прокси-агент как sidecar-контейнер рядом с основным приложением. Sidecar принимает запросы на localhost:8080 и пересылает их через ротирующийся пул внешних прокси:

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:
      # Основное приложение
      - 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: локальный прокси-агент с ротацией
      - 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"  # ротация каждые 60 секунд
        resources:
          requests:
            memory: "64Mi"
            cpu: "50m"
          limits:
            memory: "128Mi"
            cpu: "200m"

Схема с центральным Proxy Service

Альтернативный подход — единый Proxy Service внутри кластера, к которому обращаются все поды. Это проще в управлении: достаточно обновить один Secret с учётными данными прокси, и все поды автоматически начнут использовать новые данные.

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
---
# Поды используют прокси через внутренний DNS
# HTTP_PROXY=http://proxy-gateway.proxy-system.svc.cluster.local:8080

Для задач, где критична анонимность и минимальный риск блокировок (например, парсинг маркетплейсов или работа с рекламными API), рекомендуем использовать резидентные прокси с ротацией — они предоставляют реальные IP домашних пользователей, что делает трафик из вашего кластера неотличимым от обычного браузерного.

Хранение учётных данных прокси в Kubernetes Secrets

Безопасное хранение учётных данных — обязательное требование для любого продакшн-кластера. Никогда не вставляйте логин/пароль прокси напрямую в YAML-манифесты, которые хранятся в Git-репозитории.

Создание Secret для прокси

# Создание через kubectl (значения кодируются в 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'

# Проверка созданного Secret
kubectl get secret proxy-credentials -n production -o yaml

YAML-манифест Secret

apiVersion: v1
kind: Secret
metadata:
  name: proxy-credentials
  namespace: production
  labels:
    app: proxy-config
    managed-by: ops-team
type: Opaque
# Значения закодированы в base64
# echo -n 'http://user:pass@proxy:8080' | base64
stringData:
  # stringData позволяет указывать значения в открытом виде
  # Kubernetes автоматически кодирует их в 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"

Использование Secret в 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"
        # Для приложений, которые читают хост/порт отдельно
        - name: PROXY_HOST
          valueFrom:
            secretKeyRef:
              name: proxy-credentials
              key: proxy-host
        - name: PROXY_PORT
          valueFrom:
            secretKeyRef:
              name: proxy-credentials
              key: proxy-port

Интеграция с внешними хранилищами секретов

В enterprise-среде рекомендуется использовать External Secrets Operator для синхронизации секретов из HashiCorp Vault, AWS Secrets Manager или Azure Key Vault. Это позволяет автоматически обновлять учётные данные прокси без ручного вмешательства и перезапуска подов:

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

Диагностика и типичные ошибки при настройке прокси в K8s

Даже при правильной конфигурации могут возникать проблемы. Разберём самые частые из них и способы диагностики.

Проблема 1: Внутрикластерный трафик идёт через прокси

Симптом: поды перестают видеть друг друга, DNS-резолюция внутри кластера ломается, сервисы не отвечают. Причина — не настроена переменная NO_PROXY.

Минимально необходимое значение NO_PROXY для стандартного K8s-кластера:

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

Проблема 2: Прокси не применяется к конкретному поду

Диагностика: зайдите в под и проверьте переменные окружения:

# Проверка переменных окружения в поде
kubectl exec -it <pod-name> -n production -- env | grep -i proxy

# Тест подключения через прокси из пода
kubectl exec -it <pod-name> -n production -- curl -v --proxy http://proxy:8080 https://httpbin.org/ip

# Проверка что Secret смонтирован корректно
kubectl exec -it <pod-name> -n production -- env | grep PROXY

Проблема 3: TLS-ошибки при использовании HTTPS-прокси

Если прокси использует самоподписанный сертификат или корпоративный CA, приложения будут получать ошибки верификации TLS. Решение — добавить CA-сертификат прокси в доверенные:

# Создание ConfigMap с CA-сертификатом
kubectl create configmap proxy-ca-cert \
  --from-file=proxy-ca.crt=./proxy-ca.crt \
  -n production

# Монтирование в под
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

Проблема 4: Медленные запросы через прокси

Если запросы через прокси значительно медленнее прямых — проверьте:

  • DNS-резолюция: убедитесь, что DNS-запросы не идут через прокси (добавьте в NO_PROXY)
  • Keep-alive соединения: настройте пул соединений к прокси-серверу
  • Географическое расположение: прокси-сервер должен быть физически близко к целевому ресурсу
  • Тип прокси: для высокоскоростных задач рассмотрите прокси дата-центров — они обеспечивают минимальную задержку

Полезные команды для диагностики

# Проверить логи Ingress Controller
kubectl logs -n ingress-nginx -l app.kubernetes.io/name=ingress-nginx --tail=100

# Проверить события пода
kubectl describe pod <pod-name> -n production

# Тест прокси-соединения из пода
kubectl run test-proxy --image=curlimages/curl --rm -it --restart=Never -- \
  curl -x http://user:pass@proxy:8080 -v https://httpbin.org/ip

# Проверить что Secret существует и содержит нужные ключи
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]}...')
"

Заключение и рекомендации

Настройка прокси в Kubernetes — это не разовая задача, а часть архитектуры сетевой безопасности кластера. Подведём итоги:

  • Для NGINX Ingress Controller — используйте аннотации для настройки параметров прокси на уровне отдельных Ingress-ресурсов, и переменные окружения в Deployment для глобальных настроек исходящего трафика.
  • Для Traefik — комбинируйте статическую конфигурацию через ConfigMap с Middleware для управления заголовками.
  • Для подов — стандартные переменные HTTP_PROXY / HTTPS_PROXY через Secrets — самый универсальный и безопасный подход.
  • Всегда настраивайте NO_PROXY — иначе внутрикластерный трафик сломается.
  • Никогда не храните учётные данные прокси в открытом виде в манифестах или в Git.
  • Для продакшна — используйте External Secrets Operator для автоматической ротации учётных данных.

Если ваш K8s-кластер выполняет задачи, где критична стабильность IP и минимальный риск блокировок — парсинг, работа с рекламными API, геотестирование — рекомендуем использовать резидентные прокси. Они обеспечивают реальные IP домашних пользователей, которые алгоритмы защиты воспринимают как легитимный трафик. Для задач с высокими требованиями к скорости и минимальными рисками блокировок со стороны мобильных платформ отлично подойдут мобильные прокси — они работают через реальные 4G/5G-сети операторов.