I needed to map a custom sub-path in Kubernetes to a backend service I was running in Azure Kubernetes Service.
I wanted something like this:

Naturally, I needed to configure my Ingress Component to allow this. I attempted to write a valid Ingress Component to expose both my client & my server though the same root URL, with different sub-paths. The client part of the ingress worked without issue, but the server didn’t.
Here is the server Ingress Component configuration.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: containers-everywhere-server-ingress
annotations:
kubernetes.io/ingress.class: nginx
spec:
rules:
- http:
paths:
- path: /server
pathType: Prefix
backend:
service:
name: containers-everywhere-server-service
port:
number: 80
What I didn’t understand was what NGINX was appending to the requests to the backend service. By default, NGINX is going to pass the entire URL that is specified by sending it to the backend service.
Original URL
http://1.2.3.4/server/swagger/index.html
URL sent to backend service
http://server/swagger/index.html
Naturally, my backend service thinks it is the center of the universe, so it doesn’t know anything about the server
keyword I added to differentiate the services in the Ingress Component.
Therefore, I needed to re-write the URL that is passed to the backend service.
The documentation states that I need to provide a regex & specify some annotations that will get passed to the underlying NGINX Ingress Component.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /$2
...
spec:
rules:
- http:
paths:
- path: /something(/|$)(.*)
...
If we look at the regex specified in a tool like https://regex101.com, we can see that 2 capture groups will appear.

The most important part of this regex is the capture group that has the actual path on the server application I want to access (in this case, the Swagger documentation).
This is specified in the annotations
section of the Kubernetes Ingress Component (using the nginx.ingress.kubernetes.io/rewrite-target
annotation).
nginx.ingress.kubernetes.io/rewrite-target: /$2
The documentation does state what is happening, but I didn’t understand what was going to be captured in the various capture groups.
My original code didn’t have the rewrite-target
annotation at all and then the 2nd time I did it, I copied/pasted code from Stack Overflow without understanding what it was really doing (not that anyone else has ever done this :)).
nginx.ingress.kubernetes.io/rewrite-target: /$1
This was mapping requests to the root of my server application, which isn’t going to respond.
The correct Ingress in the end is:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: containers-everywhere-server-ingress
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/use-regex: "true"
nginx.ingress.kubernetes.io/ssl-redirect: "false"
nginx.ingress.kubernetes.io/rewrite-target: /$2
spec:
rules:
- http:
paths:
- path: /server(/|$)(.*)
pathType: Prefix
backend:
service:
name: containers-everywhere-server-service
port:
number: 80
This Ingress Component will match any requests to the server
sub-path, forward requests to the containers-everywhere-server-service
and the part of the URL after server
will get added to a request starting at the root of the web server.
In the end, the message is RTFM.