nginx 使用代理协议与 Kubernetes 集群

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

这是我的 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

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

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

谢谢。


编辑

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

答案1

Nginx 允许您指定在传入或传出请求中是否使用 proxy_protocol,并且您会混淆这两者。

在以下位置使用 proxy_protocol传入连接,你必须像这样添加行proxy_protocollisten

listen     443 ssl proxy_protocol;

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

proxy_protocol on;

他们是不是相同。在负载均衡器中,传入连接来自浏览器,浏览器不支持代理协议。您只需要在传出请求中使用代理协议,发送到 kubernetes 集群中的 nginx-ingress。

因此,从指令proxy_protocol中删除该参数listen,它就应该可以工作了。

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

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

另外,请确保你正在使用 hostNetwork: true 运行 nginx-ingress,否则你可能会遇到完后还有平衡层(kube-proxy,kubernetes 服务代理)

相关内容