为什么变量在 NGINX `proxy_pass` 中不起作用?

Mar*_*arc 7 nginx

为什么变量在 中不起作用proxy_pass

这很完美:

location /foo/ {
  proxy_pass http://127.0.0.1/;
}
Run Code Online (Sandbox Code Playgroud)

这根本不起作用:

location /foo/ {
  set $FOO http://127.0.0.1/;
  proxy_pass $FOO;
  add_header x-debug $FOO;
}
Run Code Online (Sandbox Code Playgroud)

我看到了,x-header: http://127.0.0.1/但结果是 404,所以我不知道它代理到哪里,但它与第一​​个示例不同。

源代码解释了在 proxy_pass 中使用变量可以防止上游不可用时 NGINX 启动错误。

更新:问题是上游路径重写。我希望它在删除前缀时重写/foo/blah到上游。它适用于静态主机/uri 条目,但不适用于变量。/blah/foo

Mar*_*arc 8

在@MSalters 的帮助下,最终的答案比我想象的要复杂。原因是 NGINX 使用变量的方式与静态输入主机名的方式不同 - 它甚至不使用相同的 DNS 机制。

主要问题是路径处理和前缀剥离对于变量的作用不同。您必须自己删除路径前缀。在我原来的例子中:

location /foo/ {
  set $FOO 127.0.0.1;
  rewrite /foo/(.*) /$1 break;
  proxy_pass http://$FOO/$1$is_args$args;
}
Run Code Online (Sandbox Code Playgroud)

在我的示例中,我使用 IP 地址,因此不需要解析器。但是,如果您使用主机名,则resolver需要在其中添加您的 DNS IP。耸耸肩。

为了充分披露,我们在 Kubernetes 中使用 NGINX,因此它变得更加复杂。特别感兴趣的点是:

  1. 添加resolver包含集群 DNS 服务 IP 的指令(在我的示例中为 10.43.0.10)。kube-dns这是命名空间中服务的 ClusterIP kube-system
  2. 即使您的 NGINX 位于同一名称空间,也请使用 FQDN,因为 DNS 显然只能解析 FQDN。
location /foo/ {
  set $MYSERVICE myservice.mynamespace.svc.cluster.local;
  rewrite /foo/(.*) /$1 break;
  proxy_pass http://$MYSERVICE/$1$is_args$args;
  resolver 10.43.0.10 valid=10s;
}
Run Code Online (Sandbox Code Playgroud)

注意:由于 NGINX 中的一个 BUG(不幸的是 NGINX 维护者没有承认),如果路径包含空格,在 URL 中使用 $1 将会中断。因此/foo%20bar/将被传递到上游/foo bar/并中断。