Guided Exercise: Select a Storage Class for an Application

Jul 12, 2023·

8 min read

Deploy a MySQL database with persistent storage based on block storage by selecting block storage instead of a default file storage.

Outcomes

You should be able to deploy applications with persistent storage and create volumes from a storage class. The storage class must meet the application storage requirements.

As the student user on the workstation machine, use the lab command to prepare your system for this exercise.

This command ensures that all resources are available for this exercise.

[student@workstation ~]$ lab start storage-classes

Procedure 5.3. Instructions

  1. Log in to the OpenShift cluster as the developer user with the developer password. Use the storage-classes project.

    1. Log in to the OpenShift cluster.

       [student@workstation ~]$ oc login -u developer -p developer \
         https://api.ocp4.example.com:6443
       Login successful.
       ...output omitted...
      
    2. Set the storage-classes project as the active project.

       [student@workstation ~]$ oc project storage-classes
       ...output omitted...
      
  2. Examine the available storage classes on the cluster. Identify an appropriate storage class to use for a database application.

    1. Use the get command to retrieve a list of storage classes in the cluster. You can use the storageclass short name, sc, in the command.

       [student@workstation ~]$ oc get sc
       NAME                    PROVISIONER                                   ...
       nfs-storage (default)   k8s-sigs.io/nfs-subdir-external-provisioner   ...
       lvms-vg1                topolvm.io                                    ...
      

      Because an administrator can change the default storage, applications must specify a storage class that meets the application requirements.

    2. Use the oc describe command to view the details of the lvms-vg1 storage class.

       [student@workstation ~]$ oc describe sc lvms-vg1
       Name:                  lvms-vg1
       IsDefaultClass:        No
       Annotations:           description=Provides RWO and RWOP Filesystem & Block volumes
       Provisioner:           topolvm.io
       Parameters:            csi.storage.k8s.io/fstype=xfs,topolvm.io/device-class=vg1
       AllowVolumeExpansion:  True
       MountOptions:          <none>
       ReclaimPolicy:         Delete
       VolumeBindingMode:     WaitForFirstConsumer
       Events:                <none>
      

      The description annotation states that the storage class provides support for block volumes. For some applications, such as databases, block volumes can provide a performance advantage over file system volumes. In the lvms-vg1 storage class, the AllowVolumeExpansion field is set to True. With volume expansion, cluster users can edit their PVC objects and specify a new size for the PVC. Kubernetes then uses the storage back end to automatically expand the volume to the requested size. Kubernetes also expands the file system of pods that use the PVC. Enabling volume expansion can help to protect an application from failing due to the data growing too fast. With these features, the lvms-vg1 storage class is a good choice for the database application.

  3. Use the registry.ocp4.example.com:8443/rhel8/mysql-80 container image to create a MySQL deployment named db-pod. Add the missing environment variables for the pod to run.

    1. Create the db-pod deployment. Ignore the warning message.

       [student@workstation ~]$ oc create deployment db-pod --port 3306 \
         --image registry.ocp4.example.com:8443/rhel8/mysql-80
       Warning: would violate PodSecurity "restricted:v1.24":
       ...output omitted...
       deployment.apps/db-pod created
      
    2. Add the environment variables. Ignore the warning message.

       [student@workstation ~]$ oc set env deployment/db-pod \
         MYSQL_USER=user1 \
         MYSQL_PASSWORD=mypa55w0rd \
         MYSQL_DATABASE=items
       Warning: would violate PodSecurity "restricted:v1.24":
       ...output omitted...
       deployment.apps/db-pod updated
      
    3. Verify that the pod is running.

       [student@workstation ~]$ oc get pods
       NAME                    READY   STATUS    RESTARTS   AGE
       db-pod-b4ccfb74-nn4s5   1/1     Running   0          5s
      
    4. Expose the db-pod deployment to create a service.

       [student@workstation ~]$ oc expose deployment/db-pod
       service/db-pod exposed
      
  4. Add a 1 Gi, RWO PVC named db-pod-odf-pvc to the deployment. Specify the volume name as odf-lvm-storage, and set the /var/lib/mysql directory as the mount path. Use the lvms-vg1 storage class to create a block mode volume.

    1. Use the oc set volume command to create a PVC for the deployment. Ignore the warning message.

       [student@workstation ~]$ oc set volumes deployment/db-pod \
         --add --name odf-lvm-storage --type pvc \
         --claim-mode rwo --claim-size 1Gi --mount-path /var/lib/mysql \
         --claim-class lvms-vg1 \
         --claim-name db-pod-odf-pvc
       ...output omitted...
       deployment.apps/db-pod volume updated
      

      The claim-class option specifies a non-default storage class.

    2. Use the oc get pvc command to view the status of the PVC. Identify the name of the PV, and confirm that the PVC uses the lvms-vg1 non-default storage class.

       [student@workstation ~]$ oc get pvc
       NAME             STATUS   VOLUME          CAPACITY   ACCESS MODES   STORAGECLASS  ...
       db-pod-odf-pvc   Bound    pvc-72...035a   1Gi        RWO            lvms-vg1   ...
      
    3. Use the oc describe pvc command to inspect the details of the db-pod-odf-pvc PVC.

       [student@workstation ~]$ oc describe pvc db-pod-odf-pvc
       Name:          db-pod-odf-pvc
       Namespace:     storage-classes
       StorageClass:  lvms-vg1
       Status:        Bound
       Volume:        pvc-b3084a46-3f32-435e-987b-4ad3b9026021
       Labels:        <none>
       Annotations:   pv.kubernetes.io/bind-completed: yes
                      pv.kubernetes.io/bound-by-controller: yes
                      volume.beta.kubernetes.io/storage-provisioner: topolvm.io
                      volume.kubernetes.io/selected-node: master01
                      volume.kubernetes.io/storage-provisioner: topolvm.io
       Finalizers:    [kubernetes.io/pvc-protection]
       Capacity:      1Gi
       Access Modes:  RWO
       VolumeMode:    Filesystem
       Used By:       db-pod-568888457d-qmxn9
       Events:
       ...output omitted...
      

      The Used By attribute confirms that the PVC is bound to a pod.

  5. Connect to the database to verify that it is working.

     [student@workstation ~]$ oc run query-db -it --rm \
       --image registry.ocp4.example.com:8443/rhel8/mysql-80 \
       --restart Never --command \
       -- /bin/bash -c "mysql -uuser1 -pmypa55w0rd --protocol tcp \
       -h db-pod -P3306 items -e 'show databases;'"
     mysql: [Warning] Using a password on the command line interface can be insecure.
     +--------------------+
     | Database           |
     +--------------------+
     | information_schema |
     | items              |
     | performance_schema |
     +--------------------+
     pod "query-db" deleted
    
  6. Observe how the oc set volume command changed the deployment.

    1. Use the oc get deployment command to view the deployment.

       [student@workstation ~]$ oc get deployment/db-pod -o yaml
       apiVersion: apps/v1
       kind: Deployment
       ...output omitted...
          spec:
             containers:
       ...output omitted...
               volumeMounts:
               - mountPath: /var/lib/mysql
                 name: odf-lvm-storage
       ...output omitted...
             volumes:
             - name: odf-lvm-storage
               persistentVolumeClaim:
                 claimName: db-pod-odf-pvc
       ...output omitted...
      
  7. Delete the db-pod deployment and the db-pod-odf-pvc PVC.

    1. Delete the db-pod deployment.

       [student@workstation ~]$ oc delete all -l app=db-pod
       pod "db-pod-568888457d-fvklp" deleted
       service "db-pod" deleted
       deployment.apps "db-pod" deleted
       replicaset.apps "db-pod-568888457d" deleted
      
    2. Verify that the PVC still exists without the deployment.

       [student@workstation ~]$ oc get pvc
       NAME            STATUS  VOLUME         CAPACITY  ACCESS MODES  STORAGECLASS ...
       db-pod-odf-pvc  Bound   pvc-72...035a  1Gi       RWO           lvms-vg1     ...
      
    3. Delete the db-pod-odf-pvc PVC.

       [student@workstation ~]$ oc delete pvc db-pod-odf-pvc
       persistentvolumeclaim "db-pod-odf-pvc" deleted
      
  8. Create a PVC for an application that requires a shared storage volume from the nfs-storage storage class.

    1. Create a PVC YAML manifest file named nfs-pvc.yaml with the following contents:

       apiVersion: v1
       kind: PersistentVolumeClaim
       metadata:
         name: nfs-pvc
       spec:
         accessModes:
         - ReadWriteOnce
         resources:
           requests:
             storage: 1Gi
         storageClassName: nfs-storage
      
    2. Create the PVC by using the oc create -f command and the YAML manifest file.

       [student@workstation ~]$ oc create -f nfs-pvc.yaml
       persistentvolumeclaim/nfs-pvc created
      
    3. Use the oc describe pvc command to view the details of the PVC resource.

       [student@workstation ~]$ oc describe pvc nfs-pvc
       Name:          nfs-pvc
       Namespace:     storage-classes
       StorageClass:  nfs-storage
       Status:        Bound
       Volume:        pvc-9f462124-d96e-43e5-96a7-f96dd9375579
       Labels:        <none>
       Annotations:   pv.kubernetes.io/bind-completed: yes
                      pv.kubernetes.io/bound-by-controller: yes
                      volume.beta.kubernetes.io/storage-provisioner: k8s-sigs.io/nfs-subdir-external-provisioner
                      volume.kubernetes.io/storage-provisioner: k8s-sigs.io/nfs-subdir-external-provisioner
       Finalizers:    [kubernetes.io/pvc-protection]
       Capacity:      1Gi
       Access Modes:  RWO
       VolumeMode:    Filesystem
       Used By:       <none>
       Events:
       ...output omitted...
      

      The Used By: <none> attribute shows that no pod is using the PVC. The Status: Bound value and the Volume attribute assignment confirm that the storage class has its VolumeBindingMode set to Immediate.

  9. Use the registry.ocp4.example.com:8443/ubi9/httpd-24:1-215 container image to create a web application deployment named web-pod.

    1. Create the web-pod deployment. Ignore the warning message.

       [student@workstation ~]$ oc create deployment web-pod --port 8080 \
         --image registry.ocp4.example.com:8443/ubi8/httpd-24:1-215
       Warning: would violate PodSecurity "restricted:v1.24":
       ...output omitted...
       deployment.apps/web-pod created
      
    2. Create a service for the web-pod application.

       [student@workstation ~]$ oc expose deployment web-pod
       service/web-pod exposed
      
    3. Expose the service to create a route for the wep-pod application. Specify web-pod.apps.ocp4.example.com as the hostname.

       [student@workstation ~]$ oc expose svc web-pod \
         --hostname web-pod.apps.ocp4.example.com
       route.route.openshift.io/web-pod exposed
      
  10. Verify that the route that is assigned to the web-pod application is accessible.

    1. View the route that is assigned to the web-pod application.

       [student@workstation ~]$ oc get routes
       NAME      HOST/PORT                       PATH   SERVICES   PORT   ...
       web-pod   web-pod.apps.ocp4.example.com          web-pod    8080   ...
      
    2. Use the curl command to view the index page of the web-pod application.

       [student@workstation ~]$ curl http://web-pod.apps.ocp4.example.com/
       <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
      
       <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
           <head>
               <title>Test Page for the HTTP Server on Red Hat Enterprise Linux</title>
       ...output omitted...
      
  11. Add the nfs-pvc PVC to the web-pod deployment.

    1. Use the oc set volume command to add the PVC to the deployment. Specify the volume name as nfs-volume, and set the mount path to the /var/www/html directory. Ignore the warning message.

       [student@workstation ~]$ oc set volumes deployment/web-pod \
         --add --name nfs-volume \
         --claim-name nfs-pvc \
         --mount-path /var/www/html
       Warning: would violate PodSecurity "restricted:v1.24":
       ...output omitted...
       deployment.apps/web-pod volume updated
      

      The volume mount-path is set to the /var/www/html directory. The server uses this path to serve HTML content.

  12. Use the registry.ocp4.example.com:8443/redhattraining/do180-roster container image to create a custom web application deployment named app-pod.

    1. Create the app-pod deployment and specify port 9090 as the target port. Ignore the warning message.

       [student@workstation ~]$ oc create deployment app-pod --port 9090 \
         --image registry.ocp4.example.com:8443/redhattraining/do180-roster
       Warning: would violate PodSecurity "restricted:v1.24":
       ...output omitted...
       deployment.apps/app-pod created
      
    2. Create a service for the app-pod application.

       [student@workstation ~]$ oc expose deployment app-pod
       service/app-pod exposed
      
    3. Expose the service to create a route for the app-pod application. Use app-pod.apps.ocp4.example.com for the hostname.

       [student@workstation ~]$ oc expose svc app-pod \
         --hostname app-pod.apps.ocp4.example.com
       route.route.openshift.io/app-pod exposed
      
  13. Add the nfs-pvc PVC to the app-pod application deployment.

    1. Use the oc set volume command to add the PVC to the deployment. Set the volume name to nfs-volume and the mount path to the /var/tmp directory. Ignore the warning message.

       [student@workstation ~]$ oc set volumes deployment/app-pod \
         --add --name nfs-volume \
         --claim-name nfs-pvc \
         --mount-path /var/tmp
       Warning: would violate PodSecurity "restricted:v1.24":
       ...output omitted...
       deployment.apps/app-pod volume updated
      

      At this point, the web-pod and the app-pod applications are sharing a PVC. Kubernetes does not have a mechanism to prevent data conflicts between the two applications. In this case, the app-pod application is a writer and the web-pod application is a reader, and thus they do not have a conflict. The application implementation, not Kubernetes, prevents data corruption from the two applications that use the same PVC. The RWO access mode does not protect data integrity. The RWO access mode means that a single node can mount the volume as read/write, and pods that share the volume must exist on the same node.

  14. Use the app-pod application to add content to the shared volume.

    1. Open a web browser to the http://app-pod.apps.ocp4.example.com/ page

    2. In the form, enter your information and then click save. The application adds your information to the list after the form.

    3. Click push to create the /var/tmp/People.html file on the shared volume.

  15. Open another tab on the browser and navigate to the http://web-pod.apps.ocp4.example.com/People.html page. The web-pod application displays the People.html file from the shared volume.

Finish

On the workstation machine, use the lab command to complete this exercise. This step is important to ensure that resources from previous exercises do not impact upcoming exercises.

[student@workstation ~]$ lab finish storage-classes