Is it possible to configure an nginx
class ingress in Kubernetes with a backend reference to a captured group from a path regex? There is no indication of this in the ingress-nginx docs https://kubernetes.github.io/ingress-nginx/user-guide/ingress-path-matching/
I am trying to reduce the complexity of ingress path / backend definitions, e.g. from this:
...
spec:
rules:
- http:
paths:
- path: /some/backend1/*
backend:
serviceName: backend1
- path: /some/otherbackend/*
backend:
serviceName: otherbackend
to something like this:
spec:
rules:
- http:
paths:
- path: /some/([^/]+)/(.+)
backend:
serviceName: $1 # or \1 - possible to ref a capture group here?
In the above example, the match regex for path
matches "any character that isn't a '/' repeated" - i.e. it will match the next URI part until '/'. Am then looking to pass into serviceName
.
Is this possible?
edit
I have found a way to shoe horn this into working. This is not an ideal way of doing it, because I am injecting an override directly into nginx configs. Would sort of functionality similar to this be worth requesting as an nginx controller feature?
I have posted a solution to get it working below, even though there are concerns with it - see the disclaimer / concerns below.
disclaimer: Before reproducing this, it is useful to know some of the concerns around working with nginx config directly - see this -
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: dynamic-routing-ingress
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/use-regex: "true"
nginx.ingress.kubernetes.io/configuration-snippet: |
set $proxy_upstream_name "default-$BackendService-8088";
spec:
rules:
- http:
paths:
- path: /dynamci/(?<BackendService>[^/]+)(.+)?
pathType: ImplementationSpecific
backend:
service:
name: backendservice
port:
number: 8088
Now requests to /dynamic/x-backend
will get routed to x-backend
service, if it exists. Heavily caveated - assuming you have consistent spec for the service definitions (e.g. host / port / namespace / etc).
The link above that discusses lack of robustness is that the nginx controller translates to nginx config in a correlated way, and now you are taking that + sanity checks (e.g. by the admission verifier), as well as understanding internal controller naming conventions into the ingress definition. Without the configuration-snippet
annotation, the nginx location block would set proxy_upstream_name
to something like default-backendservice-8088
, but then the config snippet injects another set $proxy_upstream_name
parameter later, that matches the name of the captured group from the regex - so you have to know how the back references are created and manually maintain this, while ensuring that the override proxy parameter is consistent with how all your services are defined (e.g. if you have different backend services running on different ports, this won't solve for it and it starts becoming much more complex pretty quick).
While it does get the desired functionality, am not sure if I'll take this forward because of reliability / robustness concerns....