AWS Storage Blog
Running WordPress on Amazon EKS with Amazon EFS Intelligent-tiering
A large percentage of websites today rely on Content Management Systems (CMS) which provide content creators, who may have little to no experience in web development, with the ability to easily publish their content to a website for distribution to their end users. By far, the most popular CMS platform today is WordPress.
More developers are moving to containerized services for portability and ease of deployment of their applications, and WordPress as a CMS platform is no exception. At the same time, organizations are looking for ways to reduce the overall cost of their cloud services. Over time, as data ages, the frequency at which older content is accessed diminishes, which means the number of requests for a particular webpage, blog post, image or video is also reduced.
Amazon Elastic File System (Amazon EFS) offers EFS Intelligent-tiering which enables file data to be automatically moved to lower-cost storage classes as files are less frequently accessed. EFS Intelligent-tiering delivers automatic cost savings for workloads with changing access patterns by placing your file data in the appropriate storage class, at the right time, based on file access patterns.
Leveraging Amazon EFS as a fully managed, auto-scaling file system will allow your CMS data to grow and shrink on demand without having to manage capacity or performance. Additionally, with the new cost optimization features of Intelligent-tiering, EFS will provide enhanced value by delivering optimized capacity, performance and cost to your WordPress deployment.
In this blog, I show you how to quickly deploy a containerized instance of WordPress using the Amazon Elastic Kubernetes Service (EKS) with persistent file storage leveraging EFS with Intelligent-tiering enabled for cost optimization.
Solution architecture
This is a high level diagram of the architecture you will be building, leveraging the AWS services referenced in this post. The diagram depicts the AWS services that comprise a WordPress solution running Amazon EKS on Amazon EC2 instances. The storage layer uses Amazon EFS with both Standard and Infrequent Access storage classes, and Intelligent-tiering enabled. Mount points exist in two AWS Availability Zones (AZs), and an AWS Elastic Load Balancer is used to access the WordPress website from the internet.
Setup
The setup includes creating your EKS cluster and your EFS file system with mount points and access points. Once your AWS infrastructure is created, you will deploy two containers (Pods) that comprise your WordPress website deployment.
Step 1: Create a Kubernetes Cluster with EKS
First you will set up a Kubernetes cluster on EKS. You can use the eksctl command to do this as it will save a lot of time getting your EKS cluster configured using AWS CloudFormation.
In order to use eksctl
you will need to have kubectl
and eksctl
installed and running locally on your computer. For more information, read the EKS documentation.
Let’s configure your EKS cluster using eksctl
.
Using your preferred SSH client, select your AWS account using the following command:
aws configure
Type in your credentials from your EC2 Private Key in your AWS account. For more information on how to get these credentials, and read Amazon EC2 key pairs and Linux instances.
NOTE: for this blog we will be using us-east-1 as the AWS Region for the purpose of demonstration. If you prefer to use a different Region, be sure to use that Region throughout these steps in your own AWS account.
Create your Kubernetes cluster with the following commands:
eksctl create cluster \
--name eks-wp \
--region us-east-1 \
--zones us-east-1a,us-east-1b \
--managed
You can watch the progress of the deployment in your AWS console in CloudFormation > Stacks
Once complete, you can view your EKS cluster in the AWS console in Elastic Kubernetes Service > ClustersNow use the kubectl
to view the compute nodes from Kubernetes! (For information about kubectl
read the documentation.)
Use the following command to log into your EKS Kubernetes cluster:
aws eks --region us-east-1 update-kubeconfig --name eks-wp
Once logged in, run this command to view your compute nodes:
kubectl get nodes
The node names and status of the Kubernetes compute nodes will be displayed:
Now you will create a kustomization.yaml file to allow you to use a secret password for your MySQL and WordPress Pods and enable you to both create and delete your deployment with a single command in kubectl!
First create a new directory where the configuration files will be stored on your local machine.
mkdir eks-wp
cd eks-wp
In your terminal, paste the following and enter.
cat <<EOF >./kustomization.yaml
secretGenerator:
- name: mysql-pass
literals:
- password=WordPass
resources:
- mysql-deployment.yaml
- wordpress-deployment.yaml
EOF
Next, create a deployment file for MySQL that will be used to deploy your MySQL Pod in EKS. Copy and paste the following into your terminal and enter.
cat <<EOF >./mysql-deployment.yaml
apiVersion: v1
kind: Service
metadata:
name: wordpress-mysql
labels:
app: wordpress
spec:
ports:
- port: 3306
selector:
app: wordpress
tier: mysql
clusterIP: None
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: mysql-pv-claim
labels:
app: wordpress
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 20Gi
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: wordpress-mysql
labels:
app: wordpress
spec:
selector:
matchLabels:
app: wordpress
tier: mysql
strategy:
type: Recreate
template:
metadata:
labels:
app: wordpress
tier: mysql
spec:
containers:
- image: mysql:5.6
name: mysql
env:
- name: MYSQL_ROOT_PASSWORD
valueFrom:
secretKeyRef:
name: mysql-pass
key: password
ports:
- containerPort: 3306
name: mysql
volumeMounts:
- name: mysql-persistent-storage
mountPath: /var/lib/mysql
volumes:
- name: mysql-persistent-storage
persistentVolumeClaim:
claimName: mysql-pv-claim
EOF
Step 2: Create an EFS file system with Intelligent-tiering
For the WordPress deployment we will use EFS for persistent storage of the WordPress images. In order to do this, you will need to create an EFS file system first.
Create a security group for the Amazon EFS mount target, which requires the VPC ID for the VPC created by eksctl
for your cluster.
aws ec2 create-security-group \
--region us-east-1 \
--group-name efs-mount-sg \
--description "Amazon EFS for EKS, SG for mount target" \
--vpc-id(i.e. vpc-00ab3ddf9e831f016)
Next you will need to authorize the inbound access to the security group for the Amazon EFS mount target (efs-mount-sg) to allow inbound traffic to the NFS port (2049) from the VPC CIDR block using the following command using the security group ID outputted from the previous step.
aws ec2 authorize-security-group-ingress \
--group-id (i.e. sg-0169ed1789bf1d872) \
--region us-east-1 \
--protocol tcp \
--port 2049 \
--cidr 192.168.0.0/16
Next, create an encrypted Amazon EFS file system from the console. Navigate to the EFS console and select Create file system. Name your file system WP-FS-INT and select the VPC that corresponds to your EKS cluster. For availability, select Regional, as we want to take advantage of Multi-AZ availability. (Make sure the file system is created in us-east-1 or whichever AWS Region you have selected for your EKS cluster.)
Note: Selecting Customize will reveal that Intelligent-tiering is already selected as the default setting under Lifecycle Management. This will ensure that the infrequently accessed content will be archived to EFS Standard-Infrequent access storage class after 30 days of non-access.
Next you will add the efs-mount-sg security group to each Mount target in your VPC and select Next > Next> Create
The last step in finalizing the EFS file system for use with your Kubernetes cluster is to use Amazon EFS Access points. To create an Access point, navigate to Access points on the left side menu and Create access point. Select your file system ID and other parameters as follows. To learn more about working with EFS Access Points read the documentation.
Root directory path: /wordpress
Posix User ID: 1000
Posix Group ID: 1000
Root Owner user ID: 1000
Root group ID: 1000
POSIX permissions: 777
Select Create access point
Deploy the Amazon EFS CSI driver to your Amazon EKS cluster
For the WordPress deployment we will use EFS for persistent storage of the WordPress images by leveraging the CSI driver for EFS.
For more information, you can read about the CSI drivers for EKS.
To deploy the Amazon EFS CSI driver, run the following command. Note: Helm is required for this installation. If you do not already have helm installed, learn about it and download it.
helm repo add aws-efs-csi-driver https://kubernetes-sigs.github.io/aws-efs-csi-driver/
helm repo update
helm upgrade --install aws-efs-csi-driver --namespace kube-system aws-efs-csi-driver/aws-efs-csi-driver
Now you will create the wordpress-deployment.yaml file.
Important! Paste your EFS file system ID and Access point fsap. (i.e. fs-5367904b::fsap-07e317d37bcbfb140) into the YAML file where volumeHandle
is specified.
cat <<EOF >./wordpress-deployment.yaml
apiVersion: v1
kind: Service
metadata:
name: wordpress
labels:
app: wordpress
spec:
ports:
- port: 80
selector:
app: wordpress
tier: frontend
type: LoadBalancer
---
kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
name: efs-sc
provisioner: efs.csi.aws.com
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: wordpress-efs-pv
spec:
capacity:
storage: 5Gi
volumeMode: Filesystem
accessModes:
- ReadWriteMany
persistentVolumeReclaimPolicy: Retain
storageClassName: efs-sc
csi:
driver: efs.csi.aws.com
volumeHandle: "Your EFS file system ID and Access point fsap:
(i.e. fs-5367904b::fsap-07e317d37bcbfb140)"
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: wordpress-efs-pvc
labels:
app: wordpress
spec:
accessModes:
- ReadWriteMany
storageClassName: efs-sc
resources:
requests:
storage: 5Gi
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: wordpress
labels:
app: wordpress
spec:
selector:
matchLabels:
app: wordpress
tier: frontend
strategy:
type: Recreate
template:
metadata:
labels:
app: wordpress
tier: frontend
spec:
containers:
- image: wordpress:php7.1-apache
name: wordpress
env:
- name: WORDPRESS_DB_HOST
value: wordpress-mysql
- name: WORDPRESS_DB_PASSWORD
valueFrom:
secretKeyRef:
name: mysql-pass
key: password
ports:
- containerPort: 80
name: wordpress
volumeMounts:
- name: wordpress-persistent-storage
mountPath: /var/www/html
volumes:
- name: wordpress-persistent-storage
persistentVolumeClaim:
claimName: wordpress-efs-pvc
EOF
Notice you are using a persistent volume claim for storage in both the WordPress and MySQL deployments to take advantage of AWS persistent storage. This will insure that the website remains stateful and you will not lose data if the Pod crashes or is recreated. For more detailed information on persistent storage for containers, read about storage classes here. Keep in mind that the Amazon EBS CSI driver (which we are using for the MySQL deployment) is automatically installed with eksctl
and the Amazon Elastic Block Store (EBS) Storage Class is created in Kubernetes for you!
Now deploy both containers to EKS with the following command:
kubectl apply -k .
You can monitor the deployment with the command:
kubectl get pods --watch
(Select CTL C to exit watch)
Once the containers have successfully been created and the Pods show as “Running” in Kubernetes, you can get the DNS name of the ELB LoadBalancer by typing the following command:
kubectl get svc wordpress
Note: You may need to wait a few minutes for the EC2 compute instances to register with the newly created LoadBalancer before your site will be accessible.
To ensure the AWS Elastic Load Balancer is in service, go to the EC2 console and select Load Balancers to see the DNS name of the Load Balancer from the console. (This will be the same DNS name you get from the command you just ran.)
Wait for the status to display InService for both EC2 instances and then copy the DNS name into your web browser.
Step 3: WordPress “5-minute install”
The WordPress “5-minute install” should now be ready to configure, completing the deployment process.
Congratulations! You’ve now deployed your stateful WordPress site to AWS on EKS!
Clean up your environment
To clean up your environment, follow these steps:
1.) Delete the Kubernetes Deployments, Services and Pods:
kubectl delete -k .
2.) Delete the file system: Navigate to EFS, select and delete your WP-FS file system.
3.) Delete file system security group
aws ec2 delete-security-group \
--group-id (i.e. sg-0169ed1789bf1d872) \
--region us-east-1
4.) Lastly, use eksctl
to delete your EKS cluster and all of its dependencies via CloudFormation
eksctl delete cluster eks-wp
Conclusion
Amazon EFS is a simple, serverless, set-and-forget, elastic file system that allows your CMS data to grow and shrink automatically as you add and remove files. It enables you to persist and share data, with zero management required. Additionally, EFS Intelligent-tiering delivers automatic cost savings by placing your file data in the appropriate storage class, at the right time, based on file access patterns to your WordPress deployment.
In this blog, I showed you how to create an Amazon EKS cluster, attach an Amazon EFS file system with Intelligent-tiering enabled, and deploy WordPress. Deploying WordPress on Amazon EKS can dramatically improve the scalability and manageability of your CMS website. By pairing the durability, flexibility and cost savings of EFS Intelligent-tiering with your EKS deployment, you can achieve the goal of creating both a cost-optimized and performance-optimized solution for WordPress that is simple to manage and highly scalable.
Thanks for reading this blog post. If you have any comments or questions, share them in the comments section.