ブログに戻る

Kubernetes Ingress Controllerのプロキシ:K8sクラスターでの完全な設定と構成例

Kubernetes Ingress Controllerでのプロキシサーバーの正しい設定方法を解説します。基本的なNGINXの設定から、ブロック回避のための常駐IPのローテーションまで。

📅2026年8月10日
```html

あなたのK8sクラスターが外部API、マーケットプレイス、広告プラットフォームにリクエストを送信する場合、遅かれ早かれIPによるブロックに直面することになります。Ingress Controllerは、受信トラフィックを管理しますが、ポッドを介した送信リクエストには別のプロキシスキームが必要です。この記事では、プロキシのタイプの選択から、NGINX IngressとTraefikの具体的なYAML設定まで、正しい設定方法を解説します。

Kubernetesにおけるプロキシの必要性:実際のシナリオ

Kubernetesはオーケストレーターであり、ほとんどの関連記事は受信トラフィックについて述べています:Ingressの設定、TLS証明書の発行、サービスへのリクエストのルーティング。しかし、もう一つの側面があります:ポッドからの送信トラフィックです。ここでIPによるブロック、地理的制限、IP制限の問題が発生します。

K8sクラスターでプロキシが必要となる具体的なタスクを考えてみましょう:

  • 価格のパースとモニタリング。 あなたのクラスターは15分ごとにCronJobを実行し、Wildberries、Ozon、Amazonからデータを収集します。IPのローテーションなしでは、2〜3時間後にクラウドプロバイダーのIP範囲全体がブロックされます。
  • 広告APIとの連携。 Facebook Marketing API、TikTok Ads API、Google Ads APIはすべてリクエストのソースを追跡します。数十のポッドが同じデータセンターのIPからリクエストを送信すると、自動ブロックのトリガーとなります。
  • ジオロケーションテスト。 あなたのサービスは異なる国のユーザーに異なるコンテンツを表示する必要があります。プロキシを介してポッドは必要な地域からのリクエストを模倣し、自動テストを行うことができます。
  • 企業の制限を回避。 一部のインフラストラクチャでは、すべての送信トラフィックが企業プロキシを経由する必要があります。これはコンプライアンスの要件です。
  • ホワイトリストIPのパートナーAPIとの連携。 パートナーが特定のIPからのリクエストのみを許可し、あなたのクラスターがスケールアップしてアドレスを変更する場合、静的IPを持つプロキシが問題を解決します。

アーキテクチャの分離を理解することが重要です:Ingress Controllerは受信トラフィックを管理します(ユーザーからあなたのサービスへ)、そして送信リクエストのためのプロキシは別のタスクです。それでも、両者は関連しています:プロキシの設定はしばしば同じIngress Controllerのレベルまたはそれが読み取るアノテーションで設定されます。

💡 重要な区分

この記事では、2つのシナリオを検討します:(1)外部アップストリームサーバーへのリバースプロキシとしてのIngress Controllerの設定、(2)ポッドから外部プロキシサーバーを介した送信トラフィックのルーティング。どちらのシナリオも本番環境で見られます。

K8sクラスターに適したプロキシの選択

プロキシのタイプの選択は、クラスターがブロックなしでどれだけ長く動作できるかに直接影響します。データセンターのIPは最も安価ですが、特定されやすく、ブロックされやすいです。居住者IPとモバイルIPは高価ですが、実際のユーザーを模倣する必要があるタスクにははるかに信頼性があります。

プロキシタイプ 速度 ブロックリスク K8sでの最適なシナリオ
データセンター 高い 高い 内部API、企業のコンプライアンス、ホワイトリスト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で最も一般的な選択肢です。2つのシナリオを考えてみましょう:プロキシサーバーを介して外部アップストリームへのリバースプロキシとしてNGINXを設定すること、そしてコントローラー自体のための送信プロキシのグローバル設定です。

アップストリームへのリクエストをプロキシするためのアノテーション

NGINX Ingressは、プロキシの動作を管理するためのアノテーションをサポートしています。Ingressが外部サービスへのリクエストを中間プロキシを介して転送する必要がある場合は、カスタム設定を持つConfigMapを使用します:

apiVersion: v1
kind: ConfigMap
metadata:
  name: nginx-ingress-controller
  namespace: ingress-nginx
data:
  # NGINXの送信リクエスト用のグローバルHTTPプロキシ
  http-snippet: |
    proxy_connect_timeout 10s;
    proxy_read_timeout 30s;
    proxy_send_timeout 30s;
  # プロキシを介したアップストリームの設定
  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自体が外部プロキシを介して送信リクエストを行う必要がある場合(例えば、外部エンドポイントのヘルスチェックのため)、コントローラーの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は、特にHelmやマネージドクラスター(k3s、Docker Swarm、Nomad)と組み合わせて使用される人気のあるNGINX Ingressの代替手段です。Traefikは、CRD(カスタムリソース定義)を介した独自の設定システムと静的/動的設定を持っています。

プロキシを使用した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

プロキシヘッダーを追加するためのミドルウェア

Traefikでは、リクエストを転送する際にヘッダーを追加または変更するミドルウェアを作成できます。これは、プロキシチェーンを介してクライアントの実際の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を介して行います:

# Traefik Helmチャートのためのvalues.yaml
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

すべてのポッドがプロキシを使用する必要がある企業クラスターでは、すべての作成されるポッドにプロキシの環境変数を自動的に追加するミューテイティングアドミッションWebhookを設定できます。このソリューションは、すべての送信トラフィックが企業プロキシを経由することを要求するコンプライアンスがあるエンタープライズインフラストラクチャで使用されます。このようなWebhookの実装はこの記事の範囲を超えますが、その存在を知っておくことは重要です。

K8sにおけるIPのローテーションとプロキシプールの管理

静的プロキシは企業のコンプライアンスには良いですが、ブロックを回避する必要があるタスクには不向きです。50のポッドが同じIPを介してリクエストを送信すると、そのIPは非常に早くブロックされます。解決策はプロキシのローテーションです。

プロキシサイドカーのスキーム

一つのパターンは、プロキシエージェントをメインアプリケーションの隣にサイドカーコンテナとして起動することです。サイドカーは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"
      
      # サイドカー:ローカルプロキシエージェントとローテーション
      - 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"

中央プロキシサービスのスキーム

代替アプローチは、クラスター内の単一のプロキシサービスで、すべてのポッドがそれにアクセスします。これにより管理が簡素化されます。プロキシの認証情報を含むSecretを1つ更新するだけで、すべてのポッドが自動的に新しいデータを使用し始めます。

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におけるプロキシの認証情報の保存

認証情報の安全な保存は、すべての本番クラスターにおける必須要件です。決して、Gitリポジトリに保存されるYAMLマニフェストにプロキシのユーザー名/パスワードを直接挿入しないでください。

プロキシ用の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

SecretのYAMLマニフェスト

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"

DeploymentでのSecretの使用

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

外部シークレットストレージとの統合

エンタープライズ環境では、HashiCorp Vault、AWS Secrets Manager、またはAzure Key Vaultからのシークレットを同期するためにExternal Secrets Operatorを使用することが推奨されます。これにより、手動での介入やポッドの再起動なしにプロキシの認証情報を自動的に更新できます:

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変数が設定されていないことです。

標準のK8sクラスターに必要な最小限のNO_PROXYの値は次のとおりです:

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:HTTPSプロキシ使用時のTLSエラー

プロキシが自己署名証明書または企業CAを使用している場合、アプリケーションはTLS検証エラーを受け取ります。解決策は、プロキシのCA証明書を信頼されたものに追加することです:

# CA証明書を持つConfigMapを作成
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を介した静的設定とヘッダー管理のためのミドルウェアを組み合わせてください。
  • ポッドの場合 — Secretsを介した標準のHTTP_PROXY / HTTPS_PROXYの使用が最も汎用的で安全なアプローチです。
  • 常にNO_PROXYを設定してください — そうしないと、クラスター内トラフィックが壊れます。
  • 認証情報を決して平文で保存しないでください — マニフェストやGitに保存しないでください。
  • 本番環境では — 認証情報の自動ローテーションのためにExternal Secrets Operatorを使用してください。

あなたのK8sクラスターがIPの安定性とブロックのリスクを最小限に抑える必要があるタスクを実行している場合(パース、広告APIとの連携、ジオテストなど)、居住者プロキシの使用をお勧めします。これにより、実際の家庭ユーザーのIPが提供され、保護アルゴリズムはそれを正当なトラフィックとして認識します。速度とブロックリスクが最小限に抑えられるモバイルプラットフォーム向けのタスクには、モバイルプロキシが最適です。これらは、実際の4G/5Gネットワークを介して動作します。

```