Browse code

MySQL/Wordpress on NFS PVs

markturansky authored on 2015/06/26 00:50:48
Showing 9 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,155 @@
0
+# How To Use NFS Persistent Volumes
1
+
2
+The purpose of this guide is to help you understand storage provisioning with NFS by creating a WordPress blog and MySQL database.
3
+In this example, both the blog and database require persistent storage.  
4
+
5
+This guide assumes knowledge of OpenShift fundamentals and that you have a cluster up and running.  Please review steps 1 - 10 in the
6
+[sample-app](https://github.com/openshift/origin/blob/master/examples/sample-app/README.md) to run an OpenShift cluster.
7
+
8
+## NFS Provisioning
9
+
10
+We'll be creating NFS exports on the local machine.  The instructions below are for Fedora.  The provisioning process may be slightly different based on linux distribution or the type of NFS server being used.
11
+
12
+Create two NFS exports, each of which will become a Persistent Volume in the cluster. 
13
+
14
+```
15
+# the directories in this example can grow unbounded
16
+# use disk partitions of specific sizes to enforce storage quotas
17
+mkdir /home/data/pv0001 
18
+mkdir /home/data/pv0002
19
+
20
+# data written to NFS by a pod gets squashed by NFS and is owned by 'nfsnobody'
21
+# we'll make our export directories owned by the same user
22
+chown -R /home/data nfsnobody:nfsnobody
23
+
24
+# security needs to be permissive currently, but the export will soon be restricted 
25
+# to the same UID/GID that wrote the data
26
+chmod -R 777 /home/data/
27
+
28
+# Add to /etc/exports
29
+/home/data/pv0001 *(rw,sync,no_root_squash)
30
+/home/data/pv0002 *(rw,sync,no_root_squash)
31
+
32
+# Enable the new exports without bouncing the NFS service
33
+exportfs -a
34
+
35
+```
36
+
37
+## Security
38
+
39
+### SELinux
40
+
41
+By default, SELinux does not allow writing from a pod to a remote NFS server. The NFS volume mounts correctly, but is read-only.
42
+
43
+To enable writing in SELinux on each node:
44
+
45
+```
46
+# -P makes the bool persistent between reboots.
47
+$ setsebool -P virt_use_nfs 1 
48
+```
49
+
50
+### Root access
51
+
52
+The Wordpress Dockerhub image binds Apache to port 80 in the container, which requires root access.  We can allow that 
53
+in this example, but those wishing to run a more secure cluster will want to ensure their images don't require root access (e.g, bind to high number ports, don't chown or chmod dirs, etc)
54
+
55
+Allow Wordpress to bind to port 80 by editing the restricted security context restraint.  Change "runAsUser" from ```MustRunAsRange``` to ```RunAsAny```.
56
+
57
+
58
+```
59
+$ oc edit scc restricted
60
+
61
+apiVersion: v1
62
+groups:
63
+- system:authenticated
64
+kind: SecurityContextConstraints
65
+metadata:
66
+  creationTimestamp: 2015-06-26T14:01:03Z
67
+  name: restricted
68
+  resourceVersion: "59"
69
+  selfLink: /api/v1/securitycontextconstraints/restricted
70
+  uid: c827a79d-1c0b-11e5-9166-d4bed9b39058
71
+runAsUser:
72
+  type: MustRunAsRange  <-- change to RunAsAny
73
+seLinuxContext:
74
+  type: MustRunAs
75
+```
76
+
77
+Changing the restricted security context as shown above allows the Wordpress container to bind to port 80.  
78
+
79
+
80
+## Persistent Volumes and Claims
81
+
82
+Each NFS export becomes its own Persistent Volume in the cluster.
83
+
84
+```
85
+# Create the persistent volumes for NFS.
86
+$ oc create -f examples/wordpress/pv-nfs-1.yaml 
87
+$ oc create -f examples/wordpress/pv-nfs-2.yaml 
88
+$ oc get pv
89
+
90
+NAME      LABELS    CAPACITY     ACCESSMODES   STATUS      CLAIM     REASON
91
+pv0001    <none>    1073741824   RWO,RWX       Available             
92
+pv0002    <none>    5368709120   RWO           Available             
93
+
94
+# Create claims for storage.
95
+# The claims in this example carefully match the volumes created above.
96
+$ oc create -f examples/wordpress/pvc-wp.yaml 
97
+$ oc create -f examples/wordpress/pvc-mysql.yaml
98
+$ oc get pvc
99
+
100
+NAME          LABELS    STATUS    VOLUME
101
+claim-mysql   map[]     Bound     pv0002
102
+claim-wp      map[]     Bound     pv0001
103
+```
104
+
105
+## MySQL 
106
+
107
+Launch the MySQL pod.
108
+
109
+```
110
+oc create -f examples/wordpress/pod-mysql.yaml
111
+```
112
+
113
+After a few moments, MySQL will be running and accessible via the pod's IP address.  We don't know what the IP address
114
+will be and we wouldn't want to hard-code that value in any pod that wants access to MySQL.  
115
+
116
+Create a service in front of MySQL that allows other pods to connect to it by name.
117
+
118
+```
119
+# This allows the pod to access MySQL via a service name instead of hard-coded host address
120
+oc create -f examples/wordpress/service-mysql.yaml 
121
+```
122
+
123
+## WordPress
124
+
125
+We use the MySQL service defined above in our Wordpress pod.  The variable WORDPRESS_DB_HOST is set to the name
126
+ of our MySQL service.
127
+ 
128
+Because the Wordpress pod and MySQL service are running in the same namespace, we can reference the service by name.  We
129
+can also access a service in another namespace by using the name and namespace: ```mysql.another_namespace```.  The fully qualified
130
+name of the service would also work: ```mysql.<namespace>.svc.cluster.local```
131
+
132
+```
133
+- name: WORDPRESS_DB_HOST
134
+  # this is the name of the mysql service fronting the mysql pod in the same namespace
135
+  # expands to mysql.<namespace>.svc.cluster.local  - where <namespace> is the current namespace
136
+  value: mysql
137
+```
138
+
139
+Launch the Wordpress pod and its corresponding service.
140
+
141
+```
142
+oc create -f examples/wordpress/pod-wordpress.yaml 
143
+oc create -f examples/wordpress/service-wp.yaml 
144
+
145
+oc get svc
146
+NAME            LABELS                                    SELECTOR         IP(S)            PORT(S)
147
+mysql           name=mysql                                name=mysql       172.30.115.137   3306/TCP
148
+wpfrontend      name=wpfrontend                           name=wordpress   172.30.170.55    5055/TCP
149
+```
150
+
151
+
152
+## Start Blogging
153
+
154
+In your browser, visit 172.30.170.55:5055 (your IP address will vary).  The Wordpress install process will lead you through setting up the blog.
0 155
new file mode 100644
... ...
@@ -0,0 +1,32 @@
0
+apiVersion: v1
1
+kind: Pod
2
+metadata:
3
+  name: mysql
4
+  labels:
5
+    name: mysql
6
+spec:
7
+  containers:
8
+    - resources:
9
+        limits :
10
+          cpu: 0.5
11
+      image: openshift/mysql-55-centos7
12
+      name: mysql
13
+      env:
14
+        - name: MYSQL_ROOT_PASSWORD
15
+          value: yourpassword
16
+        - name: MYSQL_USER
17
+          value: wp_user
18
+        - name: MYSQL_PASSWORD
19
+          value: wp_pass
20
+        - name: MYSQL_DATABASE
21
+          value: wp_db
22
+      ports:
23
+        - containerPort: 3306
24
+          name: mysql
25
+      volumeMounts:
26
+        - name: mysql-persistent-storage
27
+          mountPath: /var/lib/mysql/data
28
+  volumes:
29
+    - name: mysql-persistent-storage
30
+      persistentVolumeClaim:
31
+        claimName: claim-mysql
0 32
new file mode 100644
... ...
@@ -0,0 +1,31 @@
0
+apiVersion: v1
1
+kind: Pod
2
+metadata:
3
+  name: wordpress
4
+  labels: 
5
+    name: wordpress
6
+spec: 
7
+  containers: 
8
+    - image: wordpress
9
+      name: wordpress
10
+      env:
11
+        - name: WORDPRESS_DB_USER
12
+          value: wp_user
13
+        - name: WORDPRESS_DB_PASSWORD
14
+          value: wp_pass
15
+        - name: WORDPRESS_DB_NAME
16
+          value: wp_db
17
+        - name: WORDPRESS_DB_HOST
18
+          # this is the name of the mysql service fronting the mysql pod in the same namespace
19
+          # expands to mysql.<namespace>.svc.cluster.local  - where <namespace> is the current namespace
20
+          value: mysql
21
+      ports: 
22
+        - containerPort: 80
23
+          name: wordpress
24
+      volumeMounts:
25
+        - name: wordpress-persistent-storage
26
+          mountPath: /var/www/html
27
+  volumes:
28
+    - name: wordpress-persistent-storage
29
+      persistentVolumeClaim:
30
+       claimName: claim-wp
0 31
new file mode 100644
... ...
@@ -0,0 +1,13 @@
0
+apiVersion: v1
1
+kind: PersistentVolume
2
+metadata:
3
+  name: pv0001
4
+spec:
5
+  capacity:
6
+    storage: 1Gi
7
+  accessModes:
8
+    - ReadWriteOnce
9
+    - ReadWriteMany
10
+  nfs:
11
+    server: localhost
12
+    path: /home/data/pv0001
0 13
new file mode 100644
... ...
@@ -0,0 +1,12 @@
0
+apiVersion: v1
1
+kind: PersistentVolume
2
+metadata:
3
+  name: pv0002
4
+spec:
5
+  capacity:
6
+    storage: 5Gi
7
+  accessModes:
8
+    - ReadWriteOnce
9
+  nfs:
10
+    server: localhost
11
+    path: /home/data/pv0002
0 12
new file mode 100644
... ...
@@ -0,0 +1,10 @@
0
+kind: PersistentVolumeClaim
1
+apiVersion: v1
2
+metadata:
3
+  name: claim-mysql
4
+spec:
5
+  accessModes:
6
+    - ReadWriteOnce
7
+  resources:
8
+    requests:
9
+      storage: 3Gi
0 10
new file mode 100644
... ...
@@ -0,0 +1,11 @@
0
+kind: PersistentVolumeClaim
1
+apiVersion: v1
2
+metadata:
3
+  name: claim-wp
4
+spec:
5
+  accessModes:
6
+    - ReadWriteOnce
7
+    - ReadWriteMany
8
+  resources:
9
+    requests:
10
+      storage: 1Gi
0 11
new file mode 100644
... ...
@@ -0,0 +1,13 @@
0
+apiVersion: v1
1
+kind: Service
2
+metadata:
3
+  labels:
4
+    name: mysql
5
+  name: mysql
6
+spec:
7
+  ports:
8
+    # the port that this service should serve on
9
+    - port: 3306
10
+  # label keys and values that must match in order to receive traffic for this service
11
+  selector:
12
+    name: mysql
0 13
new file mode 100644
... ...
@@ -0,0 +1,15 @@
0
+apiVersion: v1
1
+kind: Service
2
+metadata: 
3
+  labels: 
4
+    name: wpfrontend
5
+  name: wpfrontend
6
+spec: 
7
+  ports:
8
+    # the port that this service should serve on
9
+    - port: 5055
10
+      targetPort: wordpress
11
+  # label keys and values that must match in order to receive traffic for this service
12
+  selector: 
13
+    name: wordpress
14
+  type: LoadBalancer