如何在 NGINX 中创建条件 proxy_pass

How to make a conditional proxy_pass within NGINX

我是 运行 我们的 K8s 前端和后端,这个问题是关于我们使用 NGINX 的前端设置。

我正在尝试找到一种方法来使用侧车容器收集我的主要前​​端容器(nginx + 前端)的指标,该容器在 /[= 上调整 stub_status 运行 34=] 在端口 8080 值到我的应用程序的键值对。这样我就可以在端口 9113 的 sidecars/metrics 上使用 Prometheus 抓取它们。

我想阻止 pod 外部 stub_staus 的流量,因为只有 sidecar 需要能够访问它并且我正在尝试从平台外部阻止 /metrics(因此示例随机 172范围地址为例)。如果我使用 return 444 或 404 而不是代理传递(见下文),我会得到一个很好的大错误。然而,我们的前端可以以一种很好的(优雅的)方式处理 404,因此您甚至不需要退出前端,而只是在停留在前端应用程序中时获得用户友好的 404 消息,并最终到达 location/404。这也使 /stub_status 或 /metrics 看起来好像没有任何内容。拥有它真好。

我尝试将 ^/metrics$ 重写为 /404(例如),但这只是让我得到了 NGINX 404。可能是因为/metrics运行在9113上,9113上没有监听/404,我不太确定。

我知道下面的代理传递示例在 IF 语句中是不可能的,因为我收到以下错误“proxy_pass”不能在正则表达式给定的位置或命名位置内包含 URI 部分,或者在“if”语句内,或在“limit_except”块内。但是,下面是为了说明我正在尝试做的事情。我只是不确定如何让它表现得像这样。

提前致谢!

HTTP 阻止

http {

  #Block traffic from outside platform for /stub_status
  map $remote_addr $block_outside_pod {
      default               1;
      127.0.0.1             0;
  } 

  #Block traffic from outside platform for /metrics
  map $http_x_forwarded_for $block_outside_platform {
      default               1;
      ~^172\.30\.\d*.\d*$   0;
  }

}

服务器块 (我想要完成的)

server {

    location /stub_status {
      #sidecar only
      if ($block_outside_pod = 1) {
        proxy_pass http://localhost:8080/404; 
      }
      stub_status;
    }  

    location /metrics {
      #platform only
      if ($block_outside_platform = 1) {
        proxy_pass http://localhost:8080/404; 
      }
    }   
} 

经过更多测试后,我发现以下效果非常好:

HTTP 阻止

http {

  #Block traffic from outside platform for /stub_status
  map $remote_addr $block_outside_pod {
      default               1;
      127.0.0.1             0;
      ::1                   0;
  } 

  #Block traffic from outside platform for /metrics
  map $http_x_forwarded_for $block_outside_platform {
      default               1;
      ~^172\.30\.\d*.\d*$   0;
  }

}

服务器阻塞

 server { 
    listen       8080 default_server; 
    server_name  _; 
    root         /<insert your location>; 
 
    error_page 418 = @block_traffic; 
    location /stub_status { 
      #sidecar only 
      if ($block_outside_pod = 1) { 
        return 418; 
      } 
      stub_status; 
    }   
 
    error_page 418 = @block_traffic; 
    location /metrics { 
      #platform only 
      if ($block_outside_platform = 1) { 
        return 418; 
      } 
    }     
 
    location @block_traffic { 
      rewrite ^ /404; 
      proxy_pass http://localhost:8080;  
    }    
 
    location / { 
      index.html etc...
      add_header etc...
    } 

这意味着任何从平台外部通过 k8s 进入此 pod 的 8080 都会从我们的网站获得一个漂亮的 404 页面,让它看起来好像不存在 =)

感谢 NGINX Slack 的提醒!