# Kubernetes: Local Storage and Volume Mounts

I’ve been in the process of migrating from a docker based infrastructure to a kubernetes based infrastructure. The infrastructure was setup with kubeadm on ubuntu and fedora. Though that will be for another blog post.

This blog post will focus on a beta storage volume feature on 1.10, Local. This is a more feature rich variation of hostPath, as local supports a disk, partiion or directory. It can also be used to schedule pods and force them to specific nodes to where the local volume is available. This means in your deployments / pods, you don’t need a nodeSelector when specifying a particular claim.

The first step is to define the local-storage storage class.

kind: StorageClass
apiVersion: storage.k8s.io/v1
name: local-storage
provisioner: kubernetes.io/no-provisioner
volumeBindingMode: WaitForFirstConsumer

Once you have the local storage class defined, you can now create your pv and pvc resources.

apiVersion: v1
kind: PersistentVolume
labels:
app: mqttbridge
name: mqttbridge-pv
spec:
capacity:
storage: 1Gi
# volumeMode field requires BlockVolume Alpha feature gate to be enabled.
volumeMode: Filesystem
accessModes:
persistentVolumeReclaimPolicy: Retain
storageClassName: local-storage
local:
path: /opt/mqttbridge
nodeAffinity:
required:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/hostname
operator: In
values:
- myhost

Then the claim itself, as dynamic provisioning is not yet available. Notice I have a volumeName reference so that the claim will reference a specific defined volume.

kind: PersistentVolumeClaim
apiVersion: v1
labels:
app: mqttbridge
name: mqttbridge-pvc
spec:
volumeName: mqttbridge-pv
accessModes:
resources:
requests:
storage: 1Gi
storageClassName: local-storage

Now for the deployment itself.

apiVersion: apps/v1beta1
kind: Deployment
labels:
app: mqttbridge
name: mqttbridge
spec:
replicas: 1
selector:
matchLabels:
app: mqttbridge
template:
labels:
app: mqttbridge
spec:
containers:
- image: stjohnjohnson/smartthings-mqtt-bridge
name: mqttbridge
volumeMounts:
- name: storage-volume
mountPath: /config
- name: config-volume
mountPath: /config/config.yml
subPath: config.yml
volumes:
- name: storage-volume
persistentVolumeClaim:
claimName: mqttbridge-pvc
- name: config-volume
configMap:
name: mqttbridge-config

A few things to note in this deployment, I am not just using a local persistent volume, but I’m also mounting a folder and a configmap into the same folder. This is using a subPath declaration. This allows to me specify a folder where other config files may reside or the container may use for files. Rather than just put a config.yml in the mounted folder, I can specify that the file be from a configmap for more flexibility.

Kubernetes volume mounts won’t allow for mountPaths to be the same within a single pod, so subPaths allow for some flexibility in this area. It can also be used as described here to mount configmaps and secrets.