Azure / application-gateway-kubernetes-ingress

This is an ingress controller that can be run on Azure Kubernetes Service (AKS) to allow an Azure Application Gateway to act as the ingress for an AKS cluster.
https://azure.github.io/application-gateway-kubernetes-ingress
MIT License
677 stars 421 forks source link

Support re-write URLs capability in Ingress Resources #49

Closed asridharan closed 5 years ago

asridharan commented 6 years ago

Is your feature request related to a problem? Please describe. In order to support multiple services in the same domain it becomes a requirement to support URL re-write in ingress, especially if its not feasible to change the service pods running on AKS.

Describe the solution you'd like The nginx ingress controller already supports re-writes using annotations. We probably need to support something similar. https://github.com/kubernetes/ingress-nginx/tree/master/docs/examples/rewrite The above would imply that we would need one ingress resource per service for the re-write to take affect, but that should be an acceptable trade-off.

asridharan commented 6 years ago

Currently, Application Gateway v2 doesn't support URL re-writes, so we will need to wait for Application Gateway v2 to add this support before we can introduce this in ingress controller.

knom commented 5 years ago

How about the "Override Backend Path" feature? image

Is that supported, @asridharan ?

asridharan commented 5 years ago

@akshaysngupta had the same suggestion @knom . The problem with just using an override vs full re-write capabilities is that it is very restricted in its ability so we wanted to wait for the full re-write capabilities to land to introduce this. That said I do see the value in building this out incrementally by using the override feature as a segway to full URL re-write capabilities.

We will need to introduce annotations to introduce these overrides so will have to think a lot of about these annotations.

knom commented 5 years ago

Thanks @asridharan! WITHOUT rewrite or override..

Assuming you have two rules:

Am I correct that backend 1 would have to host the site under "/foo/" and backend 2 under "/bar/" as well (unless we have the rewriting?)

This seems broken, as it means you're tying the actual backend to the config of the gateway :-(

asridharan commented 5 years ago

@knom I agree the current functionality is a bit restrictive and we want to fix it before we mark the ingress controller stable. Hence, we probably should support override sooner rather than later since it brings it in parity with AG.

asridharan commented 5 years ago

@knom #111 should fix this. Could you upgrade your helm to try this?

You will need to use the backen prefix annotation to use use the backend override in AG: https://github.com/Azure/application-gateway-kubernetes-ingress/blob/master/docs/annotations.md#backend-path-prefix

dkulig commented 5 years ago

@asridharan - I've just bounced my deployment to use newest version of kubernetes-ingress (0.2.0) but it doesn't seem to solve issue here.

My spec:

1 backend service (svc-a) with 2 endpoints:

Ingress spec:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: svc-a-ingress
  annotations:
    kubernetes.io/ingress.class: azure/application-gateway
    appgw.ingress.kubernetes.io/backend-path-prefix: "/a/"
spec:
  rules:
  - http:
      paths:
        - backend:
            serviceName: svc-a
            servicePort: 80

I got 404 when calling both:

Did I misunderstood purpose of #111 ?

asridharan commented 5 years ago

@dkulig guess need to document this a bit better.

The annotation:

appgw.ingress.kubernetes.io/backend-path-prefix: "/a/"

Will just override your path rule in that ingress resource with the value of the annoation. So in your case, I guess "/" will get overriden by "/a/" and that's probably why you are getting a 404.

Question: Are you able to hit the endpoints with just: http://my-app-gw-uri/ping and http://my-app-gw-uri/_status

since the ingress already sets up the "/" route?

dkulig commented 5 years ago

@asridharan neither endpoint mentioned by you works. No matter what I try to hit I get 404. I'd be grateful to get some explanation what should I expect with the setup I used.

asridharan commented 5 years ago

@dkulig let me restate: http://my-app-gw-uri/ping and http://my-app-gw-uri/_status should work without the backend prefix annotation to your resource. With the backend prefix annotation you have added: appgw.ingress.kubernetes.io/backend-path-prefix: "/a/" http://my-app-gw-uri/ping I think would be sent to the backend as http://my-app-gw-uri/a/ping which would fail. Also, http://my-app-gw-uri/a/ping I think it would be re-written to http://my-app-gw-uri/a/a/ping which would also fail.

Let me verify on my end that this is the behavior for / path, but that's my thesis as to why this is not working. Does that help?

dkulig commented 5 years ago

@asridharan Yeah this is correct. To clarify on my end, what I wanted to achieve is to prefix my services because I'll be running multiple backend services in cluster where every single service has mounted _status and ping endpoint on root ie.

therefore I'll be able to hit:

asridharan commented 5 years ago

I see. I think this ingress definition should work:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: svc-a-ingress
  annotations:
    kubernetes.io/ingress.class: azure/application-gateway
    appgw.ingress.kubernetes.io/backend-path-prefix: "/"
spec:
  rules:
  - http:
      paths:
        - path: /service-a/
             backend:
               serviceName: svc-a
               servicePort: 80
       - path: /service-b/
             backend:
                 serviceName: svc-b
                 servicePort: 80

Basically AG will override the URI http://my-app-gw-uri/service-a/ and http://my-app-gw-uri/service-b/ with http://my-app-gw-uri/ before forwarding it to the backend.

I think this ^^ is what you are looking for?

dkulig commented 5 years ago

Awesome! To made it working I had to add *after service name ie.

 - path: /service-a/*
             backend:
               serviceName: svc-a
               servicePort: 80
       - path: /service-b/*
             backend:
                 serviceName: svc-b
                 servicePort: 80

Thank you for clarification @asridharan

asridharan commented 5 years ago

Awesome! To made it working I had to add *after service name ie.

 - path: /service-a/*
             backend:
               serviceName: svc-a
               servicePort: 80
       - path: /service-b/*
             backend:
                 serviceName: svc-b
                 servicePort: 80

Thank you for clarification @asridharan

That's a bit odd. Thought the ingress path should be doing a simple prefix match. Great to see that the backend-prefix annotation is able to solve this case.

asridharan commented 5 years ago

@dkulig would you mind augmenting the doc: https://github.com/Azure/application-gateway-kubernetes-ingress/blob/master/docs/annotations.md#backend-path-prefix

With an example. A PR would be super helpful here.

If not no worries, will do it some time later this week.

dkulig commented 5 years ago

No worries, I'll do that later in the day

asridharan commented 5 years ago

Closing this out.

webrod commented 3 years ago

the doc still says: path: /hello/

instead of: path: /hello/*

does not work without the /*