Path Based Routing with Nginx Controller not working

5/31/2020

I have been trying my Nginx Path-Based routing to work, however, after spending almost 4 hours, I am failed to understand, why is it not working. I have gone through almost every possible answer on StackOverflow before anyone downgrades my question, but none worked for me.

So here what I did:

  1. I installed nginx-ingress using Helm 3 (https://docs.nginx.com/nginx-ingress-controller/installation/installation-with-helm/) in a separate namespace - nginx-test:

    helm install my-release nginx-stable/nginx-ingress

A version of the ingress controller (https://hub.helm.sh/charts/nginx-edge/nginx-ingress):

$ POD_NAME=$(kubectl get pods -l app=nginx-controller-nginx-ingress -o jsonpath='{.items[0].metadata.name}')
$ 
$ kubectl exec -it $POD_NAME -- /nginx-ingress --version
Version=edge GitCommit=50e908aa
$ 
  1. There are 2 basic nginx deployments, 2 services already configured in the same namespace, and working fine when I configure host-based routing for them.

  2. Below one works fine for me (when I define host-based routing and get the required page index.html when I run both individual URLs):

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: nginx-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /$1
spec:
  rules:
  - host: nginx1.example.com
    http:
      paths:
      - path: /
        backend:
          serviceName: nginx1
          servicePort: 80

  - host: nginx2.example.com
    http:
      paths:
      - path: /
        backend:
          serviceName: nginx2
          servicePort: 80

Now I wanted to achieve the same result using Path-Based routing, where there will be 1 URL and 2 Paths /nginx1 (pointing to nginx1 service) and /nginx2 (pointing to nginx2 service). So I configured the below ingress resource (and many permutations and combinations I applied based on different examples on internet), none of them worked for me.

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: ingress-path-based
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /$1
    kubernetes.io/ingress.class: "nginx"
spec:
  rules:
  - host: nginx.example.com
    http:
      paths:
      - path: /nginx1
        backend:
          serviceName: nginx1
          servicePort: 80
      - path: /nginx2
        backend:
          serviceName: nginx2
          servicePort: 80

When I access services directly, it works fine, however when I try to access - curl http://nginx.example.com/nginx1 or curl http://nginx.example.com/nginx2 - I get 404 Not Found error.

I was expecting to receive the same response which I was getting for Host-Based routing. But it does not seem to work.

-- Gaurav Bhaskar
kubernetes
kubernetes-ingress
nginx-ingress

1 Answer

6/1/2020

So finally I had to install the controller using manifests, instead of helm charts (edge version).

I installed it from here (https://kubernetes.github.io/ingress-nginx/deploy/#bare-metal), changed NodePort to LoadBalancer to get a LoadBalancer IP. I am using MetalLB on BareMetal.

$ POD_NAME=$(kubectl get pods -n $POD_NAMESPACE -l app.kubernetes.io/component=controller -o jsonpath='{.items[0].metadata.name}')
$ kubectl exec -it $POD_NAME -n $POD_NAMESPACE -- /nginx-ingress-controller --version
-------------------------------------------------------------------------------
NGINX Ingress controller
  Release:       0.32.0
  Build:         git-446845114
  Repository:    https://github.com/kubernetes/ingress-nginx
  nginx version: nginx/1.17.10

-------------------------------------------------------------------------------

$ 

My Ingress resource looks like the same which I posted while asking the question.

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: ingress-path-based
  annotations:
    kubernetes.io/ingress.class: "nginx"
    nginx.ingress.kubernetes.io/rewrite-target: /$1
spec:
  rules:
  - host: nginx.gofork8s.com
    http:
      paths:
      - path: /nginx1
        backend:
          serviceName: nginx1
          servicePort: 80
      - path: /nginx2
        backend:
          serviceName: nginx2
          servicePort: 80

Modified the new LoadBalancer IP in /etc/hosts file to get the domain work.

192.168.0.1 nginx.example.com

Now I am able to access - http://nginx.example.com/nginx1 and http://nginx.example.com/nginx2.

I hope it will help someone. I still need to figure out settings with Helm Charts.

-- Gaurav Bhaskar
Source: StackOverflow