Home > database >  Path or PathPrefix routing with Traefik on Kubernetes not working
Path or PathPrefix routing with Traefik on Kubernetes not working

Time:01-27

I'm using Traefik 2.7.0 on an AKS Kubernetes Cluster 1.22.6. Currently, everything routes to the same service:

apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: api
  namespace: namespace1
spec:
  entryPoints:
    - websecure
  routes:
    - match: Host(`api.my-domain.com`)
      kind: Rule
      services:
        - name: api
          namespace: namespace1
          port: 80
  tls:
    secretName: api-my-domain-com-cert

I'm currently in the process of externalizing an API resource from this service to a dedicated new service ("/users") because there will be other services in the future that will need the same functionality.

What I'm trying (and failing) to do, is to route calls to "/users" to the new service:

apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: api
  namespace: namespace1
spec:
  entryPoints:
    - websecure
  routes:
    - match: Host(`api.my-domain.com`) && Path(`/users`)
      kind: Rule
      services:
        - name: users-api
          namespace: namespace2
          port: 80
    - match: Host(`api.my-domain.com`)
      kind: Rule
      services:
        - name: api
          namespace: namespace1
          port: 80
  tls:
    secretName: api-baywa-lusy-com-cert

I tried Path(..) and PathPrefix(..). No success. Everything is still routed to the old service. The new service has slightly different output. So I can tell with certainty that it's still routed to the old service.

Adding the priority manually didn't help either:

apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: api
  namespace: namespace1
spec:
  entryPoints:
    - websecure
  routes:
    - match: Host(`api.my-domain.com`) && Path(`/users`)
      kind: Rule
      priority: 2000
      services:
        - name: users-api
          namespace: namespace2
          port: 80
    - match: Host(`api.my-domain.com`)
      kind: Rule
      priority: 1000
      services:
        - name: api
          namespace: namespace1
          port: 80
  tls:
    secretName: api-baywa-lusy-com-cert

Am I Missing something here? Any help is appreciated!

Thanks,

best regards,

Pascal

CodePudding user response:

You can only expose services in the same namespace as your IngressRoute resource. If you watch the logs of your Traefik pod when you deploy your IngressRoute, you should see something like:

time="2023-01-26T13:57:17Z" level=error msg="service namespace2/users-api not in the parent resource namespace namespace1" providerName=kubernetescrd ingress=namespace1 namespace=namespace1

To do what you want, you need to create two separate IngressRoute resources, one in namespace1 and one in namespace2.

In namespace1:

apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  labels:
    app: old-api
  name: old-api
  namespace: namespace1
spec:
  entryPoints:
  - web
  routes:
  - kind: Rule
    priority: 1000
    match: Host(`api.my-domain.com`)
    services:
    - name: old-api
      port: 80

In namespace2:

apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  labels:
    app: new-api
  name: new-api
  namespace: namespace2
spec:
  entryPoints:
  - web
  routes:
  - kind: Rule
    priority: 2000
    match: Host(`api.my-domain.com`) && PathPrefix(`/users`)
    services:
    - name: new-api
      port: 80

You can find all the files I used to test this configuration here.

I don't know if the explicit priorities are necessary or not; it worked for me without them but maybe I was just lucky so I left them there. I would generally assume that a "more specific route" takes precedence over a "less specific route", but I don't know if that's actually true.

  • Related