すべてのプロダクト
Search
ドキュメントセンター

Container Service for Kubernetes:NGINX Ingress のよくある質問

最終更新日:Jun 18, 2026

NGINX Ingress Controller の TLS、設定、パフォーマンス、アップグレードに関する一般的な問題を解決します。

NGINX Ingress Controller の以前のバージョンにおける既知の問題

以前のバージョンには、次の既知の問題があります。安定性のため、最新バージョンにアップグレードしてください。

サポートされている TLS バージョン

Ingress-nginx は TLS 1.2 と TLS 1.3 をサポートしています。TLS 1.2 より前の TLS バージョンを使用しているクライアントでは、ハンドシェイクエラーが発生する場合があります。

追加の TLS バージョンをサポートするには、kube-system 名前空間の nginx-configuration ConfigMap に以下を追加します。「TLS/HTTPS」をご参照ください。

説明

NGINX Ingress Controller 1.7.0 以降で TLS 1.0 または 1.1 を有効にするには、ssl-ciphers パラメーターに @SECLEVEL=0 を指定します。

image.png

ssl-ciphers: "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA256:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:@SECLEVEL=0"
ssl-protocols: "TLSv1 TLSv1.1 TLSv1.2 TLSv1.3"

バックエンドサーバーへのリクエストヘッダーの受け渡し

デフォルトでは、 ingress-nginx はレイヤー 7 のリクエストヘッダーをバックエンドサーバーに渡しますが、非標準 HTTP ヘッダー (Mobile_Version など)はフィルタリングします。これらのヘッダーを保持するには、 kubectl edit cm -n kube-system nginx-configuration を実行して ConfigMap を更新します。詳細については、「ConfigMap」をご参照ください。

enable-underscores-in-headers: true

HTTPS バックエンドサーバーへのリクエスト転送方法

ingress-nginx を介して HTTPS バックエンドサーバーにリクエストを転送するには、次のアノテーションを Ingress に追加します。

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: xxxx
  annotations:
    # バックエンドサーバーのプロトコルに、HTTPS を指定する必要があります。
    nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"

レイヤー 7 でクライアント IP アドレスを渡す方法

デフォルトでは、ingress-nginxX-Forwarded-For および X-Real-IP ヘッダーを追加してクライアント IP アドレスを渡します。ただし、クライアントがすでにこれらのヘッダーを含んでいる場合、バックエンドサーバーは元のクライアント IP を取得できません。

kubectl edit cm -n kube-system nginx-configuration を実行して nginx-configuration ConfigMap を変更し、ingress-nginx がレイヤー 7 でクライアント IP アドレスを渡せるようにします。

compute-full-forwarded-for: "true"
forwarded-for-header: "X-Forwarded-For"
use-forwarded-headers: "true"

トラフィックが NGINX Ingress に到達する前に複数のアップストリームプロキシサーバーを経由する場合、nginx-configuration ConfigMap に proxy-real-ip-cidr フィールドを追加し、proxy-real-ip-cidr をアップストリームプロキシサーバーの CIDR ブロック (カンマ区切り) に設定する必要があります。詳細については、「WAF の使用」をご参照ください。

proxy-real-ip-cidr:  "0.0.0.0/0,::/0"  

Classic Load Balancer (CLB) インスタンスの背後で NGINX Ingress が空の X-Forwarded-For ヘッダーを受信する IPv6 シナリオでは、CLB で Proxy プロトコルを有効にしてクライアント IP を取得します。詳細については、「CLB のレイヤー 4 リスナーによるクライアント IP アドレスの取得」をご参照ください。

HSTS の設定方法

HTTP Strict Transport Security (HSTS) はデフォルトで有効になっています。ブラウザが平文の HTTP で初めてサービスにアクセスすると、サーバーは HSTS を有効にするレスポンスを返します。その後、HSTS と互換性のあるブラウザが同じサービスに HTTP でアクセスしようとすると、リクエストは自動的に HTTPS に切り替えられます。これにより、307 Internal Redirect ステータスコードが返され、開発者ツールにはその理由として Non-Authoritative-Reason: HSTS レスポンスヘッダーが表示されます。1

ブラウザが以降のリクエストを HTTPS に自動的にアップグレードするのを防ぐには、nginx-ingress-controller の HSTS を無効にします。詳細については、「HSTS」をご参照ください。

説明

ブラウザは HSTS 設定をキャッシュします。nginx-ingress-controller の HSTS を無効にした後は、手動でブラウザのキャッシュをクリアしてください。

サポートされている書き換えルール

Ingress-nginx は、単純な 書き換え ルールのみをサポートしています。複雑な書き換えルールには、以下を使用します。

その他のスニペットはグローバル設定を追加します。main-snippet をご参照ください。2

NGINX Ingress Controller のアップグレード時に更新されるリソース

