I have multiple namespaces which utilize different services
Some of these services expose the same paths, i.e. /ready
I'de like to create an ingress rule per namespace/service so the external path of namespaceA/ready
will actually go to the service under namespaceA
at /ready
path
I read about rewrite but if I understand it correctly, it will redirect namespaceA/ready
to /ready
globally, meaning it will just act as if the path was /ready
, regardless to the namespace.
I'm not sure. But you may have a little misunderstanding between rewrite
and redirect
. Rewrite rules won't cause redirect, it rewrite the request then send it to the specific backend. It's totally reasonable and common to configure two rewrite rules rewriting two paths with the same suffix to two different backend.
Rewrite works like this:
$ curl mydomain.io/test/moretest
404 page not found
$ kubectl logs test-server
Request method=GET path=/moretest status=404 user-agent=curl/7.29.0
redirect however, works like this:
# curl mydomain.io/test/moretest
Moved Permanently
# curl mydomain.io/moretest
404 page not found
$ kubectl logs test-server
Request method=GET path=/test/moretest status=302 user-agent=curl/7.29.0
Request method=GET path=/moretest status=404 user-agent=curl/7.29.0
I'm not familiar with Nginx. I know how to achieve this with Traefik, though. For instance, this yaml
file will do:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: myappA
namespace: namespaceA
annotations:
traefik.ingress.kubernetes.io/rule-type: PathPrefixStrip
spec:
rules:
- host: mydomain.io
http:
paths:
- path: /namespaceA
backend:
serviceName: myapp
servicePort: 80
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: myappB
namespace: namespaceB
annotations:
traefik.ingress.kubernetes.io/rule-type: PathPrefixStrip
spec:
rules:
- host: mydomain.io
http:
paths:
- path: /namespaceB
backend:
serviceName: myapp
servicePort: 80
All the request for /namespaceA/ready
will be rewritten to /ready
then being sent to myapp
in namespaceA
.
All the request for /namespaceB/ready
will be rewritten to /ready
then being sent to myapp
in namespaceB
.
In addition to Lentil1016 answer, here is the example of the same rewrite solution for nginx-ingress-controller.
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
ingress.kubernetes.io/ssl-redirect: 'false'
nginx.ingress.kubernetes.io/force-ssl-redirect: 'false'
nginx.ingress.kubernetes.io/rewrite-target: /$2
name: myapp
namespace: namespaceA
spec:
rules:
- host: mydomain.io
http:
paths:
- backend:
serviceName: myapp
servicePort: 80
path: /namespaceA(/|$)(.*)
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
ingress.kubernetes.io/ssl-redirect: "false"
nginx.ingress.kubernetes.io/force-ssl-redirect: "false"
nginx.ingress.kubernetes.io/rewrite-target: /$2
name: myapp
namespace: namespaceB
spec:
rules:
- host: mydomain.io
http:
paths:
- backend:
serviceName: myapp
servicePort: 80
path: /namespaceB(/|$)(.*)
For example, the ingress definition above will result in the following rewrites:
For destination service myapp in the namespace namespaceA:
mydomain.io/namespaceA rewrites to mydomain.io/
mydomain.io/namespaceA/ rewrites to mydomain.io/
mydomain.io/namespaceA/ready/ rewrites to mydomain.io/ready/
For destination service myapp in the namespace namespaceB:
mydomain.io/namespaceB rewrites to mydomain.io/
mydomain.io/namespaceB/ rewrites to mydomain.io/
mydomain.io/namespaceB/ready/ rewrites to mydomain.io/ready/
Note: You may need to use nginx-config ConfigMap to completely switch off ssl-redirect for nginx-ingress-controller.
Note: There are two kinds of nginx-ingress-controllers, kubernetes and nginxinc. ConfigMap options and annotations could be different for each of them.
kind: ConfigMap
apiVersion: v1
metadata:
name: nginx-config
namespace: nginx-ingress # <--- or ingress-nginx, depends on your installation
data:
redirect-to-https: "false"
ssl-redirect: "false"