Kubernetes Part 10: How-To Configure Static Persistent Volumes with a Synology NAS

 


A kubernetes cluster is of course useless if you don't have storage to put your data on. To keep kubernetes flexible and scalable you don't store data on your pods. You will loose data and run into issues every time you upgrade, delete or scale the pods if you do that. There are options to store data within the cluster, but I will discuss them in later posts. For now, I have chosen to provide datastorage to the cluster via NFS on my Synology NAS. It is not that hard to install, and it makes it fairly easy to explain how Persistent Volumes en Persistent Volume Claims work within a kubernetes cluster.


So let's start providing storage to our home kubernetes cluster.

- Prepare NFS on your Synology NAS

The following action should be executed on your Synology NAS console

Firs you need to enable NFS via Control Panel -> Files Services and the select the SMB/AFP/NFS tab. Scroll down until you NFS section. Then select the Enable NFS option and select Enable NFSv4.1 support like the screen shot below, and Click Apply.


Next goto the Shared Folder option in the control and create a new share (for example kubedata). Open the share in the Control Panel  and select the NFS Permissions Tab. Click create and use the following value:

  • Hostname of IP: *
  • Privilege: Read Write
  • Squash: No Mapping
  • Security: sys
  • Enable asynchronous
  • Enable Allow users to access mounted subfolder

See also the screenshot blow.


Note the value behind Mount path. In the example above this is /volume1/kubedata. 

- Create subfolder for the kubernetes application (deployment)

Create in the kubedata share a folder called nginx-1

Nginx is the name of a webserver, which we will  use later in the blogpost. 

We now have created a nfs share with a folder on the Synology NAS.

(If you require more information to configure NFS on your Synology NAS, you can find it here )

Now that we have created an NFS share we are able to use it on our kubernetes cluster. We do this using a so called persistent volume, and a persistent volume claim.  

- Create a persistent volume in kubernetes

Execute the following command on your k8s-master server.

nano pv-nfs-kubedata-nginx-1.yaml

Cut and past the text below and save the file

apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-nfs-kubedata-nginx-1  # < Name of the persistent volume
  namespace: default    
spec:
  storageClassName: ""
  capacity:
    storage: 1Gi # < Maximum storage size you want to reserve
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Retain
  mountOptions:
    - hard
    - nfsvers=4.1
  nfs:
    server: xxx.xxx.xxx.xxx  # < The ip adress of your NAS (NFS Server)
    path: "/volume1/kubedata/nginx-1"  # < The NFS volumename 
    readOnly: false
Apply the file via the following command

kubectl apply -f pv-nfs-kubedata-nginx-1.yaml
Check if the persistant volume has been created successfully:

kubectl get pv pv-nfs-kubedata-nginx-1
You should see something similar like






- Create a persistant volume claim in kubernetes

nano pvc-nfs-kubedata-nginx-1.yaml

Cut and past the text below and save the file

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc-nfs-kubedata-nginx-1
  namespace: default
spec:
  storageClassName: ""
  volumeName: pv-nfs-kubedata-nginx-1 # < The volumename needs correpond with the persistent volume
  accessModes:
   - ReadWriteOnce 
  resources:
    requests:
      storage: 1Gi

Apply the file via the following command

kubectl apply -f pvc-nfs-kubedata-nginx-1.yaml
Check if the persistant volume claim has been created successfully:

kubectl get pvc pvc-nfs-kubedata-nginx-1 -n default
It should look like something like this






Please make sure that the status of the persistent volume claim is "BOUND". This means that the claim on the persistent volume is working properly.

Ok. Now the we have create a persisten volume and persisten volume claim.  We will now test it via a deployment of a nginx webserver to see if we can show our own example website. This requires that you have the MetalLB loadbalancer installed on your kubernetes cluster. If you don't have that, please check my previous blog here to install and configure MetalLB.

- Create index.html file on NAS

So the the first we thing do it to create a "website" via an index.html file on the nas.

Cut and paste the text below in notepad on your desktop and save it as index.html file on /volume1/kubedata/nginx-1/ folder on the NAS. 

<!DOCTYPE html>
<html>
<head>
<style>
</style>
</head>
<body>

<h1>Kubernetes - Webtest 1</h1>
<p>This page is located on a persistent volume, and run on a k8s-cluster!</p>

</body>
</html>
It should look similar to this on the Synology NAS



- Create the nginx-website deployment in kubernetes

SSH (putty) into your k8s-master and to the following

nano deploy-nginx-1-k8s.yaml

Cut and paste the text below and save the file 

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-1
  labels:
    app: nginx-1
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx-1
  template:
    metadata:
      labels:
        app: nginx-1
    spec:
      volumes:
      - name: nginx-1-volume
        persistentVolumeClaim:
          claimName: pvc-nfs-kubedata-nginx-1
      containers:
        - image: nginx
          name: nginx-1
          imagePullPolicy: Always
          resources:
           limits:
             memory: 512Mi
             cpu: "1"
           requests:
             memory: 256Mi
             cpu: "0.2"
          volumeMounts:
          - name: nginx-1-volume
            mountPath: /usr/share/nginx/html
---
kind: Service
apiVersion: v1
metadata:
  name: nginx-1-service
spec:
  selector:
    app: nginx-1
  ports:
    - name: http
      port: 80
      protocol: TCP
      targetPort: 80 
  type: LoadBalancer
---


Apply the deployment file with the following command

kubectl apply -f deploy-nginx-1-k8s.yaml

This yaml file will create a service and a deployment. 






Next check the service, to find out the ip on which the nginx-1 website is running.

kubectl get service -n default

You should see something similar to this. The red values should be external IP to access the nginx-1 website.

erikdebont@k8s-master:~$ kubectl get service -n default
NAME              TYPE           CLUSTER-IP      EXTERNAL-IP     PORT(S)        AGE
kubernetes        ClusterIP      10.96.0.1       <none>          443/TCP        46d
nginx-1-service   LoadBalancer   10.103.42.209   xxx.xxx.xxx.xxx 80:31520/TCP   18m
erikdebont@k8s-master:~$

If you open a web browser to http://xxx.xxx.xxx.xxx (your external ip). You should see this webpage, which is the index.html file we have put in the /volume1/kubedata/nginx-1 folder. As you see can NGINX running in kubernetes is using the webpage data located on the Synology NAS.


Hope this blog was helpfull. I you have any questions, do not hesitate to leave a comment in the comment section below.

More Info:

 







Comments