NGINX Ingress Controller のバージョンが 0.44 未満の場合、次のリソースが含まれます:

  • serviceaccount/ingress-nginx

  • configmap/nginx-configuration

  • configmap/tcp-services

  • configmap/udp-services

  • clusterrole.rbac.authorization.k8s.io/ingress-nginx

  • clusterrolebinding.rbac.authorization.k8s.io/ingress-nginx

  • role.rbac.authorization.k8s.io/ingress-nginx

  • rolebinding.rbac.authorization.k8s.io/ingress-nginx

  • service/nginx-ingress-lb

  • deployment.apps/nginx-ingress-controller

バージョンが 0.44 以降の場合、上記のリソースに加えて、次のリソースも含まれます:

  • validatingwebhookconfiguration.admissionregistration.k8s.io/ingress-nginx-admission

  • service/ingress-nginx-controller-admission

  • serviceaccount/ingress-nginx-admission

  • clusterrole.rbac.authorization.k8s.io/ingress-nginx-admission

  • clusterrolebinding.rbac.authorization.k8s.io/ingress-nginx-admission

  • role.rbac.authorization.k8s.io/ingress-nginx-admission

  • rolebinding.rbac.authorization.k8s.io/ingress-nginx-admission

  • job.batch/ingress-nginx-admission-create

  • job.batch/ingress-nginx-admission-patch

ACK コンソールの [アドオン] ページで NGINX Ingress Controller をアップグレードする場合、次のリソースは変更されません:

  • configmap/nginx-configuration

  • configmap/tcp-services

  • configmap/udp-services

  • service/nginx-ingress-lb

他のすべてのリソース構成はデフォルト値に戻ります。 たとえば、deployment.apps/nginx-ingress-controller リソースにおける replicas のデフォルト値は 2 です。 NGINX Ingress Controller をアップグレードする前に replicas5 に設定した場合、アップグレード後にデフォルト値の 2 に戻ります。

レイヤー 4 リスナーからレイヤー 7 リスナーへの切り替え

デフォルトでは、ingress-nginx の LoadBalancer は TCP ポート 80 および 443 でリッスンします。プロトコルを HTTP または HTTPS に変更することで、レイヤー 7 リスナーに切り替えます。

説明

リスナーの変更中はサービスが中断されます。オフピーク時間に実行してください。

  1. 証明書を作成し、証明書 ID (cert-id) を記録します。詳細については、「証明書管理サービスの証明書を使用する」をご参照ください。

  2. annotations を使用して、Ingress が使用する LoadBalancer リスナーをレイヤー 4 からレイヤー 7 に変更します。

    1. ACKコンソールにログインします。 左側のナビゲーションウィンドウで、[クラスター] をクリックします。

    2. [クラスター] ページで、管理するクラスターの名前をクリックします。 左側のウィンドウで、[ネットワーク] > [サービス] を選択します。

    3. [Service] ページの上部で、[名前空間]kube-system に設定します。ingress-nginx-lb Service を見つけ、[操作] 列の [YAML の編集] をクリックします。

    4. [YAML の編集] パネルで、https という名前のポート (ポート 443) の targetPort80 に更新します。

        - name: https
          port: 443
          protocol: TCP
          targetPort: 80 # ポート 443 の targetPort を 80 に設定します。

      annotations フィールドに以下を追加し、[OK] をクリックします。

      service.beta.kubernetes.io/alibaba-cloud-loadbalancer-protocol-port: "http:80,https:443"
      service.beta.kubernetes.io/alibaba-cloud-loadbalancer-cert-id: "${YOUR_CERT_ID}"
  3. 結果を確認します。

    1. [Service] ページで、[ingress-nginx-lb] Service を見つけ、[タイプ] 列の image アイコンをクリックします。

    2. [リスナー] タブをクリックします。[フロントエンドプロトコル/ポート] 列に HTTP:80HTTPS:443 の両方が表示されている場合、LoadBalancer のリスナーがレイヤー 4 からレイヤー 7 に変更されています。

ack-ingress-nginx での既存 SLB インスタンスの使用

  1. ACKコンソールにログインします。 左側のナビゲーションウィンドウで、[Marketplace] > [Marketplace] を選択します。

  2. [アプリカタログ] タブで、クラスターのバージョンに基づいて [ack-ingress-nginx] または [ack-ingress-nginx-v1] を選択します。

    • クラスターが Kubernetes 1.20 以前を実行している場合は、[ack-ingress-nginx] を選択します。

    • クラスターが 1.20 より後の Kubernetes バージョンを実行している場合は、[ack-ingress-nginx-v1] を選択します。

  3. Ingress controller をデプロイします。詳細については、「複数の Ingress controller をデプロイしてトラフィックを分離する」をご参照ください。

    [パラメーター] ページで、次の手順を実行します。

    1. controller.service.annotations セクションのアノテーションをすべて削除します。

      image..png

    2. 新しいアノテーションを追加します。

      # 使用する SLB インスタンスを指定します。
      service.beta.kubernetes.io/alibaba-cloud-loadbalancer-id: "${YOUR_LOADBALANCER_ID}"
      # リスナーを強制的に上書きします。
      service.beta.kubernetes.io/alibaba-cloud-loadbalancer-force-override-listeners: "true"

      image..png

  4. [OK] をクリックして Ingress controller をデプロイします。

  5. Ingress controller をデプロイした後、IngressClass を設定します。詳細については、「複数の Ingress controller をデプロイしてトラフィックを分離する」をご参照ください。

