Can later ingress subpaths override earlier ingress parent paths?

10/16/2018

I have a Kubernetes ingress that I want to be the default for all paths on a set of hosts, provided there is not a more specific match:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: default-ing
spec:
  rules:
  - host: host1.sub.example.com
    http:
      paths:
      - backend:
          serviceName: my-default-service
          servicePort: http
        # Note: here we specify the root path intended as a default
        path: /
      - backend:
          serviceName: my-default-service
          servicePort: http
        path: /route/path/to/default

A second ingress defines a custom service for a specific path:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: special-ing
spec:
  rules:
  - host: host1.sub.example.com
    http:
      paths:
      - backend:
          serviceName: special-service
          servicePort: http
        path: /special

I would expect that the order of adding/deleting the ingresses would not matter, or at least I could have some way of indicating that the path: / in default-ing is always to be ordered last.

When I try the above, the routing is fine as long as I add special-ing before default-ing (or alternatively, add default-ing, then the special-ing, then delete default-ing and re-add it again). When I add them as default-ing, then special-ing, requests to /special are routed to my-default-service instead of special-service.

I want the order of adding/deleting to be independent of the routing that is generated by nginx-ingress-controller, so that my kubectl manipulations are more robust, and if one of the ingresses is recreated nothing will break.

I'm using nginx-ingress-controller:0.19.0

Thanks for any help you can offer!

-- Michael FiG
kubernetes
nginx-ingress

1 Answer

10/16/2018

The short answer is no. I believe your configs should be disallowed by the nginx ingress controller or documented somewhere. Basically what's happening when you have 2 hosts rules with the same value: host1.sub.example.com one is overwriting the other in the server {} block in the nginx.conf that your nginx ingress controller is managing.

So if your add default-ing before special-ing then special-ing will be the actual config. When you add special-ing before default-ing then default-ing will be your only config, special-ing is not supposed to work at all.

  1. Add special-ing, and the configs look something like this:

     server {
         server_name host1.sub.example.com;
         ...
         location /special {
                            ...
         }
         location / { # default backend
                     ...
         }
         ...            
    }
    
  2. Now add default-ing, and the configs will change to like this:

    server {
         server_name host1.sub.example.com;
         ...
         location /route/path/to/default {
                                         ...
         }
         location / { # default backend
                     ...
         }
         ...
    }
    

If you add them the other way around the config will look like 1. in the end.

You can find more by shelling into your nginx ingress controller pod and looking at the nginx.conf file.

 $ kubectl -n <namespace> exec -it nginx-ingress-controller-pod sh
 # cat /etc/nginx/nginx.conf
-- Rico
Source: StackOverflow