Kuldeep
Kuldeep

Reputation: 659

Kubernetes Ingress path based routing not working as expected

I installed NGINX Ingress in kubernetes cluster. When i am trying to access the micro service end via Ingress Controller its not working as expected

I have deployed two spring boot application

Ingress Rules

When i am trying to access one of the service ex. http://test.practice.com/prac/practice/getprac , it does not work

enter image description here

but when i try to access without Ingress path http://test.practice.com/practice/getprac, it works

enter image description here

I am not able to understand why with Ingress path its not working and same happens for other service

Micro service 1 (Port 9090)

apiVersion: apps/v1
kind: Deployment
metadata:
  name: customer
  namespace: practice
  labels: 
    app: customer
spec:
  replicas: 5
  selector:
    matchLabels: 
      app: customer
  template: 
    metadata:
      labels: 
        app: customer
    spec: 
      imagePullSecrets:
      - name: testkuldeepsecret
      containers:
      - name: customer
        image: kuldeep99/customer:v1
        ports:
        - containerPort: 9090
          hostPort: 9090

---
apiVersion: v1
kind: Service
metadata:                     
  name: customer-service
  namespace: practice
  labels: 
spec:                         
  ports: 
  - port: 9090 
    targetPort: 9090
    protocol: TCP
    name: http
  selector:
    app: customer

Micro service 2 (port 8000)

apiVersion: apps/v1
kind: Deployment
metadata:
  name: prac
  namespace: practice
  labels: 
    app: prac
spec:
  replicas: 4
  selector:
    matchLabels: 
      app: prac
  template: 
    metadata:
      labels: 
        app: prac
    spec: 
      imagePullSecrets:
      - name: testkuldeepsecret
      containers:
      - name: prac
        image: kuldeep99/practice:v1
        ports:
        - containerPort: 8000
          hostPort: 8000

---
apiVersion: v1
kind: Service
metadata:                     
  name: prac-service
  namespace: practice
  labels: 
spec:                         
  ports: 
  - port: 8000 
    targetPort: 8000
    protocol: TCP
    name: http
  selector:
    app: prac

Service (customer-service and prac-service)

NAME               TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
customer-service   ClusterIP   10.97.203.19    <none>        9090/TCP   39m
ngtest             ClusterIP   10.98.74.149    <none>        80/TCP     21h
prac-service       ClusterIP   10.96.164.210   <none>        8000/TCP   15m
some-mysql         ClusterIP   None            <none>        3306/TCP   2d16h

Ingress

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: practice-ingress
  namespace: practice
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec: 
  rules:
  - host: practice.example.com
    http: 
      paths:
      - backend:
          serviceName: customer-service
          servicePort: 9090
        path: /customer
      - backend:
          serviceName: prac-service
          servicePort: 8000
        path: /prac

Upvotes: 3

Views: 8735

Answers (3)

L.GANESH
L.GANESH

Reputation: 21

On top the discussion, i observed one thing. We should not confuse with

apiVersion: networking.k8s.io/v1
kind: Ingress

And

apiVersion: networking.k8s.io/v1beta1
kind: Ingress

First ensure which Ingress controller we are using and based on that decide apiVersion. I'm using "ingress-nginx" (not "nginx-ingress"). This one supports "apiVersion: networking.k8s.io/v1beta1" and works charm as per "Arsene" comment.

This Ingress yaml file WORKS with "ingress-nginx" Ingress controller

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  annotations:
    kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.io/rewrite-target: /$2

  name: k8-exercise-03-two-app-ingress
spec:
  rules:
    - host: ex03.k8.sb.two.app.ingress.com
      http:
        paths:
          - backend:
              serviceName: k8-excercise-01-app-service
              servicePort: 8080
            path: /one(/|$)(.*)
          - backend:
              serviceName: k8-exercise-03-ms-service
              servicePort: 8081
            path: /two(/|$)(.*)

But, this Ingress yaml file NOT WORKING with "ingress-nginx" Ingress controller

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
    name: k8-exercise-03-two-app-ingress
    annotations:
       kubernetes.io/ingress.class: "nginx"