複数の Ingress controller からのアクセスログ収集

前提条件

手順

  1. ACK コンソールにログインします。左側のナビゲーションペインで、[クラスター] をクリックします。

  2. [クラスター] ページで、対象のクラスター名をクリックし、左側のナビゲーションペインで [クラスター情報] をクリックします。

  3. [クラスター情報] ページで、[基本情報] タブをクリックし、[クラスターリソース] セクションにある [Log Service プロジェクト] の右側のリンクをクリックします。

  4. [Logstore] ページで Logstore を作成します (詳細については、「Logstore の管理」をご参照ください)。収集の重複を避けるために、Ingress controller ごとに個別の Logstore を作成します。

    • Logstore には、使用する Ingress controller の名前を付けます。

    • 表示されるメッセージで、[データ収集ウィザード] をクリックします。

  5. [クイックデータインポート] ダイアログボックスで、[K8S - 標準出力と標準エラー - 旧バージョン] > [今すぐ統合][注意] メッセージで [続行] をクリックします。[Kubernetes 標準出力と標準エラー] ページで、次の操作を実行します。

    1. [マシングループの作成] ステップで、[既存のマシングループを使用] をクリックします。

    2. [マシングループ設定] ステップで、k8s-group-<YOUR_CLUSTER_ID> マシングループを選択し、> をクリックしてマシングループを [適用済みサーバーグループ] セクションに移動します。次に、[次へ] をクリックします。

    3. [Logtail 設定] ステップで、次の手順を実行します。

      1. [他の設定をインポート] をクリックします。クラスターで使用中のプロジェクトと k8s-nginx-ingress 設定を選択します。次に、[OK] をクリックします。

      2. [グローバル設定] セクションで、設定名を変更します。[コンテナフィルター] オプションを有効にし、Ingress controller コンテナのラベルをキーと値のペアとして追加します。

      3. [プロセッサー設定] セクションで、[プロセッサー名] 列の [フィールドの抽出 (正規表現モード)] をクリックして、ログ処理フィールドを表示します。

        説明

        異なる NGINX Ingress Controller が異なるログ形式を使用する場合は、対応するログフィールドのキーと正規表現を設定します。

    4. [クエリと分析の設定] ステップで、[次へ] をクリックします。

    5. [終了] ステップで、[ログのクエリ] をクリックして、収集されたログを表示します。

nginx-ingress-controller での TCP リスナーの有効化

デフォルトでは、Ingress は HTTP および HTTPS リクエストのみを転送します。ingress-nginx を設定して、関連する ConfigMap で指定されたポートに外部 TCP リクエストを転送します。

  1. tcp-echo テンプレートを使用して、Service と Deployment をデプロイします。

  2. 次のテンプレートを使用して ConfigMap を作成します。

    1. tcp-services-cm.yaml ファイルを変更し、変更を保存して終了します。

      apiVersion: v1
      kind: ConfigMap
      metadata:
        name: tcp-services
        namespace: kube-system 
      data:
        9000: "default/tcp-echo:9000" # ポート 9000 で受信した外部 TCP リクエストを、default 名前空間の tcp-echo Service に転送します。
        9001: "default/tcp-echo:9001" 
    2. ConfigMap を作成します。

      kubectl apply -f tcp-services-cm.yaml
  3. nginx-ingress-controller が使用する Service に TCP ポートを追加し、変更を保存して終了します。

    kubectl edit svc nginx-ingress-lb -n kube-system 
    apiVersion: v1
    kind: Service
    metadata:
      labels:
        app: nginx-ingress-lb
      name: nginx-ingress-lb
      namespace: kube-system
    spec:
      allocateLoadBalancerNodePorts: true
      clusterIP: 192.168.xx.xx
      ipFamilies:
      - IPv4
      ports:
      - name: http
        nodePort: 30xxx
        port: 80
        protocol: TCP
        targetPort: 80
      - name: https
        nodePort: 30xxx
        port: 443
        protocol: TCP
        targetPort: 443
      - name: tcp-echo-9000       # ポート名。
        port: 9000                # ポート番号。
        protocol: TCP             # プロトコル。
        targetPort: 9000          # 宛先ポート。
      - name: tcp-echo-9001       # ポート名。
        port: 9001                # ポート番号。
        protocol: TCP             # プロトコル。
        targetPort: 9001
      selector:
        app: ingress-nginx
      sessionAffinity: None
      type: LoadBalancer
  4. 設定を確認します:

    1. Ingress をクエリして、SLB インスタンスの IP アドレスを取得します:

       kubectl get svc -n kube-system| grep nginx-ingress-lb 

      期待される出力:

      nginx-ingress-lb      LoadBalancer   192.168.xx.xx  172.16.xx.xx   80:31246/TCP,443:30298/TCP,9000:32545/TCP,9001:31069/TCP   
    2. nc を使用して、IP アドレスのポート 9000 に helloworld を送信します。「helloworld」という応答が返された場合、設定は有効になっています。

      echo "helloworld" |  nc <172.16.xx.xx> 9000
      
      echo "helloworld" |  nc <172.16.xx.xx> 9001

