Kubernetes ingress nginx not matching sub paths - kubernetes

I'm trying to make a simple example of ingress-nginx on google cloud, but it's not matching the subpaths:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: test-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- http:
paths:
- path: /one
backend:
serviceName: test-one-backend
servicePort: 80
- path: /two
backend:
serviceName: test-two-backend
servicePort: 80
When I call, http://server/one works, but when I call http://server/one/path I get a 404.
I'd tried several things like using regex, but is simply not working
The backends are just, echo servers that reply always on any path.

You need to use a /* at the end of the path:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: test-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- http:
paths:
- path: /one/*
backend:
serviceName: test-one-backend
servicePort: 80
- path: /two
backend:
serviceName: test-two-backend
servicePort: 80
It's not really documented widely as of today, but in essence the path translates to a location {} block in the nginx.conf

Attention it changed in version 0.22.0 of ingress-nginx. checkout example at https://github.com/kubernetes/ingress-nginx/blob/master/docs/examples/rewrite/README.md
Now you have to work with captured groups to pass a subpath to the rewrite-target.
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /$2
name: rewrite
namespace: default
spec:
rules:
- host: rewrite.bar.com
http:
paths:
- backend:
serviceName: http-svc
servicePort: 80
path: /something(/|$)(.*)

This definition matches the exact string for the path. If you want to include subdirectories you can use the wildcard *. Your modified definition should look like this:
- path: /one/*
backend:
serviceName: test-one-backend
servicePort: 80
I am not sure if http://server/one (without the slash at the end) still works. In that case you have to keep your old definition and add another one like the above.

Related

Is there a best practice to implement ingress rule with rewrite to root

For example, I have a rule (https://kubernetes.github.io/ingress-nginx/examples/rewrite/):
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /$2
name: rewrite
namespace: default
spec:
rules:
- host: rewrite.bar.com
http:
paths:
- backend:
serviceName: http-svc
servicePort: 80
path: /something(/|$)(.*)
So anything that goes to rewrite.bar.com/something will go to http-svc/. And if http-svc will answer another location, e.g. /static there will be redirect to rewrite.bar.com/static and here we go - 404. I wonder is there any simple and clear solution to fix such situations without asking the developer to implement proxy_path variable or something like that?
Tried Make links in response relative to new path
Change the rewrite annotation to $1. Note I have also changed the path regex. That should do it.
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /$1
name: rewrite
namespace: default
spec:
rules:
- host: rewrite.bar.com
http:
paths:
- backend:
serviceName: http-svc
servicePort: 80
path: /something/(.*)

Kubernetes nginx ingress rewrite issue

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
namespace: default
name: my-ingress
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/rewrite-target: $2
spec:
rules:
- host: hostname.com
http:
paths:
- path: /
backend:
serviceName: frontend
servicePort: 80
- path: /api/v1(/|$)(.*)
backend:
serviceName: backend
servicePort: 80
What I am trying to accomplish here is:
hostname.com/api/v1/anyurl should become hostname.com/anyurl when it goes to the backend.
hostname.com/anyurl should remain hostname.com/anyurl and go to the frontend.
The /api/v1 rewrite seems to work, but any urls going to the frontend gets rewrited to /.
What I need is the rewrite rule to only apply to the /api/v1 path
I guess this should work for you -
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
namespace: default
name: my-ingress
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/rewrite-target: $1
spec:
rules:
- host: hostname.com
http:
paths:
- path: /(.*)
backend:
serviceName: frontend
servicePort: 80
- path: /api/(.*)
backend:
serviceName: backend
servicePort: 80
I have just edited this, it works for me, please check for this. I guess we can troubleshoot

Route traffic using ingress

I had a working example of a project a year back, which is not working anymore.
It's basically related to change in the behavior of nginx.ingress.kubernetes.io/rewrite-target property mentioned here - https://github.com/kubernetes/ingress-nginx/tree/master/docs/examples/rewrite
I have 3 application and I want to route based on conditions.
/* to frontend-cluster-ip-service
/api/battleship/* to battleship-cluster-ip-service
/api/connect4/* to connect-four-cluster-ip-service
The working example that was working an year back was
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: ingress-service
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- http:
paths:
- path: /
backend:
serviceName: frontend-cluster-ip-service
servicePort: 3000
- path: /api/connect4/
backend:
serviceName: connect-four-cluster-ip-service
servicePort: 8080
- path: /api/battleship/
backend:
serviceName: battleship-cluster-ip-service
servicePort: 8080
However, this is not working anymore and only routing to / , i.e to frontend-cluster-ip-service is working. Routing to other serives fails and I get 404.
Then I came to know about the change in nginx.ingress.kubernetes.io/rewrite-target.
I tried following then
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: ingress-service
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/rewrite-target: /$2
spec:
rules:
- http:
paths:
- path: /
backend:
serviceName: frontend-cluster-ip-service
servicePort: 3000
- path: /api/connect4(/|$)(.*)
backend:
serviceName: connect-four-cluster-ip-service
servicePort: 8080
- path: /api/battleship(/|$)(.*)
backend:
serviceName: battleship-cluster-ip-service
servicePort: 8080
Now the routing to connect-four-cluster-ip-service and battleship-cluster-ip-service is working but frontend-cluster-ip-service is not working and few js files loads are showing error:
I had the same issue with a bit more complicated rewrite (it was only for one different path).
Making multiple Ingresses for each path worked for me but might not be the cleanest solution.
My ingress definition:
https://github.com/FORTH-ICS-INSPIRE/artemis/blob/master/artemis-chart/templates/ingresses.yaml

How to specify a prefix to a service exposed with an ingress

I want exposing various services with a single ingress.
rules:
- http:
paths:
# The path is the URL prefix for the service, e.g. /api/* or just /*
# Note that the service will receive the entire URL with the prefix
- path: /service1/*
backend:
serviceName: service1
servicePort: 5000
- path: /service2/*
backend:
serviceName: service2
servicePort: 5000
The problem is the whole URL including the prefix is passed to the underlying services so all requests return 404 errors: service1 and api don't respond on /service1/some/path but directly on /some/path
How can I specify a prefix to the underlying services?
UPDATE
I tried using rewrite-target as follows. Requests are sent to the rasa-nlu service, but they all trigger 404 because rasa-nlu still gets the /nlu
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: ingress
annotations:
ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- http:
paths:
- path: /nlu
backend:
serviceName: rasa-nlu
servicePort: 5000
This might be what you are looking for;
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
ingress.kubernetes.io/rewrite-target: /
name: rewrite
namespace: default
spec:
rules:
- host: rewrite.bar.com
http:
paths:
- backend:
serviceName: echoheaders
servicePort: 80
path: /something
Note the annotation to rewrite-target.
Found this here
This thread might be solved till now, but just for the sake of solution.
below will solve the issue, the default path will be /nlu when it is added to the re-write annotation.
It is from the nginx re-write rule which gets applies to the definition of location directive.
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: ingress
annotations:
ingress.kubernetes.io/rewrite-target: /nlu
spec:
rules:
- http:
paths:
- path: /nlu
backend:
serviceName: rasa-nlu
servicePort: 5000

Dynamic redirect using ingress

I have 2 questions:
1) I have a kubernetes cluster with multiple services and I want to use ingress to dynamically redirect the traffic to the cluster.
I expect the configuration to look something like this:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: test
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- host: foo.bar.com
http:
paths:
- path: /service1/*
backend:
serviceName: service1
servicePort: 80
path: /*
- path: /service2/*
backend:
serviceName: service2
servicePort: 80
path:/*
So basically I want all the traffic to /service1/endpoint to be redirected to s1:80/endpoint dynamically.
2) Let's say I have 2 web services - service1 & service2.
I want the users to work with the following URL in their browser:
kube/serviceN/endpoint
Is there a way to do that without having my users redirected to service1/endpoint?
Thanks!
I believe your ingress definition to be almost correct:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: test
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- host: foo.bar.com
http:
paths:
- path: /service1
backend:
serviceName: service1
servicePort: 80
- path: /service2
backend:
serviceName: service2
servicePort: 80
This should work if you have an ingress correctly deployed!
I hope I have understood your question properly but if so, what you have provided as an example is pretty close to the mark. The below config should work as described.
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: test
spec:
rules:
- host: foo.bar.com
http:
paths:
- path: /service1/
backend:
serviceName: service1
servicePort: 80
- path: /service2/
backend:
serviceName: service2
servicePort: 80
Good luck :)