8

I'm trying to rewrite the path to the service while preserving the browser url with nginx ingress on kubernetes.

What I need is this:

  • http://example.com/path => http://service
  • http://example.com/path/bar => http://service/bar
  • http://example.com/path/file.css => http://service/file.css

That is, make the /path be the root (or some different url) in the upstream server.

From what I see here, this is done using a trailing slash on the proxy_pass, but nginx ingress doesn't seem to have this option.

Is this possible nginx ingress?

Guss
  • 2,520
  • 5
  • 32
  • 55
Natan
  • 183
  • 1
  • 2
  • 8

2 Answers2

8

Is it Possible on Nginx Ingress?

  • Yes, In order to achieve it you can use rewrite-target.

  • It will create a capture group and send it to the appropriate service. Here is an Ingress example:

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: "rewrite"
  annotations:
    kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.io/rewrite-target: /$2
spec:
  rules:
    - http: example.com
        paths: 
          - path: /foo(/|$)(.*)
            backend:
              serviceName: echo-svc
              servicePort: 80

In this ingress definition, any characters captured by (.*) will be assigned to the placeholder $2, which is then used as a parameter in the rewrite-target annotation.

This ingress will do the following:

  • Requests to /foo will be delivered to echo1-svc as /
  • Requests to /foo/bar will be delivered to echo1-svc as /bar
  • Requests to /foo/file.css will be delivered to echo-svc as /file.css
  • Nginx Ingress uses Path Priority:

In NGINX, regular expressions follow a first match policy. In order to enable more accurate path matching, ingress-nginx first orders the paths by descending length before writing them to the NGINX template as location blocks.


Example:

$ kubectl apply -f echo-ingress.yaml 
ingress.networking.k8s.io/echo-ingress created

$ kubectl get ingress
NAME           HOSTS          ADDRESS        PORTS   AGE
echo-ingress   mydomain.com   35.188.7.149   80      48s

$ tail -n 1 /etc/hosts
35.188.7.149 mydomain.com

$ curl mydomain.com/foo/bar
{"path": "/bar",
...suppressed output...
  "os": {"hostname": "echo-deploy-764d5df7cf-6m5nz"}
}

$ curl mydomain.com/foo
{"path": "/",
  "os": {"hostname": "echo-deploy-764d5df7cf-6m5nz"}
}

If you have any question let me know in the comments.

Will R.O.F.
  • 244
  • 1
  • 7
  • good answer. note that ingress-nginx has to be installed in the cluster to work. also this is interesting to know how to go about multipath : https://github.com/kubernetes/ingress-nginx/issues/6139 (thus making two ingress yaml files). – Vincent Gerris Feb 01 '21 at 17:59
  • Missing pathType? – dallasclark Sep 11 '22 at 12:49
0

In short: yes it is. Make sure not to confuse nginx-ingress (which you use as a label in your question ) and ingress-nginx, those are different. It works with ingress-nginx by installing it according to documentation. The provided answer from @Will R.O.F. shows how and the documentation can be found here: https://kubernetes.github.io/ingress-nginx/user-guide/ingress-path-matching/