NGINX Ingress Controller による TLS 証明書とリクエストの対応付け

Kubernetes の Ingress リソースでは、TLS 証明書は spec.tls フィールドで定義されますが、適用対象のホスト名は spec.rules.host フィールドで指定されます。

NGINX Ingress Controller は、これらのルールを処理し、各ホスト名と対応する証明書のマッピングを内部の Lua テーブルに保存します。

リクエストフロー

  1. クライアントが HTTPS リクエストを開始すると、TLS ハンドシェイクのサーバー名表示 (SNI) 拡張にリクエストされたホスト名が含まれます。

  2. NGINX Ingress Controller はこのリクエストを受信し、certificate.call() 関数を使用して、Lua マッピングテーブルで SNI ホスト名を検索します。

  3. 一致する証明書が見つかった場合、その証明書がクライアントに提示され、TLS ハンドシェイクが完了します。

  4. リクエストされたホスト名に一致する証明書が見つからない場合、コントローラーはデフォルトの自己署名 fake 証明書を提示します。

このロジックを実装する NGINX の関連設定を以下に示します。


    ## サーバー _ の開始
    server {
        server_name _ ;
        listen 80 default_server reuseport backlog=65535 ;
        listen [::]:80 default_server reuseport backlog=65535 ;
        listen 443 default_server reuseport backlog=65535 ssl http2 ;
        listen [::]:443 default_server reuseport backlog=65535 ssl http2 ;
        set $proxy_upstream_name "-";
        ssl_reject_handshake off;
        ssl_certificate_by_lua_block {
            certificate.call()
        }
   ...
   }
    
    
    ## サーバー www.example.com の開始
    server {
        server_name www.example.com ;
        listen 80  ;
        listen [::]:80  ;
        listen 443  ssl http2 ;
        listen [::]:443  ssl http2 ;
        set $proxy_upstream_name "-";
        ssl_certificate_by_lua_block {
            certificate.call()
        }
    ...
    }

ingress-nginx は OCSP ステープリングをサポートしており、失効チェックのための CA への直接接続を不要にし、初期接続時間を短縮します。詳細については、「OCSP ステープリングの設定」をご参照ください。

NGINX Ingress に一致する証明書がない場合の対処

TLS 証明書と秘密キーが一致しない場合、または証明書内のドメイン名がクライアントが使用するホスト名と一致しない場合、HTTPS アクセスエラーが発生することがあります。この問題をトラブルシューティングするには、次の操作を実行してください。

  • 証明書と秘密キーが一致していることの確認

    Kubernetes Secret から証明書と秘密キーを抽出し、暗号モジュラスを比較します。

    # <YOUR-SECRET-NAME> と <SECRET-NAMESPACE> をご自身の値に置き換えます
    kubectl get secret <YOUR-SECRET-NAME>  -n <SECRET-NAMESPACE> -o jsonpath='{.data.tls\.crt}' | base64 -d > /tmp/tls.crt && \ # <YOUR-SECRET-NAME> を実際の Secret 名に置き換えます
    kubectl get secret <YOUR-SECRET-NAME>  -n <SECRET-NAMESPACE> -o jsonpath='{.data.tls\.key}' | base64 -d > /tmp/tls.key && \
    
    # 証明書とキーのモジュラスのMD5 ハッシュを計算して比較します
    openssl x509 -noout -modulus -in /tmp/tls.crt | openssl md5 && \
    openssl rsa -noout -modulus -in /tmp/tls.key | openssl md5

    これらのコマンドは、証明書とキーをそれぞれ /tmp/tls.crt/tmp/tls.key に抽出します。 openssl コマンドは、両方の公開モジュラスの MD5 ハッシュを計算します。

    ハッシュ値が 一致しない 場合、証明書と秘密キーは一致していません。有効で一致するキーペアで Secret を更新してください。

  • 証明書がドメイン名と一致していることの確認

    証明書を確認し、対応するドメイン名を確認します。

    kubectl get secret  <YOUR-SECRET-NAME>  -n <SECRET-NAMESPACE>  -o jsonpath={.data."tls\.crt"} | base64 -d  | openssl x509  -text -noout

    出力を確認してください。

    • サブジェクト:共通名 (CN) フィールドを確認してください。形式は CN = example.com のようになります。

    • サブジェクトの代替名 (SAN)DNS: エントリを確認してください。

    ホスト名が CN または SAN エントリ に記載されていない場合、そのドメイン名に対して証明書は無効です。正しいホスト名を含む新しい証明書を取得してください。

