Create and Manage StatefulSets

Objective

This guide provides instructions on how to create and manage StatefulSets for applications running on Volterra vK8s deployments. A StatefulSet is a controller for stateful applications such as databases and manages the deployment and scaling of pods. It also guarantees the uniqueness and ordering of the pods.

Similar to the Deployment, the StatefulSet manages pods that are based on an identical container spec. Additionally, StatefulSet maintains a sticky identity for each pod. These pods are created from the same spec but are not interchangeable. That is, each gets a persistent identifier that it maintains across any rescheduling. For more information, see StatefulSets.

StatefulSet also supports specifying Persistent Volume Claim (PVC) for the service or application. For more information on PVC configuration, see Create and Manage PVCs.

Using the instructions provided in this guide, you can create a StatefulSet for a service, perform scaling of pods using the StatefulSet, and delete the Statefulset.

Note: For an application to consume storage resources, it needs to be provisioned by the cluster administrator. This guide assumes that the administrator configured dynamic provisioning of storage resources.


Prerequisites

The following prerequisites apply:

  • VES account

  • An application deployed using Volterra vK8s.

    • Note: See Deploy guides to deploy your applications on Volterra network cloud or edge cloud.

Configuration

You can create a StatefulSet using one of the following methods:

  • Create a StatefulSet in the VoltConsole.
  • Download the kubeconfig of your vK8s deployment from VoltConsole and use kubectl to create StatefulSet.

Note: In both methods, it is required that first you create vK8s in VoltConsole.

The example shown in this guide assumes the NGINX service is created to control network domain.

Create StatefulSet in VoltConsole

Step 1: Log into the VoltConsole and change to a desired namespace or create one where your application needs to be deployed.

Step 2: Select Applications from the configuration menu and Virtual K8s from the options pane. Click on the vK8s object to open its dashboard.

Note: In case vK8s object is not already created, the Add virtual K8s option will be available to create vK8s. See Deploy guides for more information.

Step 3: Select the StatefulSets tab and click Add StatefulSet to load the StatefulSet creation form.

Step 4: Enter the StatefulSet configuration. Click Save to create StatefulSet and associated pods.

StSUI
Figure: Create StatefulSet in VoltConsole

Note: The volumeClaimTemplates section of the configuration specifies the PVC configuration information. Also, ensure that you specify the appropriate labels in the Selector field so that the pods are selected accordingly.


Create Service and StatefulSet Using Kubectl

Step 1: Log into the VoltConsole and change to the namespace where your vK8s object is created.

Step 2: Select Applications from the configuration menu and Virtual K8s from the options pane. The vK8s object is displayed.

Note: In case vK8s object is not already created, the Add virtual K8s option will be available to create vK8s. See Deploy guides for more information.

Step 3: Click ... -> Download to download the kubeconfig file for your vK8s object. Save the file in your machine.

vK8sKubecfg
Figure: Kubeconfig for the vK8s Object

Step 4: Create a StatefulSet configuration file on your local machine in JSON or YAML format. This example shows a sample configuration.

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: web
  namespace: vk8s-sts
spec:
  selector:
    matchLabels:
      app: nginx # has to match .spec.template.metadata.labels
  serviceName: "nginx"
  replicas: 3 # by default is 1
  template:
    metadata:
      labels:
        app: nginx # has to match .spec.selector.matchLabels
    spec:
      terminationGracePeriodSeconds: 10
      containers:
      - name: nginx
        image: k8s.gcr.io/nginx-slim:0.8
        ports:
        - containerPort: 80
          name: web
        volumeMounts:
        - name: www
          mountPath: /usr/share/nginx/html
  volumeClaimTemplates:
  - metadata:
      name: www
    spec:
      accessModes: [ "ReadWriteOnce" ]
      storageClassName: "my-storage-class"
      resources:
        requests:
          storage: 1Gi

Step 5: Create and export the KUBECONFIG environment variable using the kubeconfig file downloaded in Step 3. This example uses the kubeconfig file downloaded to the Downloads folder.

export KUBECONFIG=~/Downloads/ves_vk8s-stc_vk8s1.yaml

