NodeJS Service is not reachable on Kubernete (GCP)

8/6/2019

I have a true roadblock here and I have not found any solutions so far. Ultimately, my deployed NodeJS + Express server is not reachable when deploying to a Kubernete cluster on GCP. I followed the guide & example, nothing seems to work.

The cluster, node and service are running just fine and don't have any issues. Furthermore, it works just fine locally when running it with Docker.

Here's my Node YAML:

apiVersion: apps/v1
kind: Deployment
metadata:
  annotations:
    deployment.kubernetes.io/revision: "1"
  creationTimestamp: 2019-08-06T04:13:29Z
  generation: 1
  labels:
    run: nodejsapp
  name: nodejsapp
  namespace: default
  resourceVersion: "23861"
  selfLink: /apis/apps/v1/namespaces/default/deployments/nodejsapp
  uid: 8b6b7ac5-b800-11e9-816e-42010a9600de
spec:
  progressDeadlineSeconds: 2147483647
  replicas: 1
  revisionHistoryLimit: 10
  selector:
    matchLabels:
      run: nodejsapp
  strategy:
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 1
    type: RollingUpdate
  template:
    metadata:
      creationTimestamp: null
      labels:
        run: nodejsapp
    spec:
      containers:
      - image: gcr.io/${project}/nodejsapp:latest
        imagePullPolicy: Always
        name: nodejsapp
        ports:
        - containerPort: 5000
          protocol: TCP
        resources: {}
        terminationMessagePath: /dev/termination-log
        terminationMessagePolicy: File
      dnsPolicy: ClusterFirst
      restartPolicy: Always
      schedulerName: default-scheduler
      securityContext: {}
      terminationGracePeriodSeconds: 30
status:
  availableReplicas: 1
  conditions:
  - lastTransitionTime: 2019-08-06T04:13:29Z
    lastUpdateTime: 2019-08-06T04:13:29Z
    message: Deployment has minimum availability.
    reason: MinimumReplicasAvailable
    status: "True"
    type: Available
  observedGeneration: 1
  readyReplicas: 1
  replicas: 1
  updatedReplicas: 1

Service YAML:

apiVersion: v1
kind: Service
metadata:
  creationTimestamp: 2019-08-06T04:13:34Z
  labels:
    run: nodejsapp
  name: nodejsapp
  namespace: default
  resourceVersion: "25444"
  selfLink: /api/v1/namespaces/default/services/nodejsapp
  uid: 8ef81536-b800-11e9-816e-42010a9600de
spec:
  clusterIP: XXX.XXX.XXX.XXX
  externalTrafficPolicy: Cluster
  ports:
  - nodePort: 32393
    port: 80
    protocol: TCP
    targetPort: 5000
  selector:
    run: nodejsapp
  sessionAffinity: None
  type: LoadBalancer
status:
  loadBalancer:
    ingress:
    - ip: XXX.XXX.XXX.XXX

The NodeJS server is configured to run on Port 5000. I tried doing no port-forwarding as well but not a difference in the result.

Any help is much appreciated.

UPDATE: I used this guide and followed the instructions: https://cloud.google.com/kubernetes-engine/docs/tutorials/hello-app

UPDATE 2: FINALLY - figured it out. I'm not sure why this is not mentioned anywhere but you have to create an Ingress that routes the traffic to the pod accordingly.

Here's the example config:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  annotations:
    ingress.kubernetes.io/backends: '{"k8s-be-32064--abfe1f07378017e9":"HEALTHY"}'
    ingress.kubernetes.io/forwarding-rule: k8s-fw-default-nodejsapp--abfe1f07378017e9
    ingress.kubernetes.io/target-proxy: k8s-tp-default-nodejsapp--abfe1f07378017e9
    ingress.kubernetes.io/url-map: k8s-um-default-nodejsapp--abfe1f07378017e9
  creationTimestamp: 2019-08-06T18:59:15Z
  generation: 1
  name: nodejsapp
  namespace: default
  resourceVersion: "171168"
  selfLink: /apis/extensions/v1beta1/namespaces/default/ingresses/versapay-api
  uid: 491cd248-b87c-11e9-816e-42010a9600de
spec:
  backend:
    serviceName: nodejsapp
    servicePort: 80
status:
  loadBalancer:
    ingress:
    - ip: XXX.XXX.XXX
-- jP_
docker
google-cloud-platform
kubernetes
node.js

2 Answers

8/6/2019

Adding it as an answer as need to include image (But not necessarily an answer):

As shown in the image, besides your backend service, a green tick should be visible

enter image description here

Probable Solution:

In your NodeJsApp, please add the following base URL .i.e.,

When the application is started locally, http://localhost:5000/ should return a 200 status code (With ideally Server is running... or some message)

And also, if path based routing is enabled, another base URL is also required:

http://localhost:5000/<nodeJsAppUrl>/ should also return 200 status code.

Above URLs are required for health check of both LoadBalancer and Backend Service and redeploy the service.

Please let me know if the above solution doesn't fix the said issue.

-- Sagar Chilukuri
Source: StackOverflow

8/6/2019

You need an intermediate service to internally expose your deployment.

Right now, you have a set of pods grouped in a deployment and a load balancer exposed in your cluster but you need to link them with an additional service.

You can try using a NodePort like the following:

apiVersion: v1
kind: Service
metadata:
  name: nodejsapp-nodeport
spec:
  selector:
    run: nodejsapp
  ports:
  - name: default
    protocol: TCP
    port: 32393
    targetPort: 5000
  type: NodePort    

This NodePort service is in between your Load Balancer and the pods in your deployment, targeting them in port 5000 and exposing port 32393 (as per your settings in the original question, you can change it).

From here, you can redeploy your Load Balancer to target the previous NodePort. This way, you can reach your NodeJS app via port 80 from your load balancer public address.

apiVersion: v1
kind: Service
metadata:
  name: nodejs-lb
spec:
  selector:
    run: nodejsapp
  ports:
  - name: default
    protocol: TCP
    port: 80
    targetPort: 32393
  type: LoadBalancer

The whole scenario would look like this:

publicy exposed address --> LoadBalancer --> | NodePort --> Deployment --> Pods
-- yyyyahir
Source: StackOverflow