高トラフィック下で NGINX Pod がヘルスチェックに失敗した場合の対処法

背景

NGINX Ingress Controller のヘルスチェックは、ポート 10246/healthz パスにアクセスし、NGINX プロセスが正常であることを確認します。

症状

ヘルスチェックが失敗すると、ログには healthz エンドポイントに到達できないことが示されます。

I0412 11:01:52.581960       7 healthz.go:261] nginx-ingress-controller check failed: healthz
[-]nginx-ingress-controller failed: the ingress controller is shutting down
2024/04/12 11:01:55 Get "http://127.0.0.1:10246/nginx_status": dial tcp 127.0.0.1:10246: connect: connection refused
W0412 11:01:55.895683       7 nginx_status.go:171] unexpected error obtaining nginx status info: Get "http://127.0.0.1:10246/nginx_status": dial tcp 127.0.0.1:10246: connect: connection refused
I0412 11:02:02.582247       7 healthz.go:261] nginx-ingress-controller check failed: healthz
[-]nginx-ingress-controller failed: the ingress controller is shutting down
2024/04/12 11:02:05 Get "http://127.0.0.1:10246/nginx_status": dial tcp 127.0.0.1:10246: connect: connection refused
W0412 11:02:05.896126       7 nginx_status.go:171] unexpected error obtaining nginx status info: Get "http://127.0.0.1:10246/nginx_status": dial tcp 127.0.0.1:10246: connect: connection refused
I0412 11:02:12.582687       7 healthz.go:261] nginx-ingress-controller check failed: healthz
[-]nginx-ingress-controller failed: the ingress controller is shutting down
2024/04/12 11:02:15 Get "http://127.0.0.1:10246/nginx_status": dial tcp 127.0.0.1:10246: connect: connection refused
W0412 11:02:15.895719       7 nginx_status.go:171] unexpected error obtaining nginx status info: Get "http://127.0.0.1:10246/nginx_status": dial tcp 127.0.0.1:10246: connect: connection refused
I0412 11:02:22.582516       7 healthz.go:261] nginx-ingress-controller check failed: healthz
[-]nginx-ingress-controller failed: the ingress controller is shutting down
2024/04/12 11:02:25 Get "http://127.0.0.1:10246/nginx_status": dial tcp 127.0.0.1:10246: connect: connection refused
W0412 11:02:25.896955       7 nginx_status.go:171] unexpected error obtaining nginx status info: Get "http://127.0.0.1:10246/nginx_status": dial tcp 127.0.0.1:10246: connect: connection refused
I0412 11:02:28.983016       7 nginx.go:408] "NGINX process has stopped"
I0412 11:02:28.983033       7 sigterm.go:44] Handled quit, delaying controller exit for 10 seconds
I0412 11:02:32.582587       7 healthz.go:261] nginx-ingress-controller check failed: healthz
[-]nginx-ingress-controller failed: the ingress controller is shutting down
2024/04/12 11:02:35 Get "http://127.0.0.1:10246/nginx_status": dial tcp 127.0.0.1:10246: connect: connection refused
W0412 11:02:35.895853       7 nginx_status.go:171] unexpected error obtaining nginx status info: Get "http://127.0.0.1:10246/nginx_status": dial tcp 127.0.0.1:10246: connect: connection refused
I0412 11:02:38.986048       7 sigterm.go:47] "Exiting" code=0

原因

高トラフィック下では、NGINX のワーカープロセスが 100% に近い CPU 使用率に達し、ヘルスチェックプローブに時間内に応答するためのリソースが不足する可能性があります。

解決策

NGINX Ingress Controller の Pod のレプリカ数を増やして トラフィックを分散させ、Pod ごとの CPU 負荷を軽減します。

cert-manager が証明書の発行に失敗した場合の対処法

これは、Web アプリケーションファイアウォール (WAF) が有効になっている場合に発生します。WAF は、cert-manager がドメイン所有権の検証に使用する HTTP-01 リクエストをインターセプトし、証明書の発行を妨げる可能性があります。

