Image works on Docker but not on Kubernetes

I have a simple Dockerfile:

FROM nodered/node-red

# Copy package.json to the WORKDIR so npm builds all
COPY package.json .
COPY node-red-static .
COPY defaults .
RUN npm install --unsafe-perm --no-update-notifier --no-fund --only=production

# NodeRED configuration
COPY .node-red/settings.js /usr/src/node-red/.node-red/settings.js
COPY .node-red/flows.json /data/flows.json

That I turned into an image and run it using:

docker run -it --rm -p 1880:1880/tcp ghcr.io/myorg/myImage:latest

Works like a charm. Now I tried to deploy that to a MicroK8S Kubernetes instance using a deployment

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nodered-deployment
  labels:
    app: core
spec:
  replicas: 2
  selector:
    matchLabels:
      app: core
  template:
    metadata:
      labels:
        app: core
    spec:
      containers:
      - name: core
        image: ghcr.io/myorg/myImage:latest
        ports:
        - containerPort: 1880
        imagePullPolicy: Always
        volumeMounts:
          - name:  facility-volume
            mountPath:  '/opt/facility/facility.json'
            subPath: facility.json
          - name: core-export
            mountPath: "/export"  
        resources:
          limits:
            memory: "8Mi"
            cpu: "500m"
        envFrom:
        - secretRef:
            name: core-secret    
      imagePullSecrets:
      - name: regcred 
      volumes:
        - name: facility-volume
          configMap:
            name: facility-map
        - name: core-export
          persistentVolumeClaim:
            claimName: export-pv-claim 

K8S indicates a successful deployment, but port 1880 is silent.
So I checked the log of the pod. It contains exactly 2 lines:

core@0.1.0 start /usr/src/node-red
node-red --settings ./.node-red/settings.js --userDir ./.node-red "--userDir" "/data" 

Then I checked ps -A and get

PID   USER     TIME  COMMAND
    1 node-red  0:09 npm
   16 node-red  2:08 node /usr/src/node-red/node_modules/.bin/node-red --settin
   30 node-red  0:00 /bin/sh
   35 node-red  0:00 ps -A

Which would indicate, the application is running? (Or stuck?)
What do I miss?

Update: I tried the same with a naked image:

kind: Deployment
metadata:
  name: red-playground
  labels:
    app: red-playground
spec:
  replicas: 2
  selector:
    matchLabels:
      app: red-playground
  template:
    metadata:
      labels:
        app: red-playground
    spec:
      containers:
      - name: red-playground
        image: nodered/node-red:latest
        ports:
        - containerPort: 1880
        imagePullPolicy: Always 
        resources:
          limits:
            memory: "8Mi"
            cpu: "500m"   
      imagePullSecrets:
      - name: regcred 
---
apiVersion: v1
kind: Service
metadata:
  name: red-service
  labels:
    app: red-playground
spec:
  type: ClusterIP
  ports:
  - name: http
    port: 1880
    protocol: TCP
    targetPort: 1880
  selector:
    app: red-playground
  sessionAffinity: ClientIP

There the log says:

> node-red-docker@1.3.4 start /usr/src/node-red
> node $NODE_OPTIONS node_modules/node-red/red.js $FLOWS "--userDir" "/data"
5 May 04:21:33 - [info] 
Welcome to Node-RED
===================
5 May 04:21:35 - [info] Node-RED version: v1.3.4
5 May 04:21:35 - [info] Node.js  version: v10.24.1
5 May 04:21:35 - [info] Linux 5.8.0-50-generic x64 LE

But no luck on port 1880. I must be missing something?

Looks like you might need to use a NodePort instead of a ClusterIP in your service to expose the two node-red replicas outside your cluster (assuming these replicas are on a single node)

@NotQuiteAllThere : got an example YAML I can learn from?

# node-red deployment
apiVersion: apps/v1
kind: Deployment
metadata:
  name: node-red-deployment
  labels:
    app: node-red
spec:
  replicas: 1
  selector:
    matchLabels:
      app: node-red
  template:
    metadata:
      labels:
        app: node-red
    spec:
      containers:
      - name: node-red
        image: nodered/node-red:latest
        ports:
        - containerPort: 1880
---
# node-red service
apiVersion: v1
kind: Service
metadata:
  name: node-red-service
  labels:
    app: node-red
spec:
  type: NodePort
  selector:
    app: node-red
  ports:
    - protocol: TCP
      port: 1880
      targetPort: 1880
      nodePort: 30330

With the above you'll need access to the latest Node Red image. For minikube:

minikube cache add nodered/node-red:latest

And to access the service, you'll need to get hold of the cluster's ip address. For minikube:

minikube ip

Then to access the cluster use the returned IP address and the port defined in the service (30330 in the service above).

http://<ip-address-of-cluster>:30330

Be careful though, kubernetes applications are meant to be stateless so you might lose Node Red data if you don't use persistent volumes for the /data volume. However the above should be a good starting point or useful as a proof-of-concept.

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.