TLS、構成、パフォーマンス、アップグレードに関する NGINX Ingress Controller の一般的な問題を解決します。
NGINX Ingress Controller の以前のバージョンにおける既知の問題
以前のバージョンには、以下の既知の問題があります。安定性のために、最新バージョンにアップグレードしてください。
-
Ingress の defaultBackend パラメーター値が NGINX Ingress Controller のグローバル構成を上書きする
影響を受けるバージョン: 1.2.1-aliyun.1 およびそれ以前。
解決策: NGINX Ingress Controller をバージョン 1.5.1-aliyun.1 以降にアップグレードします。
-
nginx-cfg-xx の一時設定ファイルがクリアされず、ディスクがいっぱいになる可能性がある
影響を受けるバージョン: 1.10.2-aliyun.1 およびそれ以前。
解決策: NGINX Ingress Controller をバージョン 1.10.4-aliyun.1 以降にアップグレードします。
-
原因:
client-body-buffer-sizeの値が 32 ビット整数のストレージ制限を超えているためです。解決策:
client-body-buffer-sizeを200Mのような小さい値に設定します。
サポートされている TLS バージョン
Ingress-nginx は TLS 1.2 と TLS 1.3 をサポートしています。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 を指定します。
server-tokens: "false"
ssl-ciphers: '@SECLEVEL=0:ECDHE-ECDSA-AES128-GCM-SHA256:E...
ssl-protocols: TLSv1 TLSv1.1 TLSv1.2 TLSv1.3
ssl-redirect: "false"
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"
ssl-protocols: "TLSv1 TLSv1.1 TLSv1.2 TLSv1.3"
リクエストヘッダーはバックエンドサーバーに渡されるか
デフォルトでは、ingress-nginx はレイヤー 7 のリクエストヘッダーをバックエンドサーバーに渡しますが、Mobile Version のような非標準の HTTP ヘッダーは除外します。これらのヘッダーを保持するには、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-nginx は X-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 に到達する前に複数のアップストリームプロキシサーバーを通過する場合、proxy-real-ip-cidr フィールドを nginx-configuration ConfigMap に追加し、proxy-real-ip-cidr をアップストリームプロキシサーバーの CIDR ブロック (カンマ区切り) に設定する必要があります。詳細については、「WAF の使用」をご参照ください。
proxy-real-ip-cidr: "0.0.0.0/0,::/0"
NGINX Ingress がクラシックロードバランサー (CLB) インスタンスの背後で空の X-Forwarded-For ヘッダーを受信する IPv6 シナリオでは、CLB でプロキシプロトコルを有効にしてクライアント IP を取得します。詳細については、「CLB レイヤー 4 リスナーを介したクライアント IP アドレスの取得」をご参照ください。
HSTS の設定方法
HTTP Strict Transport Security (HSTS) はデフォルトで有効になっています。ブラウザが初めてプレーン HTTP 経由でサービスにアクセスすると、サーバーは HSTS レスポンスをトリガーします。開発者ツールでは、Non-Authoritative-Reason: HSTS レスポンスヘッダーが表示されます。HSTS 互換のブラウザは、後続のリクエストで自動的に HTTPS に切り替わり、その結果 307 Internal Redirect ステータスコードが返されます。
General
Request URL: http://xxx.bizprodmng xxx .com/crmhome/pageListQuery.json?pageNum=1&pageName=&pageSize=20&platform=
Request Method: GET
Status Code: 307 Internal Redirect
Response Headers
Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: http://zhbyak xxx net:3001
Location: https://bizprodmng xxx .com/crmhome/pageListQuery.json?pageNum=1&pageName=&pageSize=20&platform=
Non-Authoritative-Reason: HSTS
Request Headers
Provisional headers are shown
Referer: http://zhbyak xxx .net:3001/searchPage
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.71 Saf...
Query String Parameters
pageNum: 1
pageName:
ブラウザが後続のリクエストを自動的に HTTPS にアップグレードするのを防ぐには、nginx-ingress-controller の HSTS を無効にします。詳細については、「HSTS」をご参照ください。
ブラウザは HSTS 構成をキャッシュします。nginx-ingress-controller の HSTS を無効にした後、手動でブラウザのキャッシュをクリアしてください。
サポートされている書き換えルール
Ingress-nginx は、単純な 書き換えルールのみをサポートします。複雑な書き換えルールには、以下を使用します。
-
configuration-snippet: このアノテーションを Ingress の location 構成に追加します。
-
server-snippet: Ingress の server 構成に追加します。
他のスニペットはグローバル構成を追加します。詳細については、「main-snippet」をご参照ください。
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
Container Service for Kubernetes (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 をアップグレードする前に replicas を 5 に設定した場合、アップグレード後にデフォルト値の 2 に戻ります。
レイヤー 4 からレイヤー 7 のリスナーへの切り替え方法
デフォルトでは、ingress-nginx の LoadBalancer は TCP ポート 80 と 443 をリッスンします。プロトコルを HTTP または HTTPS に変更することで、レイヤー 7 リスナーに切り替えます。
リスナーの変更中にサービスの中断が発生します。この操作はオフピーク時に実行してください。
-
証明書を作成し、証明書 ID (cert-id) を記録します。詳細については、「Certificate Management Service の証明書を使用する」をご参照ください。
-
アノテーションを介して、Ingress が使用する LoadBalancer リスナーをレイヤー 4 からレイヤー 7 に変更します。
-
ACK コンソールにログインします。左側のナビゲーションウィンドウで、クラスターリスト をクリックします。
-
クラスターリスト ページで、クラスターの名前をクリックします。左側のナビゲーションウィンドウで、 をクリックします。
-
[サービス] ページの上部で、[名前空間] を
kube-systemに設定します。ingress-nginx-lbサービスを見つけ、[アクション] 列の [YAML の編集] をクリックします。 -
[YAML の編集] パネルで、
https(ポート 443) という名前のポートのtargetPortを80に更新します。- 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}"
-
-
結果を確認します。
-
[サービス] ページで、[ingress-nginx-lb] サービスを見つけ、
アイコンを [タイプ] 列内でクリックします。 -
[リスナー] タブをクリックします。[フロントエンドプロトコル/ポート] 列に
HTTP:80とHTTPS:443の両方が表示されている場合、LoadBalancer のリスナーはレイヤー 4 からレイヤー 7 に変更されています。
-
既存の SLB インスタンスを ack-ingress-nginx で使用する方法
-
ACK コンソールにログインします。左側のナビゲーションウィンドウで、 をクリックします。
-
[アプリカタログ] タブで、クラスターのバージョンに基づいて ack-ingress-nginx または ack-ingress-nginx-v1 を選択します。
-
クラスターが Kubernetes 1.20 以前を実行している場合は、ack-ingress-nginx を選択します。
-
クラスターが Kubernetes 1.20 より後のバージョンを実行している場合は、ack-ingress-nginx-v1 を選択します。
-
-
Ingress Controller をデプロイします。詳細については、「トラフィック分離のために複数の Ingress Controller をデプロイする」をご参照ください。
[パラメーター] ウィザードページで:
-
controller.service.annotations セクションのすべてのアノテーションを削除します。
# 追加の内部 SLB を有効にする internal: enabled: false annotations: service.beta.kubernetes.io/alibaba-cloud-loadbalancer-address-type: "intranet" service.beta.kubernetes.io/alibaba-cloud-loadbalancer-spec: "slb.s1.small" -
新しいアノテーションを追加します。
# 使用したい SLB インスタンスを指定します。 service.beta.kubernetes.io/alibaba-cloud-loadbalancer-id: "${YOUR_LOADBALANCER_ID}" # リスナーを上書きします。 service.beta.kubernetes.io/alibaba-cloud-loadbalancer-force-override-listeners: "true"
-
-
[OK] をクリックして Ingress Controller をデプロイします。
-
Ingress Controller がデプロイされた後、Ingress クラスを設定します。詳細については、「トラフィック分離のために複数の Ingress Controller をデプロイする」をご参照ください。
複数の Ingress Controller からアクセスログを収集する方法
前提条件
-
Logtail がクラスターにインストールされていること (クラスター作成時にデフォルトでインストールされます。そうでない場合は、「ACK クラスターからコンテナログを収集する」をご参照ください)。
-
デフォルトの Ingress Controller でログ収集が有効になっていること。
-
他の Ingress Controller の Pod のラベルが取得されていること。詳細については、「Docker コンテナのラベルと環境変数を取得する方法」をご参照ください。
手順:
-
ACK コンソールにログインします。左側のナビゲーションウィンドウで、[クラスター] をクリックします。
-
[クラスター] ページで、対象のクラスター名をクリックし、左側のナビゲーションウィンドウで [クラスター情報] をクリックします。
-
[クラスター情報] ページで、[基本情報] タブをクリックし、[クラスターリソース] セクションの [Log Service プロジェクト] の右側にあるハイパーリンクをクリックします。
-
[Logstore] ページで、Logstore を作成します (詳細については、「Logstore の管理」をご参照ください)。重複収集を避けるために、Ingress Controller ごとに個別の Logstore を作成します。
-
Logstore には、それを使用する Ingress Controller の名前を付けます。
-
表示されるメッセージで、[データ収集ウィザード] をクリックします。
-
-
[クイックデータインポート] ダイアログボックスで、 を選択します。[注意] メッセージで、[続行] をクリックします。[Kubernetes Stdout and Stderr] ページで、次の操作を実行します。
-
[マシングループの作成] ステップで、[既存のマシングループを使用] をクリックします。
-
[マシングループ構成] ステップで、
k8s-group-<YOUR_CLUSTER_ID>マシングループを選択し、>をクリックしてマシングループを [適用済みサーバーグループ] セクションに移動します。その後、[次へ] をクリックします。 -
[Logtail 設定] ステップでは、
-
[他の構成をインポート] をクリックします。クラスターが使用するプロジェクトと
k8s-nginx-ingress構成を選択します。その後、[OK] をクリックします。 -
[グローバル構成] セクションで、構成名を変更します。[コンテナフィルタリング] オプションを有効にし、Ingress Controller コンテナのラベルをキーと値のペアとして追加します。
-
[プロセッサー構成] セクションで、[プロセッサー名] 列の [フィールドの抽出 (正規表現モード)] をクリックして、ログ処理フィールドを表示します。
説明異なる NGINX Ingress Controller が異なるログフォーマットを使用する場合、対応するログフィールドキーと正規表現を設定します。
-
-
[クエリと分析の構成] ステップで、[次へ] をクリックします。
-
[終了] ステップで、[ログの照会] をクリックして収集されたログを表示します。
-
nginx-ingress-controller の TCP リスナーを有効にする方法
デフォルトでは、Ingress は HTTP および HTTPS リクエストのみを転送します。ingress-nginx を構成して、関連する ConfigMap で指定されたポートで外部 TCP リクエストを転送します。
-
tcp-echo テンプレートを使用して、サービスとデプロイメントをデプロイします。
-
次のテンプレートを使用して ConfigMap を作成します。
-
tcp-services-cm.yamlファイルを変更し、変更を保存して終了します。apiVersion: v1 kind: ConfigMap metadata: name: tcp-services namespace: kube-system data: 9000: "default/tcp-echo:9000" # この構成は、ポート 9000 で受信した外部 TCP リクエストがデフォルト名前空間の tcp-echo サービスに転送されることを示します。 9001: "default/tcp-echo:9001" -
ConfigMap を作成します。
kubectl apply -f tcp-services-cm.yaml
-
-
nginx-ingress-controllerが使用するサービスに TCP ポートを追加し、変更を保存して終了します。kubectl edit svc nginx-ingress-lb -n kube-systemapiVersion: 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 -
構成を確認します。
-
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 -
ncを使用して、ポート 9000 の IP アドレスに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 テーブルに保存します。
リクエストフロー
-
クライアントが HTTPS リクエストを開始すると、TLS ハンドシェイクのサーバ名表示 (SNI) 拡張にリクエストされたホスト名を含めます。
-
NGINX Ingress Controller はこのリクエストを受信し、
certificate.call()関数を使用して、Lua マッピングテーブルで SNI ホスト名を検索します。 -
一致する証明書が見つかった場合、それがクライアントに提示され、TLS ハンドシェイクが完了します。
-
リクエストされたホスト名に一致する証明書が見つからない場合、コントローラーはデフォルトの自己署名
fake証明書を提示します。
このロジックを実装する関連する NGINX 構成を以下に示します。
## Start server _
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()
}
...
}
## Start server 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 は Online Certificate Status Protocol (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出力を確認します。
-
Subject:
CN = example.comのような形式の Common Name (CN) フィールドを探します。 -
Subject Alternative Name (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 ワーカープロセスの CPU 使用率が 100% 近くに達し、ヘルスチェックプローブに時間内に応答するためのリソースが不足することがあります。
解決策
NGINX Ingress Controller の Pod レプリカ数を増やして、トラフィックを分散させ、Pod ごとの CPU 負荷を軽減します。
証明書の発行に cert-manager が失敗した場合、どうすればよいですか?
これは、Web Application Firewall (WAF) が有効になっている場合に発生します。WAF は、cert-manager がドメインの所有権の検証に使用する HTTP01 リクエストをインターセプトし、証明書発行を妨げる可能性があります。
これを解決するには、一時的に WAF を無効にして、HTTP-01 チャレンジが成功するようにします。
WAF を無効にする前に、アプリケーションを不必要なリスクにさらさないように、潜在的なセキュリティへの影響を十分に評価する必要があります。
高トラフィック下で NGINX が大量のメモリを使用する理由
症状
高トラフィック下で、NGINX Ingress Controller のメモリ使用量が大幅に増加し、最終的に Out-of-Memory (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 Controller の段階的なロールアウト (カナリアアップグレード) 中に、プロセスが検証フェーズで停止します。Operation is forbidden for task in a failed state というメッセージが表示されることがあります。
原因
これは、アドオンのアップグレードタスクが 4 日間の有効期限を超えた後、システムによってクリーンアップされた場合に発生します。これを解決するには、アドオンのデプロイメント状態を手動でリセットします。
注意: アドオンがすでにアップグレードの最終的な Released フェーズに達している場合は、何もする必要はありません。現在のタスクがタイムアウトして自動的に終了するのを待つだけです。
手順
Deployment をリセットし、アップグレードを続行させます。
-
Deploymentマニフェストを編集用に開きます。kubectl edit deploy -n kube-system nginx-ingress-controller -
エディターで、
specセクションの下にある次のフィールドを見つけ、以下に示すようにデフォルト値に戻します。-
spec.minReadySeconds: 0 -
spec.progressDeadlineSeconds: 600 -
spec.strategy.rollingUpdate.maxSurge: 25% -
spec.strategy.rollingUpdate.maxUnavailable: 25%
spec: minReadySeconds:0 progressDeadlineSeconds: 600 replicas: 2 revisionHistoryLimit: 10 selector: matchLabels: app: ingress-nginx strategy: rollingUpdate: maxSurge: 25% maxUnavailable: 25% -
-
変更を保存してエディターを終了します。
期待される結果
保存後、アドオンのアップグレードが自動的に再開され、古い Pod が置き換えられて段階的なロールアウトが完了します。
アップグレードはバックグラウンドで完了しますが、ACK コンソールの [アドオン] ページのアドオンステータスは、自動解決されるまで最大 2 週間「アップグレード中」と表示される場合があります。
コントローラーバージョン 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 マニフェストで次のアノテーションを使用します。
|
アノテーション |
説明 |
|
|
クライアント IP アドレスまたは CIDR ブロックの拒否リスト。複数の値をカンマ (,) で区切って指定できます。 |
|
|
クライアント IP アドレスまたは CIDR ブロックの許可リスト。複数の値をカンマ (,) で区切って指定できます。 |
公式ドキュメントの Denylist Source Range および Whitelist Source Range をご参照ください。
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 はエラーが発生した場合に非冪等リクエスト (POST、LOCK、PATCH) をリトライしません。
以前の動作に戻すには、nginx-configuration ConfigMap で retry-non-idempotent: "true" を設定します。
大きなクライアントヘッダーまたは Cookie を持つリクエストをサポートする方法
症状
NGINX Ingress 経由でサービスにアクセスすると、400 Bad Request エラーと Request Header Or Cookie Too Large というメッセージが表示されます。
原因
このエラーは、クライアントのリクエストヘッダーまたは Cookie のサイズが 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 Controller Pod の 1 つの内部にある 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 の現在の実装ロジックです。詳細については、「コミュニティドキュメント」をご参照ください。

多数の 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を使用して、一致しないペアでtlsSecret を作成しようとすると、コマンドは次のエラーで失敗します。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.11.4 ではデフォルトで無効になっています。
特定のバージョンの特定のパラメーターのデフォルトの動作を見つけるには、公式ドキュメントの対応するバージョンブランチにある configmap.md ファイルを参照してください。
例: controller-v1.8.0 の場合、ページの左側にあるバージョンセレクターを使用して他のバージョンに切り替えます。