これを解決するには、一時的に WAF を無効にしHTTP-01 チャレンジを成功させます。

重要

WAF を無効にする前に、アプリケーションを不必要なリスクに晒さないよう、セキュリティ上の潜在的な影響を十分に評価する必要があります。

高トラフィック下で NGINX が大量のメモリを使用する原因

症状

高トラフィック下で、NGINX Ingress Controller のメモリ使用量が大幅に増加し、最終的にメモリ不足 (OOM) イベントが発生します。

原因

コントローラープロセスが過剰なメモリを消費する場合、問題は Prometheus のメトリクス収集におけるメモリリークである可能性が高いです。

これは、NGINX Ingress Controller バージョン 1.6.4 の既知の問題 であり、多くの場合、nginx_ingress_controller_ingress_upstream_latency_seconds のような高カーディナリティメトリクスに関連しています。

解決策

この問題が修正されている 最新バージョンの NGINX Ingress Controller に アップグレード します高トラフィック環境向けに NGINX Ingress を設定する 場合は、メモリ使用量に大きな影響を与えるメトリクスを監視します。

コミュニティリソース:

NGINX Ingress Controller のアップグレードが停滞した場合の対処

症状

NGINX Ingress コントローラーの段階的なロールアウト (カナリアアップグレード) 中に、処理が検証フェーズで停止します。 Operation is forbidden for task in a failed state が表示される場合があります。

原因

アドオンのアップグレードタスクが 4 日間の有効期限を超過した後にシステムによってクリーンアップされると、この問題が発生します。この問題を解決するには、アドオンの Deployment 状態を手動でリセットする必要があります。

注: アドオンがすでにアップグレードの最終 Released フェーズに到達している場合、対応は不要です。現在のタスクがタイムアウトし、自動的に終了するまで待機してください。

手順

Deployment をリセットし、アップグレードを続行します。

  1. Deployment マニフェストを開いて編集します:

    kubectl edit deploy -n kube-system nginx-ingress-controller
  2. エディターで spec セクション内の次のフィールドを見つけ、以下のとおりデフォルト値に戻します:

    • spec.minReadySeconds: 0

    • spec.progressDeadlineSeconds: 600

    • spec.strategy.rollingUpdate.maxSurge: 25%

    • spec.strategy.rollingUpdate.maxUnavailable: 25%

    image

  3. 変更を保存して、エディターを終了します。

想定される結果

保存後、アドオンのアップグレードが自動的に再開されます。古い Pod が置き換えられ、段階的なロールアウトが完了します。

重要

アップグレードはバックグラウンドで完了しますが、ACK コンソールの [Add-ons] ページに表示されるアドオンのステータスは、最大 2 週間 Upgrading と表示され、その後に自動的に解消される場合があります。

コントローラーバージョン 1.10 以降、チャンク転送エンコーディング (Transfer-Encoding: chunked) が機能しなくなった理由

症状

アプリケーションが Transfer-Encoding: chunked を設定しており、コントローラーのログに重複ヘッダーに関するエラーが表示されます。

原因

v1.10 以降、基盤となる NGINX のバージョン (詳細については「NGINX 更新ログ」をご参照ください) では、より厳格な HTTP 応答検証が実施されています。バックエンドが複数の Transfer-Encoding: chunked ヘッダーを返す場合、NGINX は応答を無効として扱うようになりました。

解決策

バックエンドが単一の Transfer-Encoding: chunked ヘッダーのみを返すようにしてください。詳細については、「GitHub Issue #11162」をご参照ください。

アクセス制御のための IP 許可リスト / 拒否リストの設定

NGINX Ingress は、Ingress リソースのアノテーション、またはグローバル ConfigMap のキーと値のペアを使用した IP ベースのアクセス制御をサポートしています。

  • ConfigMap: すべての Ingress にグローバルに適用されます。

  • Ingress アノテーション: 特定の Ingress リソースのみに適用されます。

説明

Ingress リソースのアノテーションは、常にグローバル ConfigMap 設定よりも優先されます。

Ingress マニフェストで以下のアノテーションを使用します。

アノテーション

説明

nginx.ingress.kubernetes.io/denylist-source-range

クライアント IP アドレスまたは CIDR ブロックの拒否リストです。複数の値をカンマ (,) 区切りで指定できます。

nginx.ingress.kubernetes.io/whitelist-source-range

クライアント IP アドレスまたは CIDR ブロックの許可リストです。複数の値をカンマ (,) 区切りで指定できます。

詳細については、公式ドキュメントの「拒否ソース範囲」および「許可ソース範囲」をご参照ください。

NGINX Ingress v1.2.1 におけるdefaultBackend の既知の問題

現象

Ingress リソースで defaultBackend を設定すると、デフォルトサーバーの defaultBackend 設定が誤ってオーバーライドされる場合があります。

