Getting an NGINX ingress running on a cluster is really easy, but the documentation did not immediately tell me how to strip the path prefix off at the ingress. I know I can use something like Istio to do this for me but for this specific project I didn’t need all of the additional complexity of that tool. So, how do I have nginx rewrite away the path prefix I use to target my services? It turns out it’s simple; although nowhere near as capable as Istio’s VirtualServices.
First, let’s define (possibly) the most simple ingress possible:
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: my-ingress namespace: my-namespace spec: rules: - http: paths: - pathType: Prefix path: /api backend: service: name: my-api port: number: 8080
I think this is quite straightforward: I want anything with the prefix
/api to get sent to a service named
my-api running at port 8080. The drawback to this ingress definition is that now my service must run expecting the path to include
/api. That’s not the end of the world I suppose, but I prefer my services to not care about things outside their control.
In my case I want NGINX to basically erase that path match before the request is routed to my service. I can do that with a little regular expression with a capture group for my path:
/api(/|$)(.*) instead of
/api and the
rewrite-target annotation, like so:
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: my-ingress namespace: my-namespace annotations: nginx.ingress.kubernetes.io/rewrite-target: /$2 spec: rules: - http: paths: - pathType: Prefix path: /api(/|$)(.*) backend: service: name: my-api port: number: 8080
That’s it! Now the
/api prefix will be “erased” – Really I’m just not including it in our rewrite target. I’ve told NGINX to rewrite the path to
/ plus the second capture group (that’s $2), which is anything in the
(.*) capture group. As an example requests coming in to
/api/person will be rewritten to
/api/ will be rewritten to
/. To learn more about regular expression capture groups read here.