You’re ready to take Tier 1 apps into production on Kubernetes, but storage is holding you back. Here’s how to configure Datera to optimize for production and scale.
You’ve containerized apps in Kubernetes and are ready to move to production, but accessing storage dynamically has been a road block. This is where your choice of underlying storage fabric can make or break your ability to scale.
Your infrastructure is a wide assortment of server and storage classes, generations, and media—each one with a different personality. With the right storage fabric, neither the app developer nor the storage admin needs to be prescriptive about which resources are the best fit—that should be determined in human language terms (e.g. super performant, highly secure) and based on Storage Classes defined in Kubernetes.
Defining Storage Classes
Optimizing storage in Kubernetes is achieved by managing a class of storage against application intent. Just like a Terraform script that defines application needs, the storage platform should supply storage needs using templates whether you’re looking for IOPs, latency, scale, efficiency (compression and dedupe), security (encryption).
Dynamic storage provisioning in Kubernetes is based on the Storage Classes. A persistent volume uses a given Storage Class specified into its definition file. A claim can request a particular class by specifying the name of a Storage Class in its definition file. Only volumes of the requested class can be bound to the claim requesting that class.
Multiple Storage Classes can be defined to match the diverse requirements on storage resources across multiple applications. This allows the cluster administrator to define multiple types of storage within a cluster, each with a custom set of parameters.
Your storage fabric should then have an intelligent optimizer that analyzes the user request, matches to resources, and places them appropriately onto a server that matches the personality of the data. It should also be policy-driven and use telemetry to continuously inventory and optimize for application and microservice needs without human involvement.
Let’s say you want to create a Storage Class to access your MySQL data, add extra protection by making 3 replicas, and place it in a higher performance tier to serve reads/writes better. You can set this up in Datera with just a few steps.
Create a Storage Class for the Datera storage backend as in the following datera-storage-class.yaml file example here:
$ cat datera-storage-class.yaml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
labels:
name: datera-storage-class
namespace:
provisioner: io.datera.csi.dsp
reclaimPolicy: Delete
parameters:
template: “basic”
secretName: “mysecret”
secretNamespace: “default”
fsType: “xfs”
$ kubectl create -f datera-storage-class.yaml
Datera allows the Kubernetes cluster administrator to configure a wide range of parameters in the Storage Class definition. Another way to define a Storage Class is with labels (policies), e.g. gold, silver, bronze. These options convey the storage personality and define necessary policies at Datera Storage System level.
It’s very easy to compose three or 300 Storage Classes on the fly in Datera. To manage data services such as dedupe, compression and encryption for high velocity apps and microservices, you can attach volumes to a storage pool that can be further configured alongside policies for data protection and efficiency. Where typically this is done in a silo, Datera can achieve this level of velocity and scale for Tier 1 workloads.
If you have absolutely no idea what the app requirements will be, that’s ok—Datera uses AI/ML to find the best placement, and the resources and will automatically adjust based on inputs. For mature apps, you can graduate those to policies and templates.
No Scale Without Automation
Kubernetes lets applications scale along with a Storage Class without deviating from the base definition/requirements of resources. Datera keeps that promise intact by binding Storage Classes to templates, and homogeneously extend resources (volumes) to match the intent of applications (consumers).
As application needs change, the storage should adapt alongside it and not rely on human intervention. This is done by defining policies and templates. The storage fabric should also recognize and adapt to new nodes or hardware and automatically adjust to enhance performance, capacity, and resilience of a cluster, as well as making the resources available to all the underlying PVs.
Create the StatefulSet:
$ kubectl create -f consul-sts.yaml
List the pods:
$ kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE
consul-0 1/1 Running 0 32s 10.38.3.152 kubew03
consul-1 0/1 PodInitializing 0 15s 10.38.4.4 kubew04
The first pod has been created. The second pod will be created only after the first one is up and running, and so on. StatefulSets behave this way because some stateful applications can fail if two or more cluster members come up at the same time. For a StatefulSet with N replicas, when pods are deployed, they are created sequentially, in order from {0…N-1} with a sticky, unique identity in the form $(statefulset name)-$(ordinal). The (i)th pod is not created until the (i-1)th is running. This ensures a predictable order of pod creation. However, if the order of pod creation is not strictly required, it is possible to create pods in parallel by setting the podManagementPolicy: Parallel option in the StatefulSet template.
List the pods again to see how the pod creation is progressing:
$ kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE
consul-0 1/1 Running 0 29m 10.38.3.152 kubew03
consul-1 1/1 Running 0 28m 10.38.4.4 kubew04
consul-2 1/1 Running 0 27m 10.38.5.128 kubew05
Now all pods are running and forming the initial cluster.
Scaling the Cluster
Scaling down a StatefulSet and then scaling it up is similar to deleting a pod and waiting for the StatefulSet to recreate it. Please, remember that scaling down a StatefulSet only deletes the pods, but leaves the Persistent Volume Claims. Also note that scaling down and scaling up is performed similar to how pods are created when the StatefulSet is created. When scaling down, the pod with the highest index is deleted first: only after that pod gets deleted, the pod with the second highest index is deleted, and so on.
What is the expected behavior scaling up the Consul cluster? Since the Consul cluster is based on the Raft algorithm, we have to scale up our 3 nodes cluster by 2 nodes at the same time because an odd number of nodes is always required to form a healthy Consul cluster. We also expect a new Persistent Volume Claim is created for each new pod.
Scale the StatefulSet:
$ kubectl scale sts consul --replicas=5
By listing the pods, we see our Consul cluster gets scaled up:
$ kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE
consul-0 1/1 Running 0 5m 10.38.3.160 kubew03
consul-1 1/1 Running 0 5m 10.38.4.10 kubew04
consul-2 1/1 Running 0 4m 10.38.5.132 kubew05
consul-3 1/1 Running 0 1m 10.38.3.161 kubew03
consul-4 1/1 Running 0 1m 10.38.4.11 kubew04
Check the membership of the scaled cluster:
$ kubectl exec -it consul-0 — consul members
NAME ADDRESS STATUS TYPE BUILD PROTOCOL DC SEGMENT
consul-0 10.38.3.160:8301 alive server 1.0.2 2 kubernetes
consul-1 10.38.4.10:8301 alive server 1.0.2 2 kubernetes
consul-2 10.38.5.132:8301 alive server 1.0.2 2 kubernetes
consul-3 10.38.3.161:8301 alive server 1.0.2 2 kubernetes
consul-4 10.38.4.11:8301 alive server 1.0.2 2 kubernetes
Also check the dynamic Datera storage provisioner created the additional volumes:
$ kubectl get pvc -o wide
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
data-consul-0 Bound pvc-91df35af-0123-11e8-86d2-000c29f8a512 1Gi RWO datera-storage-class 7m
data-consul-1 Bound pvc-a010257c-0123-11e8-86d2-000c29f8a512 1Gi RWO datera-storage-class 6m
data-consul-2 Bound pvc-adaa4d2d-0123-11e8-86d2-000c29f8a512 1Gi RWO datera-storage-class 6m
data-consul-3 Bound pvc-1b1b9bd6-0124-11e8-86d2-000c29f8a512 1Gi RWO datera-storage-class 3m
data-consul-4 Bound pvc-28feff1c-0124-11e8-86d2-000c29f8a512 1Gi RWO datera-storage-class 2m
Today, companies may be deploying apps by Storage Class. But according to IDC 90% of new applications will be built with a microservices architecture this year. Data velocity must match microservices with the right Storage Class, and continually and granularly enhance the storage environment with additional performance and capabilities—not via legacy arrays or monolithic and siloed major migrations, but via discrete racks. In other words, autonomous storage is a necessity for any business that needs to scale.