Kubernetes Ingress - referring external path to another path in service

8/28/2019

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.

-- SagiLow
kubernetes
kubernetes-ingress
nginx-ingress

2 Answers

8/28/2019

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.

-- Lentil1016
Source: StackOverflow

9/2/2019

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"
-- VAS
Source: StackOverflow