Setting cache-control headers for nginx ingress controller on kubernetes GKE

10/8/2018

I have an ingress-nginx controller handling traffic to my Kubernetes cluster hosted on GKE. I set it up using helm installation instructions from docs:

Docs here

For the most part everything is working, but if I try to set cache related parameters via a server-snippet annotation, all of the served content that should get the cache-control headers comes back as a 404.

Here's my ingress-service.yaml file:

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

Again, it's only the resources that are matched by the regex that come back as 404 (all .js files, .css files, etc.).

Any thoughts on why this would be happening?

Any help is appreciated!

-- Murcielago
google-kubernetes-engine
kubernetes
kubernetes-ingress
nginx
nginx-ingress

2 Answers

11/18/2019

configuration-snippet will work with nginx ingress

you can use something like

nginx.ingress.kubernetes.io/configuration-snippet : |
      if ($request_uri ~* \.(js|css|gif|jpe?g|png)) {
        expires 1M;
        add_header Cache-Control "public";
      }
-- Harsh Manvar
Source: StackOverflow

10/8/2018

Those location blocks are last and/or longest match wins, and since the ingress itself is not serving any such content, the nginx relies on a proxy_pass directive pointing at the upstream server. Thus, if you are getting 404s, it's very likely because your location is matching, thus interfering with the proxy_pass one. There's a pretty good chance you'd actually want configuration-snippet: instead, likely in combination with if ($request_uri ~* ...) { to add the header.

One can try this locally with a trivial nginx.conf pointing at python3 -m http.server 9090 or whatever fake upstream target.

Separately, for debugging nginx ingress problems, it is often invaluable to consult its actual nginx.conf, which one can grab from any one of the ingress Pods, and/or consulting the logs of the ingress Pods where nginx will emit helpful debugging text.

-- mdaniel
Source: StackOverflow