解決策

これは既知の問題です (「GitHub Issue #8823」をご参照ください)。NGINX Ingress Controller をバージョン 1.3 以降にアップグレードしてください。詳細については、「NGINX Ingress Controllerのアップグレード」をご参照ください。

Connection reset by peer エラーが curl 使用時に発生する理由

症状

curl を使用して HTTP 経由で外部のパブリックサービスにアクセスすると、 curl: (56) Recv failure: Connection reset by peer エラーが返されます。

原因

通常、プレーンテキストの HTTP リクエストにネットワーク中間者が機密と判断するキーワードが含まれていると、接続がブロックされたりリセットされたりするため、このエラーが発生します。

解決策

Ingress ルートに TLS 証明書を設定し、すべての通信で HTTPS を使用して、トラフィックが暗号化されるようにしてください。

パス マッチングの優先度の仕組み

NGINX の正規表現パスは、定義された順序で評価され、最初にマッチしたものが使用されます。より正確なパス マッチングを可能にするために、ingress-nginx はまずすべてのパスを長さの降順でソートし、次にそれらを nginx.conf ファイル内の location ブロックとして書き込みます。

詳細については、「Ingress パスマッチング」をご参照ください。

非べき等なリクエストがリトライされない理由

バージョン 1.9.13 以降、NGINX はエラーが発生した際に、非べき等なリクエスト (POSTLOCK、および PATCH) をリトライしません

以前の動作に戻すには、nginx-configuration ConfigMap で retry-non-idempotent: "true" をセットしてください。

大きなクライアントヘッダーやクッキーを含むリクエストへの対応

症状

NGINX Ingress 経由でサービスにアクセスすると、Request Header Or Cookie Too Large というメッセージとともに 400 Bad Request エラーが返されます。

原因

このエラーは、クライアントヘッダーまたはクッキーのサイズが、NGINX で設定されているデフォルトのバッファサイズを超えた場合に発生します。

解決策

関連するバッファサイズを増やしてください。主な 2 つのパラメーターは次のとおりです:

  • client-header-buffer-size:クライアントヘッダーのバッファサイズ。デフォルトは 1k です。

  • large-client-header-buffers:大きなクライアントヘッダーを読み取るためのバッファの最大数とサイズ。デフォルトは 4 8k です。

nginx-configuration ConfigMap を編集して、これらのパラメーターを変更します。
kubectl edit cm -n kube-system nginx-configuration

client-header-buffer-size: "16k"
large-client-header-buffers: "4 32k" 

変更を適用した後、NGINX 設定に反映されたことを確認してください。いずれかの Ingress コントローラー Pod 内の nginx.conf ファイルを調べることができます。
kubectl exec <nginx-ingress-pod> -n kube-system -- cat /etc/nginx/nginx.conf

Exact または Prefix のパスが正規表現として扱われるのはなぜですか

特定の hostいずれかの Ingress ルールが use-regex または rewrite-target アノテーションを使用する場合、その同じ host 配下の すべてのパス で、大文字と小文字を区別しない正規表現照合の使用が強制されます。 これは、NGINX Ingress Controller の現在の実装ロジックです。 「コミュニティドキュメント」をご参照ください。

image.png

Ingress が多数存在するクラスターで Ingress を追加する際に、検証 Webhook の応答が遅い理由

これは NGINX Ingress Controller V1.12 以前の既知のパフォーマンス問題です。検証 Webhook は既存のすべての Ingress に対してフルチェックを実行するため、大規模な環境では時間がかかる場合があります。詳細については、「#11115」をご参照ください。

解決策

  • オプション 1:Webhook のタイムアウトを増やす
    応答時間が長くなることを許容でき、インクリメンタル検証を使用しない場合は、検証 Webhook のタイムアウトを増やしてください。デフォルトは 10s です。

    • アクションingress-nginx-admission という名前の validatingwebhookconfigurations オブジェクトを編集して、timeoutSeconds の値を増やしてください (最大 30s)。

    • 注意:この値は、アドオンのアップグレード中にオーバーライドされます。

  • オプション 2:インクリメンタル検証を有効にする
    NGINX Ingress Controller の Deployment を変更して、起動引数 --disable-full-test=true を追加してください。

    • 影響:このフラグを使用すると、Webhook は新しい Ingress ルールに対してのみインクリメンタル検証を実行します。これにより検証速度は大幅に向上しますが、異なる Ingress リソース間の競合は 検出されません

スニペット使用時の注意

問題

複数の Ingress リソースで、同一ドメインに対して server-snippet アノテーションを設定すると、ログに警告が出力され、最初のスニペットのみが適用されます。これにより、想定外の動作が発生する可能性があります。

ログ警告の例:

W0619 14:58:49.323721       7 controller.go:1314] Server snippet already configured for server "test.example.com", skipping (Ingress "default/test.example.com")
W0619 14:58:49.323727       7 controller.go:1314] Server snippet already configured for server "test.example.com", skipping (Ingress "default/test.example.com")
W0619 14:58:49.323734       7 controller.go:1314] Server snippet already configured for server "test.example.com", skipping (Ingress "default/test.example.com")

