Amazon EKS : Deploying a Website

Aman Pasi
7 min readJul 15, 2020

Launching PHP-MySql website over EKS.

What is EKS?
Amazon Elastic Kubernetes Service (Amazon EKS) is a fully managed Kubernetes service. Using EKS we can make multi node cluster within minute with all the configuration done. EKS manages the master node as it is a managed service by AWS. EKS also provides facility to launch cluster with Fargate which make application serverless. EKS is deeply integrated with services such as Amazon CloudWatch, Auto Scaling Groups, AWS Identity and Access Management (IAM), and Amazon Virtual Private Cloud (VPC), providing you a seamless experience to monitor, scale, and load-balance your applications.

How it Works?

Lets get started

Step 1: Create a IAM user with admin access

Make sure to download or Mail the User information.

Step 2 : AWS CLI configuration

You will need to install aws cli from AWS website for this.
You can download it from here : https://aws.amazon.com/cli/
Add the aws command to your path depending upon your OS.

To configure AWS CLI run :-
$ aws configure
And enter the access key and secret keys you downloaded while creating IAM user.

Step 3: eksctl Configuration

We can use eks service from amazon, but it is time consuming.
amazon have adopted a new way to launch eks clusture using eksctl.

What is “eksctl”?
eksctlis a simple command line utility for creating and managing Kubernetes clusters on Amazon EKS. It creates a CloudFormation script ni the background to launch eks clusture.

You can download eksctl from here https://docs.aws.amazon.com/eks/latest/userguide/eksctl.html and add it to your PATH.

Download and extract the latest release of eksctl with the following command :-
$ curl — silent — location “https://github.com/weaveworks/eksctl/releases/latest/download/eksctl_$(uname -s)_amd64.tar.gz” | tar xz -C /tmp

Move the extracted binary to /usr/local/bin :-
$ sudo mv /tmp/eksctl /usr/local/bin

To confirm the Setup run following command :-
$ eksctl version

Step 3: Launching EKS Cluster

There are two ways to launch EKS cluster: -
1. Using EC2 Instances
2. Using Fargate service

I am going to launch EC2 instances in this article.
For that we need to make a yaml file with all the configuration we need.

Before launching the instance we can attach a public key, So that we can login via SSH. So you must create key-pair in AWS beforehand. I have already created the key and downloaded it.

Now Lets make the yaml file :-
I have launched two node groups ng1 and ng-2 with desiredCapacity of two i.e the number of instances in each group

To create the cluster, we just need to run the following command:-
$ eksctl create cluster -f eks_cluster.yml

The output will be like this:-

It will take some time to launch the cluster.

You can see in AWS Web cnsole that a Cloudformation created :-

To access the kubernetes cluster, we need to configure local kubectl.
It can be done easily using AWS CLI command :-
$ aws eks update-kubeconfig — name cluster

To confirm and view configuration of kubectl, use following command :-
$ kubectl config view

Step 4 : Create EFS storage

We can use EBS volume also to start pods but as EBS can only be atached to one EC2 instance for multi node cluster it’s not usefull.
So we create a Storage Class in EKS using EFS

To create go to AWS WebUI console -> EFS -> Create

Give the same VPC and Security Group as clusture so that it can be accessed.

Now we have to make a provisioner which will let us mount the efs storage to the cluster.
For this you will need the FILE_SYSTEM_ID, DNS name of EFS(server), etc

efs_provisioner.yml

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-8343d652
- name: AWS_REGION
value: ap-south-1
- name: PROVISIONER_NAME
value: basic/aws-efs
volumeMounts:
- name: pv-volume
mountPath: /persistentvolumes
volumes:
- name: pv-volume
nfs:
server: fs-8343d652.efs.ap-south-1.amazonaws.com
path: /

Run the yaml using following command:-
$ kubectl create -f eks_provisioner.yml

Now we have to create a RBAC role for efs:-

apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
name: nfs-provisioner-role-binding
subjects:
- kind: ServiceAccount
name: default
namespace: default
roleRef:
kind: ClusterRole
name: cluster-admin
apiGroup: rbac.authorization.k8s.io

