While working with minikube ingress, I have to write nginx.ingress.kubernetes.io/rewrite-target: /$1
. I have been trying hard to understand why we need this annotation and how to use it.
I know that the doc says the following:
In some scenarios the exposed URL in the backend service differs from the specified path in the Ingress rule. Without a rewrite any request will return 404. Set the annotation nginx.ingress.kubernetes.io/rewrite-target to the path expected by the service.
But I am not able to get the exact point of what exactly the exposed URL in the backend service differs from the specified path in the Ingress rule
means. I am not able to get the idea clearly.
Further, upon trying to execute ingress file with services:
code 1:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: example-ingress
namespace: example-namespace
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /$1
spec:
rules:
- host: myexample.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: example-service
port:
number: 80
code 2:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: example-ingress
namespace: example-namespace
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- host: myexample.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: example-service
port:
number: 80
code 3:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: example-ingress
namespace: example-namespace
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /$1
spec:
rules:
- host: myexample.com
http:
paths:
- path: /index
pathType: Prefix
backend:
service:
name: example-service
port:
number: 80
what exactly is the difference between each pair of the above 3 code snippets with respect to rewrite-target and path mentioned above?
PS: I’m new to minikube and trying to figure out the exact way things work. Please help.
2
Answers
I don’t know if things changes with new versions of the Ingress resource or with new versions of the Nginx Ingress Controller, but this is how I think it works.
Suppose I want to serve 2 different web applications under the same domain, with a Ingress.
/
/
So, both Apps are expecting their requests directly under root, which (at first glance) seems to make them impossible to be served at the same domain.
Except, with rewrite targets, I can. I could just serve them under a different path, but rewrite the target to
/
myexample.com/aaa/
myexample.com/bbb/
And add a rewrite target to remove the first part of the path. This is just an example of what a rewrite target can be used for, it simply makes you able to serve an application under a different path of the one expected by the app itself.
Example of the ingress:
Notice that, while this works pretty well on Rest API and similar things, it may work less well on web pages, because a web page could try to load resources at a different path (for example if it does not use relative paths). This is why (usually) frontend applications needs to know on which path they are being served under a domain.
Regarding the syntax of rewrite targets, I’ll take as example the Ingress I wrote above. There are a couple things to take into consideration:
Let’s start with
path
andpathType
interactions. With the path I can define where to serve my services. Depending on thepathType
, it may be just aPrefix
of the whole path, theExact
path, or it can depends on the Ingress Controller (akaImplementationSpecific
). Everything is nicely explain in the documentation with a long table of examples ( https://kubernetes.io/docs/concepts/services-networking/ingress/#examples )I can do almost everything just with path and pathType, except if the applications I want to serve are expecting to be served at different paths from the ones specified in the Ingress; this is when
rewrite-target
comes into play.Like in the example above, I can use
rewrite-target
to serve an application under a different path from the one expected, composing the url as I want. I can also use regex and capture groups (this is what$1
,$2
and so on are)For example, if I write
path: /bbb(/|$)(.*)
I mean that this path will match everything under /bbb, with or without a / after bbb. And if I then writerewrite-target: /$2
I’m meaning that requests will be rewritten to substitute/bbb
with/
and then take the second capture group (which means the second regex expression,(.*)
)The documentation explains it pretty well, even if it makes still use of the old Ingress resource ( https://kubernetes.github.io/ingress-nginx/examples/rewrite/ )
Great explanation provided by @AndD!
There are few things I’d like to add:
(/|$)(.*)
is sometimes crucial as you want to reach your app under htpps://example.com and https://example.com/$1
and$2
variables capture the path elements that aren’t changing, docsSo here’s how I’d do it (main service under
pathType and all sub-paths excluding the
test
pathType (Exact) to point to testing service):