GKE Ingres and GCE Load balancer : Always get 404

7/14/2021

I try to deploy 2 applications (behind 2 separates Deployments objects). I have 1 Service per Deployment, with type NodePort.

application1_service.yaml

apiVersion: v1
kind: Service
metadata:
  name: application1-service
  namespace: default
spec:
  ports:
  - port: 80
    protocol: TCP
    targetPort: 80
  selector:
    run: application1
  type: NodePort

application2_service.yaml is the exact same (except for name and run)

I use an Ingress to make the 2 services available,

ingress.yaml

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: my-ingress
  annotations:
    kubernetes.io/ingress.global-static-ip-name: "my-static-ip"
    networking.gke.io/managed-certificates: "my-certificate"
    kubernetes.io/ingress.class: "gce"
spec:
  rules:
  - host: "my.host.com"
    http:
      paths:
      - path: /*
        backend:
          serviceName: application1-service
          servicePort: 80
      - path: /application2/*
        backend:
          serviceName: application2-service
          servicePort: 80

I also create a ManagedCertificate object, to be able to handle HTTPS requests.

managed_certificate.yaml

apiVersion: networking.gke.io/v1beta1
kind: ManagedCertificate
metadata:
  name: my-certificate 
spec:
  domains:
    - my.host.com

The weird thing here is that curl https://my.host.com/ works fine and I can access my service, but when I try curl https://my.host.com/application2/, I keep getting 404 Not Found.

Why is the root working and not the other ?

Additional info: The ManagedCertificate is valid and works fine with /. application1 and application2 are the exact same app and if I swap them in the ingress, the output is the same.

Thanks for your help !

EDIT:

Here is the 404 I get when I try to access application2

404

Don't know if it can help but here is also the part of the Ingress access logs showing the 404

LOGS

-- Agudolive
gcp-load-balancer
google-kubernetes-engine
kubernetes
kubernetes-ingress

3 Answers

7/14/2021

i think you can't use the same port for 2 different applications because this port is used on every node to route to one app.

From docs:

NodePort: Exposes the Service on each Node's IP at a static port (the NodePort). A ClusterIP Service, to which the NodePort Service routes, is automatically created. You'll be able to contact the NodePort Service, from outside the cluster, by requesting <NodeIP>:<NodePort>.

So in your case one app is already using port 80, you could try to use a different one for application 2

-- bern.ar
Source: StackOverflow

7/16/2021
  • I have replicated the problem without a domain and managed a Certificate. For me it's working fine using the Load Balancer IP address.

               (ingress-316204)$ curl http://<LB IP address>/v2/
                               Hello, world!
                               Version: 2.0.0
                               Hostname: web2-XXX
    
               (ingress-316204)$ curl http://<LB IP address>/
                               Hello, world!
                               Version: 1.0.0
                               Hostname: web-XXX
  • Ingress configuration seems to be correct as per doc. Check if curl https://LB IP address/application2/ is working or not, if it's working then there might be some issue with the host name.

  • Check if you have updated the host file (/etc/hosts) with line LB IP address my.host.com.

  • Check if host, path and backend are configured correctly in Load Balancer configuration.

  • If still having the problem then check Port,Nodeport and Targetport configured correctly or else share the output of ‘kubectl describe ing my-ingress’ for further investigation.

-- Priya Gaikwad
Source: StackOverflow

7/20/2021

Answering my own question:

After searching for days, I ultimately found the reason of the problem.

Everything was fine with the cluster and the configs, my problem was from my Flask API.

All the URLs was like this one:

@app.route("/my_function")

So it was working fine on root path with my.host.com/my_function, but when I was typing my.host.com/application1/my_function it wasn't working...

I just changed my app to

@app.route("/application1/my_function")

Everything works fine now :) Hope it will help !

-- Agudolive
Source: StackOverflow