Setting up persistent volumes in RWX mode using 
WordPress with OpenEBS over NFS
Many stateful applications like WordPress require persistent storage in Read-Write-Many or RWX mode. OpenEBS is popular in the open source community for its ease of use and it’s simplistic design for pluggable storage engines. Currently, block volume or iSCSI support is provided natively by OpenEBS. Here, native iSCSI support means that the iSCSI stack is part of OpenEBS project and has full support for synchronous replication, granular monitoring, day 2 storage operations like backup restore etc. iSCSI is typically used in Read-Write-Once or RWO mode which is common for all block storage engines. There have been multiple inquiries from the OpenEBS community about RWX support from OpenEBS, in other words, support for NFS. Though native support for NFS is being considered, it is already possible today to provision RWX mode storage using OpenEBS and to use it for applications like WordPress that require RXW mode.
In this blog, an example of WordPress is taken to show how OpenEBS storage volumes are exposed in RWX mode through the use of NFS in between WordPress and the Jiva volumes of OpenEBS.
WordPress, when deployed on Kubernetes, requires both shared storage volumes on NFS and block storage volumes on iSCSI. The shared storage is required to store the core WordPress content or the admin managed content so that all the WordPress PODs can share the same data quickly. When PODs are spawned by Kubernetes on the fly to service more traffic, the PODs need to initialize quickly and require the core data to be available close to the application and in RWX mode. As an extremely high percentage of the shared storage traffic is Read traffic, the RWX volume need not be highly performant for writes and therefore the data can be served through NFS sitting in front of an iSCSI volume.
The typical deployment of a scalable WordPress application is shown in the below diagram.
WordPress deployment architecture
As shown in the above, OpenEBS can be used to serve the storage volumes in both RWO and RWX mode. The NFS storage volume for WordPress is served through the Kubernetes external storage plugin “nfs”. The block storage for the database needs of WordPress is provided through OpenEBS jiva volumes. If distributed databases like Percona or MariaDB are used then a common approach is that the database is deployed as a StatefulSet for horizontal scalability and Jiva volumes are deployed as a single replica. Alternatively one can use MySQL with jiva persistent volume replicating to three copies for enhanced resiliency.
Configuration details of PVCs and Storage Classes
The PVC construct openebs-nfs-pvc and storage class construct openebs-nfs-sc are used to create an NFS share in RWX mode to be consumed by the WordPress pod. The deployment spec of nfs-provisioner uses an OpenEBS PVC claim which dynamically provisions the JIVA volumes in RWO mode and mounts it inside the nfs-provisioner pod. The entire process can take under 10–15 seconds.
A note on the required size of the NFS volume and the provisioned size of Jiva volume
As we are providing RWX volume over and above the RWO Jiva volume, iSCSI space overhead needs to be considered. It is recommended that the OpenEBS storage class specifies 10% more space than what is required by the NFS PVC.
For example of if WordPress NFS PVC spec specifies 100G as the required storage of the NFS volume, it is recommended to request 110G as the required storage from the OpenEBS Jiva volume.
TL;DR
Shared storage can be provisioned in RWX mode on OpenEBS through a single PVC request.
YAML spec examples:
The same YAML spec can be found in the Kubernetes external storage nfs plugin. The YAML specs below show how to automatically provision the OpenEBS iSCSI storage in the nfs-provisioner pod.
YAML spec for NFS provisioner security policy
PodSecurity YAML for openebs nfs provisioner pod
By applying the above YAML we will create PodSecurityPolicy for the NFS server.
YAML spec for ClusterRoleBinding for NFS provisioner
ClusterRoleBinding YAML for OpenEBS nfs provisioner
The above YAML will successfully create role bindings for the NFS provisioner. So its time to configure NFS provisioner YAML to use OpenEBS volumes and apply it to the Kubernetes cluster.
YAML spec for NFS provisioner deployment
<td style=”line-height:20px;position:relative;vertical-align:top;color:rgb(36, 41, 46);font-family:SFMono-Regular, Consolas, “Liberation Mono”, Menlo, Courier, monospace;font-size:12px;overflow:visible;white-space:pre;overflow-wrap:normal;background:transparent;padding:1px 10px;border:0px;text-align:left;padding-top:4px;”–<-
<td style=”line-height:20px;position:relative;vertical-align:top;color:rgb(36, 41, 46);font-family:SFMono-Regular, Consolas, “Liberation Mono”, Menlo, Courier, monospace;font-size:12px;overflow:visible;white-space:pre;overflow-wrap:normal;background:transparent;padding:1px 10px;border:0px;text-align:left;”–<-
<td style=”line-height:20px;position:relative;vertical-align:top;color:rgb(36, 41, 46);font-family:SFMono-Regular, Consolas, “Liberation Mono”, Menlo, Courier, monospace;font-size:12px;overflow:visible;white-space:pre;overflow-wrap:normal;background:transparent;padding:1px 10px;border:0px;text-align:left;”–<-
<td style=”line-height:20px;position:relative;vertical-align:top;color:rgb(36, 41, 46);font-family:SFMono-Regular, Consolas, “Liberation Mono”, Menlo, Courier, monospace;font-size:12px;overflow:visible;white-space:pre;overflow-wrap:normal;background:transparent;padding:1px 10px;border:0px;text-align:left;”–<-
<td style=”line-height:20px;position:relative;vertical-align:top;color:rgb(36, 41, 46);font-family:SFMono-Regular, Consolas, “Liberation Mono”, Menlo, Courier, monospace;font-size:12px;overflow:visible;white-space:pre;overflow-wrap:normal;background:transparent;padding:1px 10px;border:0px;text-align:left;”–<-
1 | |
2 | apiVersion: v1 |
3 | kind: ServiceAccount # Creating a service account for openebs-nfs-provisioner |
4 | metadata: |
5 | name: openebs-nfs-provisioner |
6 | |
7 | apiVersion: v1 |
8 | kind: Service # Creating a service for openebs-nfs-provisioner |
9 | metadata: |
10 | name: openebs-nfs-provisioner |
11 | labels: |
12 | app: openebs-nfs-provisioner |
13 | spec: |
14 | ports: |
15 | – name: nfs |
16 | port: 2049 |
17 | – name: mountd |
18 | port: 20048 |
19 | – name: rpcbind |
20 | port: 111 |
21 | – name: rpcbind-udp |
22 | port: 111 |
23 | protocol: UDP |
24 | selector: |
25 | app: openebs-nfs-provisioner |
26 | |
27 | apiVersion: apps/v1 |
28 | kind: Deployment # Creating deployment for openebs-nfs-provisoner |
29 | metadata: |
30 | name: openebs-nfs-provisioner |
31 | spec: |
32 | selector: |
33 | matchLabels: |
34 | app: openebs-nfs-provisioner |
35 | replicas: 1 |
36 | strategy: |
37 | type: Recreate |
38 | template: |
39 | metadata: |
40 | labels: |
41 | app: openebs-nfs-provisioner |
42 | spec: |
43 | serviceAccount: openebs-nfs-provisioner |
44 | containers: |
45 | – name: openebs-nfs-provisioner |
46 | image: quay.io/kubernetes_incubator/nfs-provisioner:latest |
47 | ports: |
48 | – name: nfs |
49 | containerPort: 2049 |
50 | – name: mountd |
51 | containerPort: 20048 |
52 | – name: rpcbind |
53 | containerPort: 111 |
54 | – name: rpcbind-udp |
55 | containerPort: 111 |
56 | protocol: UDP |
57 | securityContext: |
58 | capabilities: |
59 | add: |
60 | – DAC_READ_SEARCH |
61 | – SYS_RESOURCE |
62 | args: |
63 | – “-provisioner=openebs.io/nfs” # Name of the provisioner |
64 | env: |
65 | – name: POD_IP |
66 | valueFrom: |
67 | fieldRef: |
68 | fieldPath: status.podIP |
69 | – name: SERVICE_NAME |
70 | value: openebs-nfs-provisioner |
71 | – name: POD_NAMESPACE |
72 | valueFrom: |
73 | fieldRef: |
74 | fieldPath: metadata.namespace |
75 | imagePullPolicy: “IfNotPresent” |
76 | volumeMounts: |
77 | – name: export-volume |
78 | mountPath: /export |
79 | volumes: |
80 | – name: export-volume |
81 | persistentVolumeClaim: |
82 | claimName: openebspvc |
83 | |
84 | apiVersion: v1 |
85 | kind: PersistentVolumeClaim # Creating PVC for openebs-nfs-provisoner to mount on it |
86 | metadata: |
87 | name: openebspvc |
88 | spec: |
89 | storageClassName: openebs-jiva-default |
90 | accessModes: |
91 | – ReadWriteOnce |
92 | resources: |
93 | requests: |
94 | storage: “110G” |
95 | |
96 | apiVersion: storage.k8s.io/v1 |
97 | kind: StorageClass # Creating storage class for applications to point to openebs-nfs-provisioner |
98 | metadata: |
99 | name: openebs-nfs |
100 | provisioner: openebs.io/nfs |
101 | parameters: |
102 | mountOptions: “vers=4.1″# TODO: reconcile with StorageClass.mountOptions |
view raw
openebs-nfs-provisioner-deployment.yaml
hosted with ❤ by GitHub
Deployment for OpenEBS provisioner
In the above YAML under the args you as can see we are providing -provisioner=openebs.io/nfs this means that the NFS provisioner will claim volumes for those applications whose PVC is pointing this provisioner and these applications will be deployed on top of NFS provisioner, I will explain it further. Now at the end of the YAML, you can see that we are creating a PVC under which the storage class is pointing to openebs-jiva-default this means we want to use Jiva storage engine for provisioning volume for NFS provisioner.
YAML Spec for accessing NFS from WordPress
1 | - - |
2 | apiVersion: v1 |
3 | kind: Service |
4 | metadata: |
5 | name: wordpress-mysql |
6 | labels: |
7 | app: wordpress |
8 | …. |
9 | # Specs for the application |
10 | …. |
11 | volumes: |
12 | - name: wordpress-persistent-storage |
13 | persistentVolumeClaim: |
14 | claimName: openebs-nfs |
15 | - - |
16 | kind: PersistentVolumeClaim |
17 | apiVersion: v1 |
18 | metadata: |
19 | name: openebs-nfs |
20 | annotations: |
21 | volume.beta.kubernetes.io/storage-class: “openebs-nfs” # Pointing to OpensEBS-NFS-Provisioner |
22 | spec: |
23 | accessModes: |
24 | - ReadWriteMany # Making this RWX to mount on multiple applications |
25 | resources: |
26 | requests: |
27 | storage: 100G |
view raw
wordpress-openebs-nfs.yaml
hosted with ❤ by GitHub
WordPress deployment configuration
Summary
OpenEBS storage can be used in RWX mode by deploying NFS provisioner in front of OpenEBS storage volume which is in RWO mode. This model is scalable for applications like WordPress. If you know or have any applications or workloads that require RWX access mode in the PVC, please comment below. Thank you for reading and connect with us https://slack.openebs.io or at our twitter handle @openebs.