Search code examples
nginxkuberneteskubernetes-ingressnginx-ingress

Kubernetes Ingress Exact not prioritized over Prefix


In Kubernetes we need a new service to handle the root path, but but still a catch everything else on our current frontend.

Current frontend Ingress

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: current-frontend
  labels:
    app: current-frontend
    tier: frontend
  annotations:
    kubernetes.io/ingress.class: nginx
spec:
  tls:
    - hosts:
      - my.domain.com
      secretName: tls-secret
  rules:
    - host: my.domain.com
      http:
        paths:
          - backend:
              service:
                name: current-frontend
                port:
                  number: 80
            path: /
            pathType: Prefix

New service Ingress

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: new-service
  labels:
    app: new-service
    tier: frontend
  annotations:
    kubernetes.io/ingress.class: nginx
spec:
  tls:
  - hosts:
    - my.domain.com
    secretName: tls-secret
  rules:
  - host: my.domain.com
    http:
      paths:
      - backend:
          service:
            name: new-service
            port:
              number: 80
        path: /someendpoint
        pathType: ImplementationSpecific
      - backend:
          service:
            name: new-service
            port:
              number: 80
        path: /
        pathType: Exact

According to the documentation of Kuberntes Ingress, it should prioritize Exact over Prefix

If two paths are still equally matched, precedence will be given to paths with an exact path type over prefix path type.

https://kubernetes.io/docs/concepts/services-networking/ingress/#multiple-matches

The problem is that everything else then my.domain.com/someendpoint goes to the current-frontend, while the expected would be that my.domain.com/ would go to new-service.

How do I achieving this?


Solution

I got it working, even If it doesn't seams to be the optimal solution (According to the Documentation)

I Followed Hemanth Kumar's answer and changed the Current Frontend to use Regex, with (.+) instead of (.*) as I wanted at least one char after the slash for it to be hit.

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: current-frontend
  labels:
    app: current-frontend
    tier: frontend
  annotations:
    nginx.ingress.kubernetes.io/use-regex: "true"
    kubernetes.io/ingress.class: nginx
spec:
  tls:
    - hosts:
      - my.domain.com
      secretName: tls-secret
  rules:
    - host: my.domain.com
      http:
        paths:
          - backend:
              service:
                name: current-frontend
                port:
                  number: 80
            path: /(.+)
            pathType: Prefix

At the same time I needed to change the New service to use Prefix instead of Exact as it does not work, event if there is no other services to hit.

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: new-service
  labels:
    app: new-service
    tier: frontend
  annotations:
    kubernetes.io/ingress.class: nginx
spec:
  tls:
  - hosts:
    - my.domain.com
    secretName: tls-secret
  rules:
  - host: my.domain.com
    http:
      paths:
      - backend:
          service:
            name: new-service
            port:
              number: 80
        path: /someendpoint
        pathType: ImplementationSpecific
      - backend:
          service:
            name: new-service
            port:
              number: 80
        path: /
        pathType: Prefix

Solution

  • Ingress path matching can be enabled by setting the

    nginx.ingress.kubernetes.io/use-regex annotation to true .

    See the description of the use-regex annotation :

    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: test-ingress
      annotations:
        nginx.ingress.kubernetes.io/use-regex: "true"
    spec:
      ingressClassName: nginx
      rules:
      - host: test.com
        http:
          paths:
          - path: /foo/.*
            pathType: Prefix
            backend:
              service:
                name: test
                port:
                  number: 80
    

    Refer to this ingress path matching for more information on path priority