I'm trying to change my express server deployment from Deployment to Statefulsets in my Kubernetes cluster. After I added the volumeMounts to the yaml file, I gets the following error from the pod's log:
npm ERR! path /usr/src/app/package.json
npm ERR! code ENOENT
npm ERR! errno -2
npm ERR! syscall open
npm ERR! enoent ENOENT: no such file or directory, open '/usr/src/app/package.json'
npm ERR! enoent This is related to npm not being able to find a file.
npm ERR! enoent
npm ERR! A complete log of this run can be found in:
npm ERR! /root/.npm/_logs/2019-08-23T13_55_03_058Z-debug.log
My previous files:
Dockerfile
FROM node:10.16-alpine
WORKDIR /usr/src/app
COPY package*.json ./
RUN npm install
COPY . .
CMD [ "npm", "start" ]
Service yaml file
apiVersion: v1
kind: Service
metadata:
name: image-server-cluster-ip-service
spec:
type: ClusterIP
selector:
component: image-server
ports:
- port: 3001
targetPort: 3001
deployment yaml file
apiVersion: apps/v1
kind: Deployment
metadata:
name: image-server-deployment
spec:
replicas: 1
selector:
matchLabels:
component: image-server
template:
metadata:
labels:
component: image-server
spec:
containers:
- name: image-server
image: gcr.io/my-project/image-server:v0.0.10
ports:
- containerPort: 3001
env:
- name: MONGO_HOST
value: mongo-cluster-ip-service
- name: MONGO_PORT
value: '27017'
My current file:
headless service file
apiVersion: v1
kind: Service
metadata:
name: image-server-cluster-ip-service
spec:
clusterIP: None
selector:
component: image-server
ports:
- port: 3001
targetPort: 3001
statefulsets yaml file
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: image-server-deployment
spec:
serviceName: "image-server-cluster-ip-service"
replicas: 2
selector:
matchLabels:
component: image-server
template:
metadata:
labels:
component: image-server
spec:
containers:
- name: image-server
image: gcr.io/my-project/image-server:v0.0.10
ports:
- containerPort: 3001
env:
- name: MONGO_HOST
value: mongo-cluster-ip-service
- name: MONGO_PORT
value: '27017'
volumeMounts:
- mountPath: /usr/src/app
name: image-server-vol
volumeClaimTemplates:
- metadata:
name: image-server-vol
spec:
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 1Gi
I think the package.json file might be deleted when I added the volume mount.
What is the proper way to mount the volume to my pod?
You are mouting a voulume image-server-vol which you have not created
Your StatefulSet declaration seems ok.
However, as you're using a volumeClaimTemplates, have you declared a PersistentVolume before applying your configuration ?
In order to use a volumeClaimTemplate, you need to be in the situation described in the official documentation. Especially this sentence :
This tutorial assumes that your cluster is configured to dynamically provision PersistentVolumes. If your cluster is not configured to do so, you will have to manually provision two 1 GiB volumes prior to starting this tutorial
This seems to be working fine:
volumeMounts:
- mountPath: /usr/src/app
name: image-server-vol
But you are mounting over your application's working directory /usr/src/app
. Instead, mount the volume somewhere else like /usr/image
.
From the comment discussion, your use case is to handle users' uploaded files.
You should not use a PV for this use case, for various reasons. One reason is that your two StatefulSet replicas will have different volumes mounted, so if a user uploads a file and that request gets handled by one replica, and then later they try to view their file and that request is handled by the other replica, it won't be there. Consider using a blobstore service like S3, Google Cloud Filestore, Minio, etc. This will require a bit more code for you to write, and probably pull in some client libraries, but it's a better practice.
For your edification, though you shouldn't use PVs for this use case, here's why it was causing the specific error you were seeing: You're mounting the volume to /usr/src/app
so it's going to blow away whatever was at that place in the filesystem within the container, namely all your app source code you put there via the COPY
commands when building your Docker image. In the future when using PVs, be sure to mount the volume to a different path that won't blow away the files you've put there intentionally.