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を使用してノードへの負荷分散を既に行っているため、構成に何が追加されるのかわかりません。
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サービスプロキシ)がある可能性があります。