'How does Traefik choose from ingresses with coliding prefixes?

I'm containerizing an existing application and I need a basicauth for a single path prefix, currently I have the following Ingress configuration:

apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
  name: service-auth
spec:
  basicAuth:
    secret: service-auth
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: service
  namespace: default
  annotations:
    kubernetes.io/ingress.class: "traefik"
    cert-manager.io/issuer: "letsencrypt-prod"
    traefik.ingress.kubernetes.io/frontend-entry-points: http, https
    traefik.ingress.kubernetes.io/redirect-entry-point: https

spec:
  tls:
  - hosts:
    - fqdn
    secretName: fqdn-tls
  rules:
    - host: fqdn
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: service
                port:
                  name: http
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: service-auth
  namespace: default
  annotations:
    kubernetes.io/ingress.class: "traefik"
    cert-manager.io/issuer: "letsencrypt-prod"
    traefik.ingress.kubernetes.io/frontend-entry-points: http, https
    traefik.ingress.kubernetes.io/redirect-entry-point: https
    traefik.ingress.kubernetes.io/router.middlewares: default-service-auth@kubernetescrd

spec:
  tls:
  - hosts:
    - fqdn
    secretName: fqdn-tls
  rules:
    - host: fqdn
      http:
        paths:
          - path: /admin/
            pathType: Prefix
            backend:
              service:
                name: service
                port:
                  name: http

This seems to be working, but I just want to make sure - can I rely on the /admin/ prefix to be always picked up by the second ingress or is there a chance that it will be picked up by the ingress with / prefix and thus displayed without basicauth?



Solution 1:[1]

As you can read in this documentation:

Each path in Ingress must have the appropriate path type. Paths without an explicit pathType will not be validated. There are three supported path types:

ImplementationSpecific: With this path type, matching is up to the IngressClass. Implementations can treat this as a separate pathType or treat it identically to Prefix or Exact path types.

Exact: Matches the URL path exactly and with case sensitivity.

Prefix: Matches based on a URL path prefix split by /. Matching is case sensitive and done on a path element by element basis. A path element refers to the list of labels in the path split by the / separator. A request is a match for path p if every p is an element-wise prefix of p of the request path.

Here is also a link for examples in documentation.

Solution 2:[2]

We had a simliar question recently (using traefik as our ingress controller) and apart from the official documentation linked in @kkopczak's answer, we also checked the logic in traefik.

In the documentation under Multiple matches:

In some cases, multiple paths within an Ingress will match a request. In those cases precedence will be given first to the longest matching path. If two paths are still equally matched, precedence will be given to paths with an exact path type over prefix path type.

In the traefik controller, there is a concept of priority:

To avoid path overlap, routes are sorted, by default, in descending order using rules length. The priority is directly equal to the length of the rule, and so the longest length has the highest priority.

Or, directly in the code:

if priority == 0 {
    priority = len(rule)
}

route := r.NewRoute().Handler(handler).Priority(priority)

Here the rule is the path, e.g /admin/. And you can actually set the priority using the following annotation

traefik.ingress.kubernetes.io/router.priority

The Priority of the default backend is per defintion the least important rule - math.MinInt32:

      rt := &dynamic.Router{
            Rule:     "PathPrefix(`/`)",
            Priority: math.MinInt32,
            Service:  "default-backend",
        }

So yes, you can rely on this solution.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 kkopczak
Solution 2 briadeus