この警告は、test.example.com のスニペットがすでに定義されており、他の Ingress リソースからの後続の定義が無視されていることを示します。

Secret に設定した TLS 証明書が機能しない理由

コントローラーログの確認

NGINX Ingress Controller Pod のログで、証明書関連のエラーを確認してください。

kubectl -n kube-system logs <nginx-ingress-controller-pod-name> | grep "Error getting SSL certificate"

以下のようなエラーが表示された場合、証明書 Secret の読み込みに問題があることを示しています(ここで、 xxxx はご使用の Secret の名前です)。

Error getting SSL certificate "xxxx": local SSL certificate xxxx tls was not found. Using default certificate

このエラーの主な原因は次の 3 つです:

原因 1:Secret が存在しない

ログメッセージで指定されている Secret が、正しい名前空間に実際に存在することを確認してください。

原因 2:証明書と秘密鍵が一致しない

Secret に格納されている tls.crt (公開キー) と tls.key (秘密キー) は、対応するペアである必要があります。

  • kubectl create secret tls を使用して、一致しないペアで tls Secret を作成しようとすると、コマンドは失敗し、次のエラーが表示されます。
    error: tls: private key does not match public key

  • 既存の Secret で不一致を確認するには、次のスクリプトを実行してください:

    export SECRET_NAME=<Your Secret Name>
    export NAME_SPACE=<Your Secret Namespace>
    diff <(kubectl get secret $SECRET_NAME -n $NAME_SPACE -o jsonpath='{.data.tls\.crt}' | base64 -d | openssl x509 -noout -modulus | openssl md5) <(kubectl get secret $SECRET_NAME -n $NAME_SPACE -o jsonpath='{.data.tls\.key}' | base64 -d | openssl rsa -noout -modulus | openssl md5) && echo "Certificate and Key match" || echo "Certificate and Key do not match"

    このコマンドは、証明書と鍵のモジュラスを比較します。鍵と証明書が一致しない場合、出力には 2 つの異なるハッシュ値とメッセージ Certificate and Key do not match が表示されます。有効なキーペアで Secret を更新します。

    root@Aliyun ~/ssl # export SECRET_NAME=test
    root@Aliyun ~/ssl # export NAME_SPACE=default
    root@Aliyun ~/ssl # diff <(kubectl get secret $SECRET_NAME -n $NAME_SPACE -o jsonpath='{.data.tls\.crt}' | base64 -d | openssl x509 -noout -modulus | openssl md5) <(kubectl get secret $SECRET_NAME -n $NAME_SPACE -o jsonpath='{.data.tls\.key}' | base64 -d | openssl rsa -noout -modulus | openssl md5) && echo "Certificate and Key match" || echo "Certificate and Key do not match"
    1c1
    < (stdin)= 66a309089e87e32d1b6fe361ebf8cd88
    ---
    > (stdin)= 12e15c5fe35585b6fd9920abc8e8706d
    Certificate and Key do not match

原因 3:同一ドメインの別の Ingress における TLS エントリの設定ミス

同じドメインについて、複数の Ingress リソースにまたがって tls セクションを定義している場合、いずれか 1 つの設定にエラーがあるだけで、証明書が正しく読み込まれない可能性があります。ドメインを参照するすべての Ingress リソースを確認し、設定ミスを修正してください。

証明書を 更新 した後も、証明書の有効期限切れアラートが表示され続ける事象

原因

古いバージョンには、証明書の更新後に nginx_ingress_controller_ssl_expire_time_seconds メトリクスが更新されず、古い certificate expired アラートが発生する既知のバグがあります。

解決策

NGINX Ingress Controller の Pod のローリング再起動 を実行して、古いメトリクスをクリアします。

この問題は新しいバージョンで解決されているため、NGINX Ingress Controller をバージョン 1.11.4 以降アップグレードすることを推奨します。

特定バージョンの NGINX Ingress Controller のデフォルト設定の確認方法

NGINX Ingress Controller の設定パラメーターのデフォルト値は、バージョンによって変わります。たとえば、use-gzip はバージョン 0.35.0 以前ではデフォルトで有効でしたが、バージョン 1.0.0 以降ではデフォルトで無効です。

特定バージョンにおける特定パラメーターのデフォルト動作を確認するには、公式ドキュメントの該当バージョンのブランチにある configmap.md ファイルをご参照ください。

例: controller-v1.8.0 の場合、ページ左側のバージョンセレクターを使用して他のバージョンに切り替えてください。