| 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 | 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 |