首页 > 解决方案 > 在 kubernetes GKE 上为 nginx 入口控制器设置缓存控制标头

问题描述

我有一个 ingress-nginx 控制器来处理我在 GKE 上托管的 Kubernetes 集群的流量。我使用文档中的 helm 安装说明进行了设置:

文档在这里

在大多数情况下,一切正常,但如果我尝试通过server-snippet注释设置缓存相关参数,则所有应获取缓存控制标头的服务内容都以404.

这是我的ingress-service.yaml文件:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: ingress-service
  annotations:
    kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.io/proxy-read-timeout: "4000"
    nginx.ingress.kubernetes.io/proxy-send-timeout: "4000"
    nginx.ingress.kubernetes.io/server-snippet: |
      location ~* \.(js|css|gif|jpe?g|png)$ {
        expires 1M;
        add_header Cache-Control "public";
      }
spec:
  tls:
    - hosts:
        - example.com
      secretName: example-com
  rules:
    - host: example.com
      http:
       paths:
        - path: /
          backend:
            serviceName: client-cluster-ip-service
            servicePort: 5000
        - path: /api/
          backend:
            serviceName: server-cluster-ip-service
            servicePort: 4000

同样,只有与正则表达式匹配的资源才会返回404(所有.js文件、.css文件等)。

关于为什么会发生这种情况的任何想法?

任何帮助表示赞赏!

标签: nginxkuberneteskubernetes-ingressgoogle-kubernetes-enginenginx-ingress

解决方案


这些location块是最后一个和/或最长的匹配获胜,并且由于入口本身不提供任何此类内容,nginx 依赖于指向上游服务器的proxy_pass指令。因此,如果您收到 404,很可能是因为 location正在匹配,从而干扰了这个proxy_pass。很有可能您实际上想要configuration-snippet:代替,可能与if ($request_uri ~* ...) {添加标题相结合。

可以通过一个简单的 nginx.conf 指向python3 -m http.server 9090或任何虚假的上游目标在本地尝试此操作。

另外,对于调试 nginx 入口问题,查阅它的实际值通常是非常宝贵的nginx.conf,可以从任何一个入口 Pod 中获取,和/或查阅入口 Pod 的日志,其中 nginx 将发出有用的调试文本。


推荐阅读