Step 7: Create Statefulset objects using the configuration file created in Step 4.

kubectl apply -f web.yml

service/nginx created
statefulset.apps/web created

Step 8: Optionally, create a service configuration file on your local machine in JSON or YAML format and use kubectl to apply the service. This example shows a sample configuration file svc.yml.

apiVersion: v1
kind: Service
metadata:
  name: nginx
  namespace: vk8s-sts
  labels:
    app: nginx
spec:
  ports:
  - port: 80
    name: web
  clusterIP: None
  selector:
    app: nginx
  
kubectl apply -f svc.yml

Note: You can also update an existing service by adding appropriate labels of the StatefulSet to select the pods.


Verify StatefulSet Operation

Creating StatefulSet creates the StatefulSet object. It also creates pods and PVCs as per the specified value in the replicas field of StatefulSet configuration. This example assumes that the configured replicas is 2.

You can verify the objects from CLI using kubectl or from the VoltConsole.

Verify StatefulSet from CLI Using Kubectl

Step 1: Verify the StatefulSet information from CLI.

StatefulSet information:

kubectl get statefulsets
NAME   READY   AGE
web    2/2     63m

Service information:

kubectl get svc
NAME    TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)    AGE
nginx   ClusterIP   192.168.78.248   <none>        9080/TCP   62m

Step 2: Verify the ordered pods information. The StatefulSet creates pods in sequential order depending on the value of replicas. For a replicas value N, the pod sequence identifiers are assigned from 0 to N-1.

kubectl get pods
NAME                    READY   STATUS    RESTARTS   AGE
demo-ce-web-0   2/2     Running   0          66m
demo-ce-web-1   2/2     Running   0          65m

The pods in a StatefulSet have a sticky, unique identity. This identity is based on a unique ordinal index that is assigned to each pod by the StatefulSet controller. The pod names take the form <sitename>-<statefulsetname>-<ordinalindex>. Since the StatefulSet web in this example has two replicas, it creates two pods demo-ce-web-0 and demo-ce-web-1.

Note: The demo-ce-web-1 pod is not launched until the demo-ce-web-0 pod status field value is Running. For more information, see Pod Lifecycle.

Step 3: The pods are also assigned with unique networking identities for their hostname property. Verify the hostnames for the pods obtained in Step 2.

for i in 0 1; do kubectl exec demo-ce-web-$i -- sh -c 'hostname'; done
Defaulting container name to nginx.
Use 'kubectl describe pod/demo-ce-web-0 -n vk8s-sts' to see all of the containers in this pod.
web-0
Defaulting container name to nginx.
Use 'kubectl describe pod/demo-ce-web-1 -n vk8s-sts' to see all of the containers in this pod.
web-1

Note: The networking identity or hostname takes the form <StatefulSetname>-<ordinalindenx>.

Step 4: Verify the PVC information.The StatefulSet controller creates PVCs that are bound to PVs automatically.

kubectl get pvc
NAME        STATUS   VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE
www-web-0   Bound                                                      123m
www-web-1   Bound                                                      123m
                                                     4m16s

Note: The PVC name takes the form <www>-<StatefulSetname>-<ordinalindenx>. The NGINX webservers, by default, serve an index file at /usr/share/nginx/html/index.html. The volumeMounts field in the StatefulSets spec ensures that the /usr/share/nginx/html directory is backed by a PersistentVolume.

Step 3: Write the pod hostnames to the index.html file of NGINX webserver and verify that the NGINX serve the hostnames.

Writing pod hostname to index.html of NGINX webserver:

for i in 0 1; do kubectl exec demo-ce-web-$i -- sh -c 'echo $(hostname) > /usr/share/nginx/html/index.html'; done
Defaulting container name to nginx.
Use 'kubectl describe pod/demo-ce-web-0 -n vk8s-sts' to see all of the containers in this pod.
Defaulting container name to nginx.
Use 'kubectl describe pod/demo-ce-web-1 -n vk8s-sts' to see all of the containers in this pod.

Verify if NGINX serving the hostname:

