web-dev-qa-db-ja.com

nginx use-proxy-protocol with Kubernetes cluster

NGINXを実行しているセルフホストサーバーに外部ロードバランサーを備えたKubernetesクラスターがあります。クライアントのproxy_protocolを取得するためにreal_ipをアクティブ化しようとしましたが、NGINXログは

2020/05/11 14:57:54 [error] 29614#29614: *1325 broken header: "▒▒▒▒▒▒▒Ωߑa"5▒li<c▒*▒ ▒▒▒s▒       ▒6▒▒▒▒▒X▒▒o▒▒▒E▒▒i▒{ ▒/▒0▒+▒,̨̩▒▒ ▒▒
▒▒/5▒" while reading PROXY protocol, client: 51.178.168.233, server: 0.0.0.0:443

ここに私のNGINX構成ファイルがあります:

worker_processes 4;
worker_rlimit_nofile 40000;

events {
    worker_connections 8192;
}

stream {

    upstream rancher_servers_http {
        least_conn;
        server <IP_NODE_1>:80 max_fails=3 fail_timeout=5s;
        server <IP_NODE_2>:80 max_fails=3 fail_timeout=5s;
        server <IP_NODE_3>:80 max_fails=3 fail_timeout=5s;
    }
    server {
        listen     80;
        proxy_protocol on;
        proxy_pass rancher_servers_http;
    }

    upstream rancher_servers_https {
        least_conn;
        server <IP_NODE_1>:443 max_fails=3 fail_timeout=5s;
        server <IP_NODE_2>:443 max_fails=3 fail_timeout=5s;
        server <IP_NODE_3>:443 max_fails=3 fail_timeout=5s;
    }

    server {
        listen     443 ssl proxy_protocol;
        ssl_certificate /certs/fullchain.pem;
        ssl_certificate_key /certs/privkey.pem;
        proxy_pass rancher_servers_https;
        proxy_protocol on;
    }
}

これは、イングレスコントローラーのconfigmapです。

apiVersion: v1
data:
  compute-full-forwarded-for: "true"
  proxy-body-size: 500M
  proxy-protocol: "true"
  use-forwarded-headers: "true"
kind: ConfigMap
metadata:
  annotations:
    kubectl.kubernetes.io/last-applied-configuration: '{"apiVersion":"v1","data":null,"kind":"ConfigMap","metadata":{"annotations":{},"labels":{"app":"ingress-nginx"},"name":"nginx-configuration","namespace":"ingress-nginx"}}'
  creationTimestamp: "2019-12-09T13:26:59Z"
  labels:
    app: ingress-nginx
  name: nginx-configuration
  namespace: ingress-nginx

proxy_protocolディレクティブを追加する前はすべて正常に機能していましたが、今ではこれらすべてのbroken headersエラーが発生し、connection resetエラーが発生しないと、イングレスの背後にあるサービスに到達できません。

私の設定の何が問題になっているのですか?

Tcpリバースプロキシの代わりにhttpリバースプロキシを使用する必要がありますか?

ありがとうございました。


編集

また、クラスターにLoadBalancerタイプのサービスがないことも言う必要があります。持っておくべき? Metallbについて考えていますが、nginxを使用してノードへの負荷分散を既に行っているため、構成に何が追加されるのかわかりません。

2
MHogge

Nginxでは、着信要求または発信要求でproxy_protocolを使用するかどうかを指定できますが、2つを混同しています。

incoming接続でproxy_protocolを使用するには、次のようにlisten行にproxy_protocolを追加する必要があります。

listen     443 ssl proxy_protocol;

outgoing接続でproxy_protocolを使用するには、次のようにスタンドアロンのproxy_protocolディレクティブを使用する必要があります。

proxy_protocol on;

それらはnotと同じです。ロードバランサーでは、受信接続は、プロキシプロトコルを話さないブラウザーからのものです。 kubernetesクラスターのnginx-ingressへの送信リクエストにのみプロキシプロトコルが必要です。

したがって、listenディレクティブからproxy_protocol引数を削除すれば、機能するはずです。

さらに、nginx-ingress構成にuse-forwarded-headers: "false"が必要です。 X-Forwarded-For&coを使用するかどうかを制御します。 incoming接続のヘッダー(nginx-ingressの観点から、つまりoutgoingロードバランサーから))、およびこれらの代わりにプロキシプロトコルを使用しているヘッダー。これを有効にすると、ユーザーはX-Forwarded-Forを指定してIPを偽装できる可能性があり、これはセキュリティ上の問題となる可能性があります。 (nginx-ingressがプロキシプロトコルよりもヘッダーを優先する場合のみ、これはわかりません)

余談ですが、nginx-ingress自体はすでにすべてのポッド間のトラフィックの負荷を分散しています。このアーキテクチャでは、おそらく2つの「レイヤー」のロードバランサーを実行しています。単純化したい場合は、nginx-ingressを単一のノードで(たとえば、nodeSelectorを使用して)実行し、すべてのトラフィックをそのノードに送信するだけです。ロードバランサーを専用のマシンに保持したい場合は、4番目のマシンをクラスターに参加させて、それがnginx-ingressを実行することを確認します(汚染と許容)。

また、hostNetwork:trueでnginx-ingressを実行していることを確認してください。そうでない場合は、まだ別のバランス層(kube-proxy、kubernetesサービスプロキシ)がある可能性があります。

2
Dirbaio