How to Deploy stateful application in AWS EKS cluster

Stateful deployment means the deployment that contains the persistent storage. in this tutorial you will learn how to deploy an stateful application deployment.

To Perform the deployment you will need a load balancer that will route the traffic to WordPress pods and WordPress site pods will store data in MySQL pod by routing it via MySQL service as shown in below picture.

WordPress or Nginx – These are known as web layers: Here in below case we will use WordPress as a frontend which will contain persistent volume (EBS) to store HTML pages.

MongoDB or MySQL – These are known as data layers: In below case you will use MySQL will be backend that will contain Persistent volume (EBS) to store MySQL data

Prerequisites

  • EKS cluster
  • AWS account

Creating a Namespace

  1. Create a namespace with below command. Creation of namespace allows you to separate a particular project or a team or env.
kubectl create namespace stateful-deployment

Creating a Storage class required for Persistent Volume (PV)

  1. Create a Storage class that is required for persistent volume in the kubernetes cluster.
    • In AWS EKS a persistent volume (PV) is implemented via a EBS volume, which has to be declared as a storage class first and to declare a storage class first create a file gp2-storage-class.yaml and copy/paste the below code.

A PersistentVolume (PV) is a piece of storage in the cluster that has been provisioned by an administrator or dynamically provisioned using Storage Classes. It is a resource in the cluster just like a node is a cluster resource.

kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
  name: gp2
provisioner: kubernetes.io/aws-ebs
parameters:
  type: gp2
reclaimPolicy: Retain
mountOptions:
  - debug
  1. Create the Storage class by running the below command.
kubectl apply -f gp2-storage-class.yaml --namespace=stateful-deployment
  1. In case you receive any error then run below command.
kubectl patch storageclass gp2 -p '{"metadata": {"annotations":{"storageclass.kubernetes.io/is-default-class":"true"}}}' --namespace=stateful-deployment
  1. Verify all the storage class in the cluster.
kubectl get storageclasses --all-namespaces

Creating a persistent volume claim (PVC).

  1. Next, create a persistent volume claim (PVC). A stateful app can then request a volume, by specifying a persistent volume claim (PVC) and mount it in its corresponding pod. Again create a file and name it as pvc.yaml and copy/paste the below content.
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: mysql-pv-claim
  labels:
    app: wordpress
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 100Mi
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: wp-pv-claim
  labels:
    app: wordpress
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 100Mi

  • kubectl get pvc –namespace=stateful-deployment

Creating secrets to store passwords

  1. create secret which stores mysql pw, to be injected as env var into container
kubectl create secret generic mysql-pass --from-literal=password=mysql-pw --namespace=stateful-deployment
  1. Now, get or fetch the secrets that were recently created.
kubectl get secrets --namespace=stateful-deployment

Creating the Stateful backend deployment in the cluster

  1. Create a file mysql.yaml for the deployment and copy/paste the below code.
    • apiVersion is the kubernetes API version to manage the object. Here the object is service.
    • For Deployment and Replicasets : apps/v1
    • For Pod and Service: v1
  1. Kind denotes what kind of resource/object will kubernetes will create ( here in the below case : deployment)
    • metadata: Data that helps uniquely identify the object, including a name string, UID, and optional namespace.
    • Labels are key/value pairs that are attached to objects, such as pods. Labels are intended to be used to specify identifying attributes of objects that are meaningful and relevant to users. Labels can be attached to objects at creation time and subsequently added and modified at any time. Each object can have a set of key/value labels defined. Each Key must be unique for a given object.
    • spec: What state you desire for the object
    • define Label for the pod in deployment under template
    • Here you can see selector tag, which is used by deployment to talk with its pods. The selector field defines how the Deployment finds which Pods to manage. In this case, you simply select a label that is defined in the Pod template (app: nginx).
    • With labels, you can mark different types of resources in your cluster with the same key: value pair. Then, you can specify the selector to match the label so that you can build upon these other resources. If you plan to expose your app publicly, you must use a label that matches the selector that you specify in the service.
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: mysql-pv-claim
  • Launch mysql deployment and service by running the below command.
kubectl apply -f mysql.yaml --namespace=stateful-deployment

Stateless vs Stateful Deployments in the Kubernetes Cluster

Deployment with EBS v/s StatefulSet with EBS

Deployment with EBS : All the Pods are created on the same node and PV is attached

StatefulSet with EBS: Pods are created on various nodes with different EBS attached.

Deploy application using EBS vs Deploy applications using EFS

EBS

  • EBS volumes are tied to only one AZ, so recreated pods can be only started in AZ of the previous EBS volume.
  • For Example if you have an ec2 instance in AZ(a) and pod inside running inside it and attached with an EBS in AZ(a) then in case your pods gets restarted in another instance in same AZ(a) then it will be able to attach to EBS in AZ(a) but if in case pod gets restarted in another instance in different AZ(b) then it pod wont be able to attach to EBS in AZ(a) rather will need a new EBS in AZ(b)
Stateful app deployment using EBS

EFS

  • To deploy application properly you need a shared volume between all pods and deploy pods in Multi AZ.
  • EBS are not shared volume as they are EBS volumes belong a particular AZ rather than multi AZ.
  • So instead use EFS ( Elastic file system). They are mounted as network file system on multiple ec2 instances regardless of AZ.
  • EFS works with EC2 instance in multi AZ and are highly available and expensive than gp2 almost 3 times.
  • Using EFS pods can be launched on any node in any AZ
Stateful app deployment using EFS

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s