ingress-nginx: rewrite-target: /$2 causes incorrect Location response header for redirects
NGINX Ingress controller version (exec into the pod and run 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:
- Cloud provider or hardware configuration: AWS EKS
- OS (e.g. from /etc/os-release): Amazon Linux 2
- Kernel (e.g.
uname -a
):Linux 4.14.252-195.483.amzn2.x86_64 #1 SMP Mon Nov 1 20:58:46 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux
- Install tools:
eksctl
- Basic cluster related info:
kubectl version
- see abovekubectl get nodes -o wide
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION
ip-xxx.compute.internal Ready <none> 35d v1.21.4-eks-033ce7e 172.xx.xx.xx xx.xx.xx.xx Amazon Linux 2 5.4.149-73.259.amzn2.x86_64
ip-xxx.compute.internal Ready <none> 35d v1.21.4-eks-033ce7e 172.xx.xx.xx xx.xx.xx.xx Amazon Linux 2 5.4.149-73.259.amzn2.x86_64
ip-xxx.compute.internal Ready <none> 35d v1.21.4-eks-033ce7e 172.xx.xx.xx xx.xx.xx.xx Amazon Linux 2 5.4.149-73.259.amzn2.x86_64
-
How was the ingress-nginx-controller installed: ArgoCD / Helm with version info shown above and no values overridden.
-
Current State of the controller:
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>
What happened:
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.
What you expected to happen:
Should send redirect for location: /analytics/jupyter/lab/
This seems to be what add-base-url
was for. What is the proper replacement?
How to reproduce it:
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
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.
Anything else we need to know:
Related to https://github.com/kubernetes/ingress-nginx/issues/3770, https://github.com/kubernetes/ingress-nginx/pull/3174, https://github.com/kubernetes/ingress-nginx/issues/6059.
/kind bug
About this issue
- Original URL
- State: open
- Created 3 years ago
- Reactions: 4
- Comments: 24 (8 by maintainers)
If I’m not mistaken, the issue here is that the service behind the nginx proxy is returning a relative redirect in the Location header, which the nginx proxy is ignoring. So a simple GET request would…
However, what we need is for nginx to reverse the rewrite in any Location headers
Is there some other way of accomplishing this?
Okay, I have created a minimal example and think I am halfway to solving it.
Create Dockerfile for Flask app:
Create Kubernetes manifests:
Test requesting the service name from another pod (service is ClusterIP):
Okay - so at this point app “works” and service talks to it properly. Service is default ClusterIP and no Ingress has been introduced yet.
Next deploy ingress-nginx with ArgoCD/Helm:
Now add Ingress resource for our Flask app:
Deploy this manifest as part of the Flask app deployment.
First two routes work:
But how about
/app1/foo
?This illustrates the central problem - http://xx-xx.zzzz.elb.amazonaws.com/bar will 404.
Now for the half-solution. The course of action seems to be to use
nginx.ingress.kubernetes.io/proxy-redirect-to
andnginx.ingress.kubernetes.io/proxy-redirect-from
. Unfortunately there appears to be a limitation in Nginx config (https://trac.nginx.org/nginx/ticket/2291, https://stackoverflow.com/q/70205048/7954504) that does not allow the precise notation required:$proxy_host
and ignore other hostsYou need to configure defaultBackend: true on your nginx controller to resolve that issue: https://kubernetes.github.io/ingress-nginx/user-guide/default-backend/
Yes.