for i in 0 1; do kubectl exec -it demo-ce-web-$i -- curl localhost; done
Defaulting container name to nginx.
Use 'kubectl describe pod/demo-ce-web-0 -n vk8s-sts' to see all of the containers in this pod.
web-0
Defaulting container name to nginx.
Use 'kubectl describe pod/demo-ce-web-1 -n vk8s-sts' to see all of the containers in this pod.
web-1

Verify StatefulSet in VoltConsole

Step 1: Log in to the VoltConsole and change to the namespace where you created the StatefulSet. Select Applications from the configuration menu and Virtual K8s from the options pane. Click on the vK8s object to open its dashboard.

Step 2: Click on the Pods tab to verify that the pods are created as per the replicas and StatefulSet configuration.

StsPods
Figure: StatefulSet Pods

Step 3: Click on the PVCs tab to verify that the PVCs are created as per the replicas and StatefulSet configuration.

StsPvcs
Figure: StatefulSet PVCs


Scale the StatefulSet

Scaling of a StatefulSet is increase or decrease of the number of replicas. You can perform this using VoltConsole or from CLI using kubectl. In both cases, the replicas field is updated and StatefulSet is re-applied. This example shows scale-up of the StatefulSet from the VoltConsole and verifying the scaled objects using kubectl.

Step 1: Log in to the VoltConsole and change to the namespace where you created the StatefulSet. Select Applications from the configuration menu and Virtual K8s from the options pane. Click on the vK8s object to open its dashboard.

Step 2: Selet the StatefulSets tab and click ...-> Edit against your StatefulSet object to load the edit form. Update the replicas field value to 5 and click Save to apply the changes.

StsEdit
StatefulSet Replica Update to Scale-up

Step 3: Verify that the pods are increased to 5. This example shows verification using kubectl.

kubectl get pods
NAME                    READY   STATUS    RESTARTS   AGE
demo-ce-web-0   2/2     Running   0          118m
demo-ce-web-1   2/2     Running   0          116m
demo-ce-web-2   2/2     Running   0          5m56s
demo-ce-web-3   2/2     Running   0          5m13s
demo-ce-web-4   2/2     Running   0          4m30s

Note: The StatefulSet creates each pod with sequential and unique ordinal index and waits till a pod is in ruinning status before launching the next pod.

You can also scale-down by reducing the replicas value and performing the previous steps. Scaling down triggers ordered termination of the pods. The controller deletes one pod at a time in the reverse order of its ordinal index. The controller waits for a pod to completely shutdown before attempting to terminate the next pod.

Note: Scaling down of a StatefulSet does not delete the PVCs and associated PVs.


Delete StatefulSet

You can delete StatefulSet using the kubectl delete command or from the VoltConsole.

  • To delete using kubectl, specify the StatefulSet either by file or by name.
kubectl delete -f <file.yaml>
kubectl delete statefulsets <statefulset-name>

Note: Deleting a StatefulSet through kubectl will scale it down to 0, thereby deleting all pods that are a part of it.

  • To delete from VoltConsole, change to the namespace where your application is deployed. Select Applications from the configuration menu and Virtual K8s from the options pane. Click on the vK8s objects and select StatefulSets tab in the dashboard. Click ... -> Delete for your StatefulSet and confirm deletion.

Delete_sts
Figure: Delete StatefulSet in VoltConsole

Note: Deleting the PVC after the pods have left the terminating state might trigger deletion of the PV depending on the storage class and reclaim policy. Therefore, ensure that you copied the data to someother location before attempting PVC deletion as you might also lose the PV.

Delete the StatefulSet and corresponding PVCs to delete every object associated with the StatefulSet. You can delete the objects from their respective tabs.

  • From UI:

DeleteSts-All
Figure: Delete StatefulSet and Associated PVCs

  • From CLI:
grace=$(kubectl get pods <stateful-set-pod> --template '{{.spec.terminationGracePeriodSeconds}}')
kubectl delete statefulset -l app=myapp
sleep $grace
kubectl delete pvc -l app=myapp

Concepts


API References