在 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" 将您的静态流量重定向到正确的服务。

上面的代码片段将为您提供如下结果:

  1. 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
  2. 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
  3. 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?