nginx 使用代理协议与 Kubernetes 集群

MHo*_*gge 4 nginx kubernetes

我在运行 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
Run Code Online (Sandbox Code Playgroud)

这是我的 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;
    }
}
Run Code Online (Sandbox Code Playgroud)

这是我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
Run Code Online (Sandbox Code Playgroud)

在我添加proxy_protocol指令之前一切正常,但现在我遇到了所有这些broken headers错误,而且我无法在没有connection reset错误的情况下访问入口后面的任何服务。

我的配置可能有什么问题?

我应该使用 http 反向代理而不是 tcp 反向代理吗?

谢谢你。


编辑

我还应该说,LoadBalancer我的集群中没有任何类型的服务。我应该有一个吗?我正在考虑 Metallb,但我不确定它将添加到我的配置中,因为我已经使用 nginx 对节点进行了负载平衡。

Dir*_*aio 5

Nginx 允许您指定是否在传入或传出请求中使用 proxy_protocol,但您将两者混淆了。

要在传入连接中使用 proxy_protocol ,您必须像这样添加proxy_protocollisten行中:

listen     443 ssl proxy_protocol;
Run Code Online (Sandbox Code Playgroud)

要在传出连接中使用 proxy_protocol ,您必须使用独立proxy_protocol指令,如下所示:

proxy_protocol on;
Run Code Online (Sandbox Code Playgroud)

它们一样。在负载均衡器中,传入连接来自浏览器,它们不使用代理协议。你只需要在你的传出请求中使用代理协议,到你的 kubernetes 集群中的 nginx-ingress。

因此,proxy_protocollisten指令中删除参数,它应该可以工作。

此外,您希望use-forwarded-headers: "false"在 nginx-ingress 配置中。那控制是否使用X-Forwarded-For& co。传入连接中的标头(从 nginx-ingress 的角度来看,即从您的负载均衡器传出),并且您在这些连接中使用代理协议而不是标头。启用它后,您的用户可能能够通过指定 X-Forwarded-For 来欺骗 IP,这可能是一个安全问题。(仅当 nginx-ingress 优先于代理协议的标头时,我不确定)

旁白:nginx-ingress 本身已经在所有 pod 之间负载平衡流量。对于您的架构,您正在运行两个“层”的负载均衡器,这可能是不必要的。如果您想简化,请强制 nginx-ingress 在单个节点上运行(nodeSelector例如)并将所有流量发送到该节点。如果您想将负载均衡器保留在专用机器上,您可以将第 4 台机器加入集群并确保它只运行 nginx-ingress(带有污点和容忍)。

另外,请确保您使用 hostNetwork: true 运行 nginx-ingress,否则您可能还有另一层平衡(kube-proxy,kubernetes 服务代理)