#       nginx.ingress.kubernetes.io/use-regex: "true"
       ingress.kubernetes.io/rewrite-target: /$2
spec:
#  ingressClassName: nginx
  rules:
 #192.168.1.5 ex03.k8.sb.com is mapped in host file. 192.168.1.5 is Host machine IP
  - host: ex03.k8.sb.two.app.ingress.com
    http:
        paths:
        - backend:
            service:
                name: k8-excercise-01-app-service
                port:
                    number: 8080  
          path: /one(/|$)(.*)
          pathType: Prefix
          
        - pathType: Prefix
          path: /two(/|$)(.*)
          backend:
            service:
                name: k8-exercise-03-ms-service
                port:
                    number: 8081

I can access the Spring Boot API Calls as like:

For App-1:

http://ex03.k8.sb.two.app.ingress.com/one/
Result: App One - Root

http://ex03.k8.sb.two.app.ingress.com/one/one
Result: App One - One API

http://ex03.k8.sb.two.app.ingress.com/one/api/v1/hello
Result: App One - Hello API

App-2:

http://ex03.k8.sb.two.app.ingress.com/two/message/James%20Bond
Result: App Two- Hi James Bond API

Finally If any one knows how to change "apiVersion: networking.k8s.io/v1" yaml to support "ingress-nginx" Controller, will be appreciate. Thank you. Sorry for long content

Upvotes: 2

Arsene Online
Arsene Online

Reputation: 17

I spend literally a day with this problem. The problem was simply the wrong nginx installed. I used helm found here to install nginx-ingress

Install it, please use helm version 3:

helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm repo update

helm install ingress-nginx ingress-nginx/ingress-nginx

Once run, in the logs you shall see a snippet that illustrates how your ingress should look like. In case you want to do the above, you can the annotation suggested above and henceforth, you can follow tutorials here to achieve more such as rewrite.

My cluster is deployed on GCP using GKE

when done, this is the output log:

NAME: ingress-nginx
LAST DEPLOYED: Sat Apr 24 07:56:11 2021
NAMESPACE: default
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
The ingress-nginx controller has been installed.
It may take a few minutes for the LoadBalancer IP to be available.
You can watch the status by running 'kubectl --namespace default get services -o wide -w ingress-nginx-controller'

An example Ingress that makes use of the controller:

  apiVersion: networking.k8s.io/v1beta1
  kind: Ingress
  metadata:
    annotations:
      kubernetes.io/ingress.class: nginx
    name: example
    namespace: foo
  spec:
    rules:
      - host: www.example.com
        http:
          paths:
            - backend:
                serviceName: exampleService
                servicePort: 80
              path: /
    # This section is only required if TLS is to be enabled for the Ingress
    tls:
        - hosts:
            - www.example.com
          secretName: example-tls

If TLS is enabled for the Ingress, a Secret containing the certificate and key must also be provided:

  apiVersion: v1
  kind: Secret
  metadata:
    name: example-tls
    namespace: foo
  data:
    tls.crt: <base64 encoded cert>
    tls.key: <base64 encoded key>
  type: kubernetes.io/tls

This is how it looks like now after installing it:

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  annotations:
    kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.io/rewrite-target: /$2

  name: example
  # namespace: foo
spec:
  rules:
    - host: [your ip address].sslip.io
      http:
        paths:
          - backend:
              serviceName: registry-app-server
              servicePort: 8761
            path: /eureka/(.*)
          - backend:
              serviceName: api-gateway-server
              servicePort: 7000
            path: /api(/|$)(.*)

As you can see I am deploying spring micro-services using kubernetes(gke). There are a lot of benefits of using nginx-ingress over built-in gke ingress, and it is more popular than its counterparts

Upvotes: 1

Arghya Sadhu
Arghya Sadhu

Reputation: 44549

You have installed this nginx ingress

nginx.ingress.kubernetes.io/rewrite-target: / annotation to work properly you need to install this nginx ingress.

Alternative way to solve this issue is to configure contextPath to /prac in the spring application

Upvotes: 5

Related Questions