Amazon EKS - Deploying WordPress, MySQL, Prometheus & Grafana

Amazon EKS - Deploying WordPress, MySQL, Prometheus & Grafana

Amazon EKS is a managed service that makes it easy for you to use Kubernetes on AWS without needing to install and operate your own Kubernetes control plane.

How EKS works -

There are two ways that aws provisions EKS.

No alt text provided for this image

1> aws Fargate - This black box is "Serverless" kind of architecture. We don't have to provide any setup as fargate profile will manage all itself. It is easy way but here we can't do any customization

2> Create customized node cluster - Here we can configure nodes according to our requirements. It is better to use as we can go deeper in EKS through this. So here we are going through this way.

No alt text provided for this image

Aim - What we are going to do :

Main aim here is to implement EKS. We are going to deploy WordPress in EKS cluster with MySQL as a secure database for it, and to store database persistent here use EFS.

  1. Create EKS cluster nodes
  2. Create EFS to use it for both WordPress and MySQL
  3. Launch WordPress and MySQL in EKS nodes
  4. Launch Prometheus and Grafana using Helm

As a prerequisite, we need following configuration -

  • aws CLI - aws CLI tool
  • eksctl - eks CLI tool
  • kubectl - kubernetes CLI tool
  • Helm - k8s package manager

First, we have to create an aws IAM user with Administrator Access and with this user configure the aws CLI.

No alt text provided for this image

with above configuration we are good to go...

  • We will use YAML for configuration

Creating cluster in EKS :

> eks-cluster.yml

apiVersion: eksctl.io/v1alpha5
kind: ClusterConfig


metadata:
  name: myekscluster
  region: ap-south-1 # Mumbai region


nodeGroups:
   - name: ng1
     desiredCapacity: 2
     instanceType: t2.micro
     ssh:
        publicKeyName: neokey
   - name: ng2
     desiredCapacity: 1
     instanceType: t2.small
     ssh:
        publicKeyName: neokey
   - name: ng-mixed # Spot instance
     minSize: 1
     maxSize: 2
     instancesDistribution:
       maxPrice: 0.025
       instanceTypes: ["t3.small", "t3.medium"] # At least one instance type should be specified
       onDemandBaseCapacity: 0
       onDemandPercentageAboveBaseCapacity: 50
       spotInstancePools: 2     
     ssh:
         publicKeyName: neokey

With this yml file we create eks cluster, it requires around 15-20 mins to get ready the cluster

No alt text provided for this image
No alt text provided for this image

Cluster will create all the required environment on aws - that we can see through console

No alt text provided for this image
No alt text provided for this image
No alt text provided for this image

After cluster is ready we must update our cluster in kube configuration so that kubectl will use only eks cluster and not local minikube cluster

No alt text provided for this image

This setup architecture -

No alt text provided for this image

For further operation it is better to use new namespace and use it as current in order to avoid any collisions with cluster. It is like allocating separate space.

No alt text provided for this image

Creating Elastic File System :

Go to your aws console and create one EFS. It must be created in same VPC as of eks cluster and have same security group

No alt text provided for this image
No alt text provided for this image

This EFS we have to provision to pods so create provisioner

> 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-3ebc29ef
            - name: AWS_REGION
              value: ap-south-1
            - name: PROVISIONER_NAME
              value: vivek/eks-efs
          volumeMounts:
            - name: pv-volume
              mountPath: /persistentvolumes
      volumes:
        - name: pv-volume
          nfs:
            server: fs-3ebc29ef.efs.ap-south-1.amazonaws.com
            path: /

Creating role based access control :

In aws there are many services and here EKS cluster should able to contact EFS, so it will need permission. Role based access control (RBAC) will give this permission.

> eks-rbac.yml

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

Creating Storage Class and Persistent Volume Claim :

Now create storage class that will use provisioned EFS. Create persistent volume claim (PVC) for both WordPress and MySQL that will provide persistent volume (PV)

> eks-storage.yml

kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
  name: aws-efs
provisioner: vivek/eks-efs # provisioner name of EFS
---
kind: PersistentVolumeClaim # PVC for WordPress
apiVersion: v1
metadata:
  name: efs-wordpress
  annotations:
    volume.beta.kubernetes.io/storage-class: "aws-efs"
spec:
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 01Gi
---
kind: PersistentVolumeClaim # PVC for MySQL
apiVersion: v1
metadata:
  name: efs-mysql
  annotations:
    volume.beta.kubernetes.io/storage-class: "aws-efs"
spec:
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 01Gi

Creating Service, Deployment, Secret :

Next, create service and deployment for both WordPress and MySQL. In case here for password storage create secret box and give its link in deployment file instead of giving password directly, this will keep our password encoded. We need this configuration in proper order, for this we will use kustomization concept that will create all files in order of preferance.

> wordpress-deployment.yml

apiVersion: v1
kind: Service
metadata:
  name: wordpress
  labels:
    app: wordpress
spec:
  ports:
    - port: 80
  selector:
    app: wordpress
    tier: frontend
  type: LoadBalancer
---
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: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

> mysql-deployment.yml

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

Customization file that will create secret first, then MySQL and last WordPress. This order must be maintained because WordPress will require MySQL and password is provided in secret.

> kustomization.yml

apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
secretGenerator:
- name: mysql-pass
  literals:
  - password=vivek
resources:
  - mysql-deployment.yml
  - wordpress-deployment.yml

Create all this configuration is sequence -

No alt text provided for this image

we can see all configured setup -

No alt text provided for this image

To launch WordPress use service external IP -

No alt text provided for this image

Now we can create blogs. Even after log out all data remains permanent in PV

No alt text provided for this image

WordPress working fine, let's get inside MySQL and see the database stored in.

No alt text provided for this image

Helm :

The package manager for Kubernetes, it will help us to find, share and use k8s apps. Helm chart is a hub for kubernetes-ready apps, with it we can discover and launch apps on the top of k8s.

For it we need two programs one is helm as a client and tiller as a server, this will work as shown below

No alt text provided for this image

Initialize helm and configure the repo from which we will use Prometheus and Grafana

No alt text provided for this image
No alt text provided for this image

Create new namespace for better management. Then create tiller service account in k8s > create role for cluster binding > initialize tiller account with upgrade. This will configure tiller server

No alt text provided for this image

Prometheus :

Prometheus is a free software application used for event monitoring and alerting. It records real-time metrics in a time series database built using a HTTP pull model, with flexible queries and real-time alerting. 

Install stable version in new namespace

No alt text provided for this image

We can see services, here I forward port 80 to 8888 because services already active on port 80.

No alt text provided for this image

Now we can use prometheus using server IP

No alt text provided for this image
No alt text provided for this image

In this manner we can set targets and monitor them.

Grafana :

Grafana is a multi-platform open source analytics and interactive visualization web application. It is expandable through a plug-in system. End users can create complex monitoring dashboards using interactive query builders.

Install stable version in new namespace

No alt text provided for this image

Now decode the password from secret yml file and use it to login.

No alt text provided for this image

We can set prometheus as a data source for visualization.

Deleting EKS cluster :

It is better to delete EKS cluster after use because it is paid service from aws. It will take some time delete everything, also cross check it from aws console. So wipe it after use and avoid any surprise bill.

No alt text provided for this image

That's it ! Thanks to Vimal Daga Sir

GitHub Reference :


To view or add a comment, sign in

More articles by Vivek Singare

Insights from the community

Others also viewed

Explore topics