How to mount a volume to a pod in Kubernetes

8/23/2019

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?

-- Jack
kubernetes
volume

4 Answers

8/23/2019

You are mouting a voulume image-server-vol which you have not created

-- RAMNEEK GUPTA
Source: StackOverflow

8/23/2019

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

-- Marc ABOUCHACRA
Source: StackOverflow

8/23/2019

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.

-- Jamie
Source: StackOverflow

8/23/2019

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.

-- Amit Kumar Gupta
Source: StackOverflow