在 Kubernetes Ingress Nginx server-snippet 中使用位置块导致 404
Using Location Blocks In Kubernetes Ingress Nginx server-snippet Causes 404
我希望有人能在这里帮助我,因为我被困住了。
我正在从传统的 nginx/node 服务器配置转移我们的 nginx 配置,其中 nginx 和节点服务器都在同一台机器上。
在 Kubernetes 中,入口控制器 (nginx) 显然位于另一个容器中。
我遇到困难的地方是重新实施我们的规则,这些规则禁止使用位置块对图像和资产进行访问日志记录。
我们的配置看起来像
location ~* \.(?:jpg|jpeg|gif|png|ico|cur|mp4|ogg|ogv|webm|htc)$ {
access_log off;
expires 2M;
add_header Cache-Control "public, max-age=5184000"; # 5184000 is 60 days
}
当我在 server-snippet
中实现相同的块时,它匹配,但所有资产都抛出 404。
我在谷歌上搜索了一下,找到了一个答案,可以解释为什么会在这里
但建议的答案提示使用 if
块而不是 location
块,因为该位置会干扰上游代理,但是,无法从 [= 内部禁用访问日志13=] 块,仅来自 location
上下文。
我入口的其余部分看起来像(其他一切都是默认的)
real_ip_header X-Forwarded-For;
real_ip_recursive on;
underscores_in_headers on;
gzip_types text/css application/x-javascript application/javascript application/json image/svg+xml;
client_max_body_size 5M;
proxy_buffers 8 16k;
proxy_set_header X-Request-Start "t=${msec}";
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $http_host;
proxy_redirect off;
图像位于上游服务器路径的 /images/ 中。
所以我又想弄清楚如何让这些位置块工作,这样我就可以从 server-snippet
禁用这些图像的访问日志
那么谁能告诉我如何让上述位置块不为入口控制器中的资产抛出 404 错误?
我假设您的后端正在为您的资产提供服务,所以我认为问题在于您的 location {}
块没有像 nginx 入口中定义的常规路径那样的上游。
您的 nginx-ingress-controller 的 nginx.conf
中有很多 lua 代码,因此可能需要一些时间才能理解,但您可以将 nginx.conf
复制到本地:
$ kubectl cp nginx-ingress-controller-xxxxxxxxx-xxxxx:nginx.conf .
检查为您当前的服务定义的 location {}
块并将它们复制到 server-snippet
location {}
块的底部,如下所示:
我相信像这样的 server-snippet
可以:
location ~* \.(?:jpg|jpeg|gif|png|ico|cur|mp4|ogg|ogv|webm|htc)$ {
access_log off;
expires 2M;
add_header Cache-Control "public, max-age=5184000"; # 5184000 is 60 days
<== add what you copied here
set $namespace "k8s-namespace";
set $ingress_name "ingress-name";
set $service_name "service-name";
set $service_port "80";
set $location_path "/images";
...
...
...
proxy_http_version 1.1;
proxy_cookie_domain off;
proxy_cookie_path off;
# In case of errors try the next upstream server before returning an error
proxy_next_upstream error timeout;
proxy_next_upstream_tries 3;
proxy_pass http://upstream_balancer;
proxy_redirect off;
}
还有另一种方法。您实际上可以使用入口方式来处理此静态内容请求(动态),而无需编辑 nginx.conf 。
此外,每次您在入口 object 中进行更改时,nginx.conf 都会由 ingress-nginx 控制器动态地 created/edited。进行更改或安装 nginx.conf 文件可能会产生问题。
对于静态文件,使用以下代码段将您的请求重定向到正确的服务。
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: sample-app-ingress
annotations:
nginx.ingress.kubernetes.io/use-regex: "true"
nginx.ingress.kubernetes.io/server-snippet: |
expires 1M;
add_header Cache-Control "public";
spec:
ingressClassName: nginx
rules:
- host: xx.xx.com
http:
paths:
- pathType: Prefix
path: /status/.*
backend:
service:
name: one-service
port:
number: 80
- host: xx.xx.com
http:
paths:
- pathType: Prefix
path: /.*(js|css|gif|jpe?g|png)
backend:
service:
name: static-app-service
port:
number: 80
- host: xx.xx.com
http:
paths:
- pathType: Prefix
path: /
backend:
service:
name: third-service
port:
number: 80
使用 nginx.ingress.kubernetes.io/use-regex: "true"
将您的静态流量重定向到正确的服务。
上面的代码片段将为您提供如下结果:
- xx.xx.com/status/ 上的任何请求都将被路由到
one-service
.
更多示例:
xx.xx.com/status/zenduty -> one-service
xx.xx.com/status/zenduty/事件 -> one-service
xx.xx.com/status/任何东西 -> one-service
- xx.xx.com 上任何包含 .png、.js、.css、.jpg、.gif 或 .jpeg 的请求都将被路由到
static-app-service
示例:
xx.xx.com/custom.js -> static-app-service
xx.xx.com/status/custom.js -> static-app-service
xx.xx.com/custom.css -> static-app-service
xx.xx.com/abc/zen/duty/custom.css -> static-app-service
xx.xx.com/status/custom.gif -> static-app-service
- xx.xx.com 上不包含(.png、.js、.css、.jpg、.gif 或 .jpeg)且不以 ( xx.xx.com/static/), 将被路由到
third-service
示例:
xx.xx.com/login -> third-service
xx.xx.com/xyz -> third-service
如果您想向代码段添加另一个 header,您可以添加它。我的建议是为静态内容创建一个单独的入口 object。
下面是如何分离上述代码段并在自定义服务级别上添加更多 header。
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: sample-app-ingress
annotations:
nginx.ingress.kubernetes.io/use-regex: "true"
nginx.ingress.kubernetes.io/server-snippet: |
expires 1M;
add_header Cache-Control "public";
spec:
ingressClassName: nginx
rules:
- host: xx.xx.com
http:
paths:
- pathType: Prefix
path: /.*(js|css|gif|jpe?g|png)
backend:
service:
name: static-app-service
port:
number: 80
下面的代码片段适用于其他服务,这些服务不必提供静态内容并根据其要求自定义 header。
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: sample-app-ingress
annotations:
nginx.ingress.kubernetes.io/use-regex: "true"
nginx.ingress.kubernetes.io/server-snippet: |
add_header X-XSS-Protection "1";
add_header Strict-Transport-Security "max-age=31536000;includeSubdomains; preload";
spec:
ingressClassName: nginx
rules:
- host: xx.xx.com
http:
paths:
- pathType: Prefix
path: /status/.*
backend:
service:
name: one-service
port:
number: 80
- host: xx.xx.com
http:
paths:
- pathType: Prefix
path: /
backend:
service:
name: third-service
port:
number: 80
此处入口class名称为ingressClassName: nginx
,请相应更改。
这是路由到正确服务的入口方式。
如果您想将客户端 IP 传递给您的后端服务,请检查此以获取更多详细信息:https://whosebug.com/questions/65345240/updating-ingress-nginx-controller-configmap-to-pass-client-ip-to-backend-service/71407668#71407668
对于自定义错误页面:How to customize error pages served via the default backend of an nginx ingress controller?
我希望有人能在这里帮助我,因为我被困住了。
我正在从传统的 nginx/node 服务器配置转移我们的 nginx 配置,其中 nginx 和节点服务器都在同一台机器上。
在 Kubernetes 中,入口控制器 (nginx) 显然位于另一个容器中。
我遇到困难的地方是重新实施我们的规则,这些规则禁止使用位置块对图像和资产进行访问日志记录。
我们的配置看起来像
location ~* \.(?:jpg|jpeg|gif|png|ico|cur|mp4|ogg|ogv|webm|htc)$ {
access_log off;
expires 2M;
add_header Cache-Control "public, max-age=5184000"; # 5184000 is 60 days
}
当我在 server-snippet
中实现相同的块时,它匹配,但所有资产都抛出 404。
我在谷歌上搜索了一下,找到了一个答案,可以解释为什么会在这里
但建议的答案提示使用 if
块而不是 location
块,因为该位置会干扰上游代理,但是,无法从 [= 内部禁用访问日志13=] 块,仅来自 location
上下文。
我入口的其余部分看起来像(其他一切都是默认的)
real_ip_header X-Forwarded-For;
real_ip_recursive on;
underscores_in_headers on;
gzip_types text/css application/x-javascript application/javascript application/json image/svg+xml;
client_max_body_size 5M;
proxy_buffers 8 16k;
proxy_set_header X-Request-Start "t=${msec}";
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $http_host;
proxy_redirect off;
图像位于上游服务器路径的 /images/ 中。
所以我又想弄清楚如何让这些位置块工作,这样我就可以从 server-snippet
那么谁能告诉我如何让上述位置块不为入口控制器中的资产抛出 404 错误?
我假设您的后端正在为您的资产提供服务,所以我认为问题在于您的 location {}
块没有像 nginx 入口中定义的常规路径那样的上游。
您的 nginx-ingress-controller 的 nginx.conf
中有很多 lua 代码,因此可能需要一些时间才能理解,但您可以将 nginx.conf
复制到本地:
$ kubectl cp nginx-ingress-controller-xxxxxxxxx-xxxxx:nginx.conf .
检查为您当前的服务定义的 location {}
块并将它们复制到 server-snippet
location {}
块的底部,如下所示:
我相信像这样的 server-snippet
可以:
location ~* \.(?:jpg|jpeg|gif|png|ico|cur|mp4|ogg|ogv|webm|htc)$ {
access_log off;
expires 2M;
add_header Cache-Control "public, max-age=5184000"; # 5184000 is 60 days
<== add what you copied here
set $namespace "k8s-namespace";
set $ingress_name "ingress-name";
set $service_name "service-name";
set $service_port "80";
set $location_path "/images";
...
...
...
proxy_http_version 1.1;
proxy_cookie_domain off;
proxy_cookie_path off;
# In case of errors try the next upstream server before returning an error
proxy_next_upstream error timeout;
proxy_next_upstream_tries 3;
proxy_pass http://upstream_balancer;
proxy_redirect off;
}
还有另一种方法。您实际上可以使用入口方式来处理此静态内容请求(动态),而无需编辑 nginx.conf 。 此外,每次您在入口 object 中进行更改时,nginx.conf 都会由 ingress-nginx 控制器动态地 created/edited。进行更改或安装 nginx.conf 文件可能会产生问题。
对于静态文件,使用以下代码段将您的请求重定向到正确的服务。
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: sample-app-ingress
annotations:
nginx.ingress.kubernetes.io/use-regex: "true"
nginx.ingress.kubernetes.io/server-snippet: |
expires 1M;
add_header Cache-Control "public";
spec:
ingressClassName: nginx
rules:
- host: xx.xx.com
http:
paths:
- pathType: Prefix
path: /status/.*
backend:
service:
name: one-service
port:
number: 80
- host: xx.xx.com
http:
paths:
- pathType: Prefix
path: /.*(js|css|gif|jpe?g|png)
backend:
service:
name: static-app-service
port:
number: 80
- host: xx.xx.com
http:
paths:
- pathType: Prefix
path: /
backend:
service:
name: third-service
port:
number: 80
使用 nginx.ingress.kubernetes.io/use-regex: "true"
将您的静态流量重定向到正确的服务。
上面的代码片段将为您提供如下结果:
- xx.xx.com/status/ 上的任何请求都将被路由到
one-service
.
更多示例:
xx.xx.com/status/zenduty ->one-service
xx.xx.com/status/zenduty/事件 ->one-service
xx.xx.com/status/任何东西 ->one-service
- xx.xx.com 上任何包含 .png、.js、.css、.jpg、.gif 或 .jpeg 的请求都将被路由到
static-app-service
示例:
xx.xx.com/custom.js ->static-app-service
xx.xx.com/status/custom.js ->static-app-service
xx.xx.com/custom.css ->static-app-service
xx.xx.com/abc/zen/duty/custom.css ->static-app-service
xx.xx.com/status/custom.gif ->static-app-service
- xx.xx.com 上不包含(.png、.js、.css、.jpg、.gif 或 .jpeg)且不以 ( xx.xx.com/static/), 将被路由到
third-service
示例:
xx.xx.com/login ->third-service
xx.xx.com/xyz ->third-service
如果您想向代码段添加另一个 header,您可以添加它。我的建议是为静态内容创建一个单独的入口 object。
下面是如何分离上述代码段并在自定义服务级别上添加更多 header。
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: sample-app-ingress
annotations:
nginx.ingress.kubernetes.io/use-regex: "true"
nginx.ingress.kubernetes.io/server-snippet: |
expires 1M;
add_header Cache-Control "public";
spec:
ingressClassName: nginx
rules:
- host: xx.xx.com
http:
paths:
- pathType: Prefix
path: /.*(js|css|gif|jpe?g|png)
backend:
service:
name: static-app-service
port:
number: 80
下面的代码片段适用于其他服务,这些服务不必提供静态内容并根据其要求自定义 header。
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: sample-app-ingress
annotations:
nginx.ingress.kubernetes.io/use-regex: "true"
nginx.ingress.kubernetes.io/server-snippet: |
add_header X-XSS-Protection "1";
add_header Strict-Transport-Security "max-age=31536000;includeSubdomains; preload";
spec:
ingressClassName: nginx
rules:
- host: xx.xx.com
http:
paths:
- pathType: Prefix
path: /status/.*
backend:
service:
name: one-service
port:
number: 80
- host: xx.xx.com
http:
paths:
- pathType: Prefix
path: /
backend:
service:
name: third-service
port:
number: 80
此处入口class名称为ingressClassName: nginx
,请相应更改。
这是路由到正确服务的入口方式。
如果您想将客户端 IP 传递给您的后端服务,请检查此以获取更多详细信息:https://whosebug.com/questions/65345240/updating-ingress-nginx-controller-configmap-to-pass-client-ip-to-backend-service/71407668#71407668
对于自定义错误页面:How to customize error pages served via the default backend of an nginx ingress controller?