WordPress with Portworx on Kubernetes
This reference architecture document shows how you can deploy WordPress, an open-source content management system, with Portworx on Kubernetes. This architecture provides the following benefits:
- Portworx enables reliable and persistent storage to ensure WordPress runs with HA
- Portworx enables sharedv4 volumes for file uploads
- Kubernetes automatically replicates your MySQL data
- You can horizontally scale the WordPress container using multi-writer semantics for the file-uploads directory
- The cluster automatically repairs itself in the event of a node failure
Prerequisites
- You must have a Kubernetes cluster with a minimum of three worker nodes.
- Portworx is installed on your Kubernetes cluster. For details about how you can install Portworx on Kubernetes, see the Portworx on Kubernetes page.
- You must have Stork installed on your Kubernetes cluster. For details about how you can install Stork, see the Stork page.
Dynamically provision a volume for MySQL
Create a file called
mysql-sc.yaml
, specifying the following fields and values:- apiVersion: as
storage.k8s.io/v1
- kind: as
StorageClass
- metadata.name: with the name of your
StorageClass
object (this example usesmysql-sc
) - provisioner: as
kubernetes.io/portworx-volume
. For details about the Portworx-specific parameters, refer to the Portworx Volume section of the Kubernetes website. - parameters.repl: with the number of replicas Portworx should create (this example creates two replicas)
parameters.priority_io: with the type of the storage pool (this example uses a high-priority storage pool)
apiVersion: storage.k8s.io/v1 kind: StorageClass metadata: name: mysql-sc provisioner: kubernetes.io/portworx-volume parameters: repl: "3" priority_io: "high"
For more details about how you can configure a storage class, see the Using Dynamic Provisioning section of the Portworx documentation.
- apiVersion: as
Apply the spec:
kubectl apply -f mysql-sc.yaml
Create a file called
mysql-pvc.yaml
with the following content:apiVersion: v1 kind: PersistentVolumeClaim metadata: name: mysql-pvc annotations: volume.beta.kubernetes.io/storage-class: mysql-sc spec: accessModes: - ReadWriteOnce resources: requests: storage: 2Gi
NOTE: This PVC references themysql-sc
storage class. As a result, Kubernetes will automatically create a new PVC for each replica.Apply the spec:
kubectl apply -f mysql-pvc.yaml
Dynamically provision a volume for WordPress
Create a file called
wordpress-sc.yaml
with the following content:apiVersion: storage.k8s.io/v1 kind: StorageClass metadata: name: wordpress-sc provisioner: kubernetes.io/portworx-volume parameters: repl: "3" priority_io: "high" shared: "true"
NOTE: Thesharedv4: "true"
flag creates a globally shared namespace volume which can be used by multiple Pods.Apply the spec:
kubectl apply -f wordpress-sc.yaml
Create a file called
wordpress-pvc.yaml
with the following content:apiVersion: v1 kind: PersistentVolumeClaim metadata: name: wp-pvc labels: app: wordpress annotations: volume.beta.kubernetes.io/storage-class: wordpress-sc spec: accessModes: - ReadWriteMany resources: requests: storage: 1Gi
NOTE: This PVC references thewordpress-sc
storage class. As a result, Kubernetes will automatically create a new PVC for each replica.Apply the spec:
kubectl apply -f wordpress-pvc.yaml
Create a Kubernetes secret for storing your MySQL password
A secret is an object that contains sensitive data. To create a secret, you can use the kubectl create secret
command. Note that, to protect your sensitive data, the kubectl get
and kubectl describe
commands do not display the content of a secret.
Use the
echo
command to save your MySQL password to a file called./password.txt
, replacing<YOUR-PASSWORD>
with your actual password:echo -n '<YOUR-PASSWORD' > ./password.txt
To create a new secret, enter the
kubectl create secret
command, specifying:- The
generic
parameter. This instructs Kubernetes to create a secret based on a file, directory, or specified literal value. - The name of your secret (this example uses
mysql-pass
) The
--from-file
flag with the name of the file in which you stored your passwordkubectl create secret generic mysql-pass --from-file=./password.txt
- The
Use the
kubectl get secrets
command to verify that Kubernetes created the secret:kubectl get secrets
Deploy MySQL
Create a file named
mysql-service.yaml
with the following content:apiVersion: v1 kind: Service metadata: name: wordpress-mysql labels: app: wordpress spec: ports: - port: 3306 selector: app: wordpress tier: mysql clusterIP: None
Apply the spec:
kubectl apply -f mysql-service.yaml
Create a file named
mysql-deployment.yaml
with the following content:apiVersion: apps/v1 kind: Deployment metadata: name: wordpress-mysql labels: app: wordpress spec: selector: matchLabels: app: wordpress strategy: type: Recreate template: metadata: labels: app: wordpress tier: mysql spec: # Use the Stork scheduler to enable more efficient placement of the pods schedulerName: stork containers: - image: mysql:5.6 imagePullPolicy: name: mysql env: # $ kubectl create secret generic mysql-pass --from-file=password.txt # make sure password.txt does not have a trailing newline - name: MYSQL_ROOT_PASSWORD valueFrom: secretKeyRef: name: mysql-pass key: password.txt ports: - containerPort: 3306 name: mysql volumeMounts: - name: mysql-persistent-storage mountPath: /var/lib/mysql volumes: - name: mysql-persistent-storage persistentVolumeClaim: claimName: mysql-pvc
Note the following about this
Deployment
:- Kubernetes creates a single-instance MySQL database
- Kubernetes creates an environment variable called
MYSQL_ROOT_PASSWORD
that contains your MySQL password - Portworx mounts the Portworx persistent volume in the
/var/lib/mysql
directory - The Stork scheduler will place your Pods closer to where their data is located
Apply the spec:
kubectl apply -f mysql-deployment.yaml
Deploy WordPress
Create a file called
wordpress-service.yaml
with the following content:apiVersion: v1 kind: Service metadata: name: wordpress labels: app: wordpress spec: ports: - port: 80 nodePort: 30303 selector: app: wordpress tier: frontend type: NodePort
Note that the
spec.type
field is set toNodePort
. Kubernetes exposes the service on each node and makes it accessible from outside the cluster. For more details, see the Type NodePort section of the Kubernetes documentation.Apply the spec:
kubectl apply -f wordpress-service.yaml
Create a file called
wordpress-deployment.yaml
with the following content:apiVersion: apps/v1 kind: Deployment metadata: name: wordpress labels: app: wordpress spec: selector: matchLabels: app: wordpress replicas: 3 strategy: type: Recreate template: metadata: labels: app: wordpress tier: frontend spec: # Use the Stork scheduler to enable more efficient placement of the pods schedulerName: stork containers: - image: wordpress:4.8-apache name: wordpress imagePullPolicy: env: - name: WORDPRESS_DB_HOST value: wordpress-mysql - name: WORDPRESS_DB_PASSWORD valueFrom: secretKeyRef: name: mysql-pass key: password.txt ports: - containerPort: 80 name: wordpress volumeMounts: - name: wordpress-persistent-storage mountPath: /var/www/html volumes: - name: wordpress-persistent-storage persistentVolumeClaim: claimName: wp-pvc
Note the following about this
Deployment
- Portworx will create three replicas of each volume
- The Stork scheduler will place your Pods closer to where their data is located
- Kubernetes will create an environment variable called
WORDPRESS_DB_PASSWORD
that contains your MySQL password
Apply the spec:
kubectl apply -f wordpress-deployment.yaml
Validate the cluster functionality
List your Pods:
kubectl get pods
Display your services:
kubectl get services
Clean up
Enter the following command to delete the Kubernetes secret:
kubectl delete secret mysql-pass
Use the
kubectl delete
to delete your WordPress deployment and PVC:kubectl delete -f wordpress-deployment.yaml kubectl delete -f wordpress-pvc.yaml
Use the
kubectl delete
to delete your MySQL deployment and PVC:kubectl delete -f mysql-deployment.yaml kubectl delete -f mysql-pvc.yaml
Discussion Forum
If you have more questions about this application, please head over to our discussion forum and feel free to ask more questions.