Run the following using the given command:-
$ kubectl create -f rbac.yml

Now lets create Storage Class for using the EFS Storage.
Following Storage class yaml file can be used to create a storage class for efs.

kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
name: aws-efs
provisioner: basic/aws-efs

Just run this and storge class will be ready for use.
$ kubectl create -f eks_storage.yml

Step 5: Creating Secrets

You can pass the password for MySQL database in the yaml file but this is not a good practice. It may be possible if anyone got the file they will also know your password. Kubernetes provide a good way to store password i,e Secrets.
You have to encode any data before passing it to yaml fie for security reasons.
e.g aman@3214 → YW1hbkAzMjE0

apiVersion: v1
kind: Secret
metadata:
name: mysql-pass
type: Opaque
data:
mysql-pass: YW1hbkAzMjE0

Run to create a storage class :-
$ kubectl create -f secrets.yml

Step 6: Creating PVC

We need to create a Persistent Volume Claim so that we can attach storage to pods.

We will two PVC, one for DB and another for hosting site. These storage will be persistent as they come from EFS. We have to give anotation that we want the storage from EFS storage class.
We also have to set read/write access to Many since we want it connected to all pods in clusture.

kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: efs-php
annotations:
volume.beta.kubernetes.io/storage-class: "aws-efs"
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 5Gi

---

kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: efs-mysql
annotations:
volume.beta.kubernetes.io/storage-class: "aws-efs"
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 5Gi

Run the following command to create above PVC:-
$ kubectl create -f pvc.yml

Step 7: Deploying MySQL Pods

It’s time to deploy MySQL pods.
Note: MySQL pods must be created first so that the pod which have website doesn’t go in Crashing when launched.

apiVersion: apps/v1
kind: Deployment
metadata:
name: php-mysql
labels:
app: webapp
spec:
replicas: 2
selector:
matchLabels:
app: webapp
tier: mysql
strategy:
type: Recreate
template:
metadata:
labels:
app: webapp
tier: mysql
spec:
containers:
- image: mysql:5.6
name: mysql
env:
- name: MYSQL_ROOT_PASSWORD
valueFrom:
secretKeyRef:
name: mysql-pass
key: mysql-pass
ports:
- containerPort: 3306
name: mysql
volumeMounts:
- name: mysql-persistent-storage
mountPath: /var/lib/mysql
volumes:
- name: mysql-persistent-storage
persistentVolumeClaim:
claimName: efs-mysql

$ kubectl create -f mysql.yml

Step 8 : Launching PHP Website

apiVersion: apps/v1 
kind: Deployment
metadata:
name: php-website
labels:
app: php
spec:
selector:
matchLabels:
app: php
tier: frontend
strategy:
type: Recreate
template:
metadata:
labels:
app: php
tier: frontend
spec:
containers:
- image: vimal13/
name: php
ports:
- containerPort: 80
name: wordpress
volumeMounts:
- name: wordpress-persistent-storage
mountPath: /var/www/html
volumes:
- name: wordpress-persistent-storage
persistentVolumeClaim:
claimName: efs-wordpress

$ kubectl create -f php.yml

Step 9: Connecting PHP and Mysql

Both the pods have been deployed but because they are not connected our apps won’t run.

To connect we have to create a service which connect to each other and also if we want to access the website publicly (outside the cluster) we have to also create a Load balance which will give us access to the website.

For MySQL:

apiVersion: v1
kind: Service
metadata:
name: php-mysql
labels:
app: webapp
spec:
ports:
- port: 3306
selector:
app: webapp
tier: mysql
clusterIP: None

$ kubectl create -f mysql_service.yml

For PHP Website:

apiVersion: v1
kind: Service
metadata:
name: php
labels:
app: php
spec:
ports:
- port: 80
selector:
app: php
tier: frontend
type: LoadBalancer

$ kubectl create -f php_service.yml

Hooray Your Website has been deployed Perfectly

--

--