0

We are using the Nginx Ingress Controller image as described here (https://docs.nginx.com/nginx-ingress-controller/) in our Kubernetes (EKS) environment, and we are having big problems trying to implement caching.

We have a JSON-based service sitting behind our ingress controller.

The Ingress generates Nginx config that looks like this:

# configuration for dcjson-mlang25/terminology-ingress

upstream dcjson-mlang25-terminology-ingress-mlang25.test.domain-jsonserver-authoring-8080 {
    zone dcjson-mlang25-terminology-ingress-mlang25.test.domain-jsonserver-authoring-8080 256k;
    random two least_conn;
    server 10.220.2.66:8080 max_fails=1 fail_timeout=10s max_conns=0;
}

server {
    listen 80;
    listen [::]:80;

    listen 443 ssl;
    listen [::]:443 ssl;

    ssl_certificate /etc/nginx/secrets/dcjson-mlang25-jsonserver-tls-secret;
    ssl_certificate_key /etc/nginx/secrets/dcjson-mlang25-jsonserver-tls-secret;

    server_tokens on;
    server_name mlang25.test.domain;

    set $resource_type "ingress";
    set $resource_name "terminology-ingress";
    set $resource_namespace "dcjson-mlang25";

    if ($scheme = http) {
            return 301 https://$host:443$request_uri;
    }

    location /authoring/ {
            set $service "jsonserver-authoring";
            proxy_http_version 1.1;
            proxy_cache STATIC;
            proxy_cache_valid 200 1d;
            proxy_cache_use_stale error timeout updating http_404 http_500 http_502 http_503 http_504;
            proxy_cache_revalidate on;
            proxy_set_header Connection "";
            proxy_hide_header 'Access-Control-Allow-Origin';
            proxy_hide_header 'Access-Control-Allow-Methods';
            proxy_hide_header 'Access-Control-Allow-Headers';
            proxy_hide_header 'Access-Control-Expose-Headers';
            proxy_hide_header 'Access-Control-Allow-Credentials';
            add_header 'Access-Control-Allow-Origin' '*' always;
            add_header 'Access-Control-Allow-Methods' 'PUT, GET, POST, DELETE, OPTIONS' always;
            add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization,AcceptX-FHIR-Starter,Origin,Accept,X-Requested-With,Content-Type,Access-Control-Request-Method,Access-Control-Request-Headers,Authorization,Prefer,Pragma,If-Match,If-None-Match' always;
            add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range' always;
            add_header 'Access-Control-Allow-Credentials' 'true';
            add_header X-Cache-Status $upstream_cache_status;
            proxy_connect_timeout 60s;
            proxy_read_timeout 1800s;
            proxy_send_timeout 1800s;
            client_max_body_size 4096m;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Host $host;
            proxy_set_header X-Forwarded-Port $server_port;
            proxy_set_header X-Forwarded-Proto $scheme;
            proxy_buffering on;
            proxy_buffers 4 256k;
            proxy_buffer_size 128k;
            proxy_max_temp_file_size 4096m;

            proxy_pass http://dcjson-mlang25-terminology-ingress-mlang25.test.domain-jsonserver-authoring-8080/;
    }
}

The Nginx.conf file itself declares the cache like so:

http {
include       /etc/nginx/mime.types;
default_type  application/octet-stream;

proxy_cache_path /tmp/nginx_cache levels=1:2 keys_zone=STATIC:32m inactive=24h max_size=10g;
proxy_cache_key $scheme$proxy_host$request_uri;


log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                  '$status $body_bytes_sent "$http_referer" '
                  '"$http_user_agent" "$http_x_forwarded_for"';

map $upstream_trailer_grpc_status $grpc_status {
    default $upstream_trailer_grpc_status;
    '' $sent_http_grpc_status;
}
** snipped**
}

The backend app does not return any Set-Cookie headers, which I know to be an issue - it's not that.

When placing a simple GET request I see this in Nginx Logs

2023/02/07 20:46:49 [debug] 416#416: *171 http script var: "https"
2023/02/07 20:46:49 [debug] 416#416: *171 http script var: "dcjson-mlang25-terminology-ingress-mlang25.test.domain-jsonserver-authoring-8080"
2023/02/07 20:46:49 [debug] 416#416: *171 http script var: "/authoring/fhir/CodeSystem/genenames.geneId-small"
2023/02/07 20:46:49 [debug] 416#416: *171 http cache key: "httpsdcjson-mlang25-terminology-ingress-mlang25.test.domain-jsonserver-authoring-8080/authoring/fhir/CodeSystem/genenames.geneId-small"
2023/02/07 20:46:49 [debug] 416#416: *171 add cleanup: 000055C5DDA4ED00
2023/02/07 20:46:49 [debug] 416#416: shmtx lock
2023/02/07 20:46:49 [debug] 416#416: slab alloc: 120 slot: 4
2023/02/07 20:46:49 [debug] 416#416: slab alloc: 00007FECD6324080
2023/02/07 20:46:49 [debug] 416#416: shmtx unlock
2023/02/07 20:46:49 [debug] 416#416: *171 http file cache exists: -5 e:0
2023/02/07 20:46:49 [debug] 416#416: *171 cache file: "/tmp/nginx_cache/8/b4/9ac307cbf4540372616c09cd894b9b48"

Repeated requests seconds later look exactly the same. To my eyes, this is saying the cache isn't hit?

Every response header set looks something like this, with the status always being MISS

2023/02/07 20:46:49 [debug] 416#416: *171 HTTP/1.1 200
Server: nginx/1.23.2
Date: Tue, 07 Feb 2023 20:46:49 GMT
Content-Type: application/fhir+json;charset=UTF-8
Transfer-Encoding: chunked
Connection: keep-alive
X-Request-Id: sJ4yXmP1ziSF3fJt
Cache-Control: no-cache
Vary: Accept,Origin,Accept-Encoding,Accept-Language,Authorization
X-Powered-By: HAPI FHIR 6.0.0 REST Server (FHIR Server; FHIR 4.0.1/R4)
ETag: W/"1"
Content-Location:             https://mlang25.test.domain/authoring/fhir/CodeSystem/genenames.geneId-small/_history/1
Last-Modified: Tue, 07 Feb 2023 20:08:35 GMT
Content-Encoding: gzip
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Strict-Transport-Security: max-age=31536000 ; includeSubDomains
X-Frame-Options: DENY
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: PUT, GET, POST, DELETE, OPTIONS
Access-Control-Allow-Headers: DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-    With,If-Modified-Since,Cache-Control,Content-Type,Authorization,AcceptX-FHIR-    Starter,Origin,Accept,X-Requested-With,Content-Type,Access-Control-Request-Method,Access-    Control-Request-Headers,Authorization,Prefer,Pragma,If-Match,If-None-Match
Access-Control-Expose-Headers: Content-Length,Content-Range
Access-Control-Allow-Credentials: true
X-Cache-Status: MISS

I am really struggling to work out why the cache is never being hit.

marc
  • 73
  • 7

1 Answers1

1

For anyone who stumbles across this - our backend had a change from a 3rd party and had started returning Cache-Control no-cache meaning nginx will never cache the result.

marc
  • 73
  • 7