Search code examples
nginxkubernetesreverse-proxykubernetes-ingressnginx-ingress

K8s Ingress resource does not add original URL prefix to Location response header


I'm unable to specify an Ingress resource correctly so that an app's Location header is rewritten to include the original URL path in front.

Using config:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress-fanout-namespace-xyz
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /$2
  namespace: namespace-xyz
spec:
  ingressClassName: nginx
  rules:
    - http:
        paths:
          - path: /analytics/spark/master(/|$)(.*)
            pathType: Prefix
            backend:
              service:
                name: spark-master-svc
                port:
                  number: 80
          - path: /analytics/jupyter/lab(/|$)(.*)
            pathType: Prefix
            backend:
              service:
                name: jupyter-proxy-public
                port:
                  number: 80

Request URL: https://xx-xx.yyy.elb.amazonaws.com/analytics/jupyter/lab/

Response header: location: /hub/

Redirects to https://xx-xx.yyy.elb.amazonaws.com/hub/, 404s.

This should instead send redirect for location: /analytics/jupyter/lab/

This seems to be what add-base-url was for, which is now deprecated. What is the proper replacement and how can I effectively make the Location become /analytics/jupyter/lab/hub/ ?


If I remove rewrite-target altogether, then http://xx-xx.yyy.elb.amazonaws.com/analytics/jupyter/lab/ does not redirect at all, it just 404s.


Info:

NGINX Ingress controller version:

-------------------------------------------------------------------------------
NGINX Ingress controller
  Release:       v1.0.5
  Build:         7ce96cbcf668f94a0d1ee0a674e96002948bff6f
  Repository:    https://github.com/kubernetes/ingress-nginx
  nginx version: nginx/1.19.9

-------------------------------------------------------------------------------

Kubernetes version (use kubectl version):

Client Version: version.Info{Major:"1", Minor:"21+", GitVersion:"v1.21.2-13+d2965f0db10712", GitCommit:"d2965f0db1071203c6f5bc662c2827c71fc8b20d", GitTreeState:"clean", BuildDate:"2021-06-26T01:02:11Z", GoVersion:"go1.16.5", Compiler:"gc", Platform:"linux/amd64"}
Server Version: version.Info{Major:"1", Minor:"21+", GitVersion:"v1.21.2-eks-0389ca3", GitCommit:"8a4e27b9d88142bbdd21b997b532eb6d493df6d2", GitTreeState:"clean", BuildDate:"2021-07-31T01:34:46Z", GoVersion:"go1.16.5", Compiler:"gc", Platform:"linux/amd64"}

Environment:

  • AWS EKS
  • Amazon Linux 2

ingress-nginx-controller was installed thorugh ArgoCD / Helm with version info shown above and no values overridden.

$ kubectl describe ingressclasses
Name:         nginx
Labels:       app.kubernetes.io/component=controller
              app.kubernetes.io/instance=ingress-controller
              app.kubernetes.io/managed-by=Helm
              app.kubernetes.io/name=ingress-nginx
              app.kubernetes.io/version=1.0.5
              helm.sh/chart=ingress-nginx-4.0.9
Annotations:  <none>
Controller:   k8s.io/ingress-nginx
Events:       <none>

Solution

  • jupyter-proxy needs its base_url to be set for the workload behind that service. Now it's unaware of the fact it is being served from a sub path, so when it send the redirect it sends as if it was (and actually is) served from the root url.

    A quick test showed that

    helm install my-jupyterhub jupyterhub/jupyterhub -n jupyterhub \
    --create-namespace \
    --set hub.baseUrl="/analytics/jupyter/lab" \
    --set ingress.enabled=true \
    --set ingress.pathType="ImplementationSpecific" \
    --set proxy.service.type=NodePort \
    --set ingress.annotations.'kubernetes\.io/ingress\.class'=nginx
    

    deployed jupyter hub for me with Ingress and I was able to access it via <X.X.X.X>/analytics/jupyter/lab/