WordPress on Amazon-EKS
Let's get started with one of the most demanding service in the market i.e Amazon Elastic Kubernetes Service (Amazon EKS).
What is Amazon Web Service?
AWS is a subsidiary of Amazon that provides cloud computing as services, or in other words Infrastructure as a Service (also called IAAS). AWS provides all the computing power(including cpu, ram, gpu) , storage solutions(like SSD), and networking (includes routers, switches, firewall etc) as a services. It is one of the top cloud infrastructure.
What is Kubernetes?
Kubernetes is a open-source platform for container-orchestration system that is used for automating the process of deploying, scaling, and managing computer applications.
What is Amazon-EKS?
In layman terms we can say that EKS is the combination of AWS and Kubernetes. Launching Kubernetes on top of AWS makes it a powerful tool for automation. EKS is a fully managed service provided by AWS for container -orchestration. It uses the computing power of AWS to launch computer applications.
Benefits of AWS-EKS -
- High availability
- Serverless option
- Secure
- Built with community
Amazon EKS Architecture-
Amazon Elastic Kubernetes Service (Amazon EKS) runs the Kubernetes management infrastructure for you across multiple AWS Availability Zones to eliminate a single point of failure.
AWS EKS service is not a free service and it charges you on hourly basis. You need to pay $0.10 per hour for each Amazon EKS cluster you create.
Let's get started with the project in which I launched a WordPress application on the top of EKS.
Pre-Requisites:
- You must have an aws account.
- Installed aws cli and configured the profile
- Installed kubectl and eksctl programs.
These are required for creating WordPress on top of EKS.
Step-by-step Explanation:
Following are the Steps which I followed to successfully complete this project:-
- Cluster creation
- Installing amazon-efs-utils on top of each node
- Creating EFS.
- Creating EFS-Provisioner
- Creating RBAC
- Creating Storage Class
- Launching Pod for MySQL
- Launching Pod for WordPress.
A. Cluster Creation
For creating cluster, we need eksctl command which is used in EKS service. This command launch , delete and manage the cluster in just one click.
Its an automation program, which creates a code and send the code to CloudFormation. CloudFormation is a service of AWS which do everything for us.
It contacts to VPC and creates subnet, it also contacts to EC2 for launching instance.
For this we can use this following code to configure our EKS cluster as per our requirements. After creating the file save it with .yml / .yaml extension.
cluster.yml
apiVersion: eksctl.io/v1alpha5 kind: ClusterConfig metadata: name: mycluster region: ap-south-1 nodeGroups: - name: ng1 desiredCapacity: 2 instanceType: t2.micro ssh: publicKeyName: mykey - name: ng2 desiredCapacity: 1 instanceType: t2.micro ssh: publicKeyName: mykey
The command used to create the cluster using the YAML code is
eksctl create cluster -f cluster.yml
where cluster.yml is the name of the code file. After we run this command we can see the following screen. This shows that eksctl command is sending the information to AWS CloudFormation which behind the scene creates everything.
Creating cluster require atleast 20-25 minutes as there are a lot of resources (such as VPC, EC2 instances, NAT Gateway, etc..) creating behind the scene. Wait until you see something like EKS cluster <clustername> in ap-south-1 region is ready.
Now we can see on the AWS portal that one cluster is launched along with the CloudFormation stack and EC2 Instances.
As we can see above that we successfully launched the cluster and also instances. After cluster is launched, we need to update our configuration file of kubectl so that we can link our kubectl with the new cluster. For this AWS has a command which automatically updates the current-context in the config file with the EKS cluster specified.
aws eks update-kubeconfig --name=<cluster-name>
This is the command can be used to update the kube-config file.
To verify that the config file is update we can use following command which shows where our k8s master is running.
kubectl cluster info
B. Installing amazon-efs-utils on each node.
The amazon-efs-utils package is an open-source collection of Amazon EFS tools. The package is available in the Amazon Linux package repositories, hence we can easily install it on any linux system as follows:
yum install amazon-efs-utils -y
The amazon-efs-utils package comes with a mount helper and tooling that makes it easier to perform encryption of data in transit for Amazon EFS. A mount helper is a program that you use when you mount a specific type of file system. Here our file system is EFS.
C. Creating EFS.
Now we need to create a EFS. This can be done by simply going to AWS-EFS portal and launching it.
Two most important things we need to keep in mind while creating EFS
- Selecting correct VPC - The vpc to be selected is the one which is created by the cloudformation stack as shown in the below image.
- Selecting correct Security group- Security group should be the one which is common in all the nodes. So first go in the description of all the instances and find out the common security group(DO NOT SELECT DEFAULT SECURITY GROUP)
If this is not done properly then entire project might fail.
D. Creating EFS-Provisioner
The efs-provisioner allows you to mount EFS storage as PersistentVolumes in kubernetes. It consists of a container that has access to an AWS-EFS resource. The container reads a configmap which contains the EFS filesystem ID, the AWS region and the name you want to use for your efs-provisioner. This name will be used later when you create a storage class.
The code used to create the EFS-Provisioner is mentioned below. Before creating this one thing we have to do which is creating a new namespace. We will do everything on that namespace only. Following is how we can create new namespace.
kubectl create namespace my
Here I created a namespace named my.
create-efs-privisioner.yaml
kind: Deployment apiVersion: apps/v1 metadata: name: efs-provisioner spec: selector: matchLabels: app: efs-provisioner replicas: 1 strategy: type: Recreate template: metadata: labels: app: efs-provisioner spec: containers: - name: efs-provisioner image: quay.io/external_storage/efs-provisioner:v0.1.0 env: - name: FILE_SYSTEM_ID value: fs-8245d053<from-aws-efs-console> - name: AWS_REGION value: ap-south-1 - name: PROVISIONER_NAME value: rachit/aws-efs volumeMounts: - name: pv-volume mountPath: /persistentvolumes volumes: - name: pv-volume nfs: server: fs-8245d053.efs.ap-south-1.amazonaws.com<from-aws-efs-console> path: /
Above mentioned is the code used to create a EFS-PROVISIONER. Here we have to update the value of FILE_SYSTEM_ID and DNS_SERVER which we can get from the AWS console.
kubectl create -f create-efs-provisioner.yaml -n my
Above command launches a provisioner pod.
E. Creating RBAC
Role-based access control (RBAC) is a method of regulating access to computer or network resources based on the roles of individual users within an enterprise.
Following are the code and command used to create a RBAC.
role.yaml
apiVersion: rbac.authorization.k8s.io/v1beta1 kind: ClusterRoleBinding metadata: name: nfs-provisioner-role-binding subjects: - kind: ServiceAccount name: default namespace: my <need-to-be-updated> roleRef: kind: ClusterRole name: cluster-admin apiGroup: rbac.authorization.k8s.io
The only thing which is dynamic in the above code is the namespace.
kubectl create -f role.yaml -n my
F. Creating Storage Class
A StorageClass is used to define which provisioner should be used and what parameters should be passed when dynamic provisioning is invoked.
A StorageClass provides a way for administrators to describe the "classes" of storage they offer.
Here we are going to create a Storage Class named aws-efs and then we are going to use that storage class to launch 2 PVC, one for Wordpress and other for MySQL.
sc.yaml
kind: StorageClass apiVersion: storage.k8s.io/v1 metadata: name: aws-efs provisioner: rachit/aws-efs --- kind: PersistentVolumeClaim apiVersion: v1 metadata: name: efs-wordpress annotations: volume.beta.kubernetes.io/storage-class: "aws-efs" spec: accessModes: - ReadWriteMany resources: requests: storage: 10Gi --- kind: PersistentVolumeClaim apiVersion: v1 metadata: name: efs-mysql annotations: volume.beta.kubernetes.io/storage-class: "aws-efs" spec: accessModes: - ReadWriteMany resources: requests: storage: 10Gi
PVC are basically used to keep our data persistent. Below image shows that after running above code storage class and PVC are launched successfully.
kubectl create -f sc.yaml -n my
Now the only thing left is to create and launch the deployment for WordPress and MySQL. But before this one small thing we have to do, we have to create a secret box in which we have to store Root password that can be accessed by the pods at the time of launching.
So to create a secret box we can use following one simple command
As the secret box is also created, now we are ready to launch the deployment for WordPress and MySQL. First we will launch MySQL and then will launch WordPress.
G. Launching Deployment for MySQL
So now as we are going to launch MySQL, for this I have created following code which launch the deployment and also the service required for MySQL.
In this code we can see the password is being fetched from the secret box and the Volume used is the one that we created already as PVC.
mysql-deploy.yaml
apiVersion: v1 kind: Service metadata: name: wordpress-mysql labels: app: wordpress spec: ports: - port: 3306 selector: app: wordpress tier: mysql clusterIP: None --- apiVersion: apps/v1 # for versions before 1.9.0 use apps/v1beta2 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: efs-mysql
As we can see here that the MySQL deployment is launched successfully. Now we can launch WordPress.
H. Launching Deployment for WordPress
Along with launching of WordPress we also have to create one service which is LoadBalancer. The use of this service is to expose our app so that anyone with the IP can access our app.
The code for creating both service and deployment is as follows
wp-deploy.yaml
apiVersion: v1 kind: Service metadata: name: wordpress labels: app: wordpress spec: ports: - port: 80 selector: app: wordpress tier: frontend type: LoadBalancer --- apiVersion: apps/v1 # for versions before 1.9.0 use apps/v1beta2 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:4.8-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: efs-wordpress
The deployment is now successfully launched and ready to use. Remember one thing, to access the app from public world i.e. Internet we need a PublicIP. This publicip is generated by the service created by us. To get this IP :
The highlighted part that we can see in the above image is the PublicIP or External IP. Now after we connect to this IP from our browser we can see that the Home page of WordPress come up.
Finally we have launched WordPress on Amazon-EKS.
At last we must delete our cluster, because EKS is not a free service provided by AWS.
eksctl delete cluster -f cluster.yml
Also do not forget to check manually on the AWS console, if any services are left just delete it or else you will be charged for it.
Thank you for reading!!