# Guided Exercise: Provision Persistent Data Volumes

Deploy a MySQL database with persistent storage from a PVC and identify the PV and storage provisioner that backs the application.

**Outcomes**

You should be able to do the following tasks:

* Deploy a MySQL database with persistent storage from a PVC.
    
* Identify the PV that backs the application.
    
* Identify the storage provisioner that created the PV.
    

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.

```plaintext
[student@workstation ~]$ lab start storage-volumes
```

**Procedure 5.2. Instructions**

1. Log in to the OpenShift cluster as the `developer` user with the `developer` password. Use the `storage-volumes` project.
    
    1. Log in to the OpenShift cluster.
        
        ```plaintext
        [student@workstation ~]$ oc login -u developer -p developer \
          https://api.ocp4.example.com:6443
        Login successful.
        ...output omitted...
        ```
        
    2. Set the `storage-volumes` project as the active project.
        
        ```plaintext
        [student@workstation ~]$ oc project storage-volumes
        ...output omitted...
        ```
        
2. Identify the default storage class for the cluster.
    
    1. Use the `oc get storageclass` command to identify the default storage class.
        
        ```plaintext
        [student@workstation ~]$ oc get storageclass
        NAME                    PROVISIONER                                   ...
        nfs-storage (default)   k8s-sigs.io/nfs-subdir-external-provisioner   ...
        lvms-vg1                topolvm.io                                    ...
        ```
        
3. Use the [`registry.ocp4.example.com:8443/rhel8/mysql-80`](http://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.
        
        ```plaintext
        [student@workstation ~]$ oc create deployment db-pod --port 3306 \
          --image=registry.ocp4.example.com:8443/rhel8/mysql-80
        ...output omitted...
        deployment.apps/db-pod created
        ```
        
    2. Add the environment variables. Ignore the warning message.
        
        ```plaintext
        [student@workstation ~]$ oc set env deployment/db-pod \
          MYSQL_USER=user1 \
          MYSQL_PASSWORD=mypa55w0rd \
          MYSQL_DATABASE=items
        ...output omitted...
        deployment.apps/db-pod updated
        ```
        
    3. Confirm that the pod is running.
        
        ```plaintext
        [student@workstation ~]$ oc get pods
        NAME                      READY   STATUS    RESTARTS   AGE
        db-pod-6ccc485cfc-vrc4r   1/1     Running   0          2m30s
        ```
        
    4. Expose the `db-pod` deployment to create a service.
        
        ```plaintext
        [student@workstation ~]$ oc expose deployment/db-pod
        service/db-pod exposed
        ```
        
4. Use the `oc get deployment` command to view the pod template specification for the deployment.
    
    1. Retrieve the pod template specification for the deployment.
        
        ```plaintext
        [student@workstation ~]$ oc get deployment/db-pod -o json | \
          jq .spec.template.spec.containers
        [
          {
            "env": [
              {
                "name": "MYSQL_USER",
                "value": "user1"
              },
              {
                "name": "MYSQL_PASSWORD",
                "value": "mypa55w0rd"
              },
              {
                "name": "MYSQL_DATABASE",
                "value": "items"
              }
            ],
            "image": "registry.ocp4.example.com:8443/rhel8/mysql-80",
            "imagePullPolicy": "Always",
            "name": "mysql-80",
            "ports": [
              {
                "containerPort": 3306,
                "protocol": "TCP"
              }
            ],
            "resources": {},
            "terminationMessagePath": "/dev/termination-log",
            "terminationMessagePolicy": "File"
          }
        ]
        ```
        
5. Add a 1 Gi, RWO PVC named `db-pod-pvc` to the deployment. Specify the volume name as `nfs-volume-storage`, and set the `/var/lib/mysql` directory as the mount path.
    
    1. Use the `oc set volume` command to create a PVC for the deployment. Ignore the warning message.
        
        ```plaintext
        [student@workstation ~]$ oc set volumes deployment/db-pod \
          --add --name nfs-volume-storage --type pvc \
          --claim-mode rwo --claim-size 1Gi --mount-path /var/lib/mysql \
          --claim-name db-pod-pvc
        ...output omitted...
        deployment.apps/db-pod volume updated
        ```
        
    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 `nfs-storage` default storage class.
        
        ```plaintext
        [student@workstation ~]$ oc get pvc
        NAME         STATUS   VOLUME          CAPACITY   ACCESS MODES   STORAGECLASS   ...
        db-pod-pvc   Bound    pvc-13...ca45   1Gi        RWO            nfs-storage    ...
        ```
        
6. Observe how the `oc set volume` command changed the deployment.
    
    1. Use the `oc get deployment` command to view the deployment again.
        
        ```plaintext
        [student@workstation ~]$ oc get deployment/db-pod -o yaml
        apiVersion: apps/v1
        kind: Deployment
        
        ...output omitted...
        
                volumeMounts:
                - mountPath: /var/lib/mysql
                  name: nfs-volume-storage
        
        ...output omitted...
        
              volumes:
              - name: nfs-volume-storage
                persistentVolumeClaim:
                  claimName: db-pod-pvc
        
        ...output omitted...
        ```
        
7. Use a `configMap` resource as a temporary volume to add initialization data to the database.
    
    1. Observe the contents of the `init-db.sql` script that initializes the database.
        
        ```plaintext
        [student@workstation ~]$ cat \
          ~/DO180/labs/storage-volumes/configmap/init-db.sql
        ```
        
        ```plaintext
         DROP TABLE IF EXISTS `Item`;
         CREATE TABLE `Item` (`id` BIGINT not null auto_increment primary key, `description` VARCHAR(100), `done` BIT);
         INSERT INTO `Item` (`id`,`description`,`done`) VALUES (1,'Pick up newspaper', 0);
         INSERT INTO `Item` (`id`,`description`,`done`) VALUES (2,'Buy groceries', 1);
        ```
        
    2. Use the contents of the `init-db.sql` file to create a `configMap` API object named `init-db-cm`.
        
        ```plaintext
        [student@workstation ~]$ oc create configmap init-db-cm \
          --from-file=/home/student/DO180/labs/storage-volumes/configmap/init-db.sql
        configmap/init-db-cm created
        ```
        
    3. Add the `init-db-cm` `configMap` resource as a volume named `init-db-volume` to the deployment. Specify the volume type as `configmap`, and set the `/tmp/init-db` directory as the mount path. Ignore the warning message.
        
        ```plaintext
        [student@workstation ~]$ oc set volumes deployment/db-pod \
          --add --name init-db-volume \
          --configmap-name init-db-cm --type configmap \
          --mount-path /tmp/init-db
        ...output omitted...
        deployment.apps/db-pod volume updated
        ```
        
    4. Capture the name of the pod in a variable.
        
        ```plaintext
        [student@workstation ~]$ PODNAME=$(oc get pods \
          -o jsonpath='{.items[0].metadata.name}')
        ```
        
    5. Start a remote shell session inside the container.
        
        ```plaintext
        [student@workstation ~]$ oc rsh $PODNAME
        sh-4.4$
        ```
        
    6. Use the `mysql` client to execute the database script in the `/tmp/init-db` volume.
        
        ```plaintext
        sh-4.4$ mysql -uuser1 -pmypa55w0rd items </tmp/init-db/init-db.sql
        mysql: [Warning] Using a password on the command line interface can be insecure.
        sh-4.4$
        ```
        
    7. Exit the shell session.
        
        ```plaintext
        sh-4.4$ exit
        ```
        
    8. Use the `oc set volume` command to remove the `init-db-volume` volume from the `dp-pod` deployment. Ignore the warning message.
        
        ```plaintext
        [student@workstation ~]$ oc set volumes deployment/db-pod \
          --remove --name init-db-volume
        ...output omitted...
        deployment.apps/db-pod volume updated
        ```
        
8. Create a `query-db` pod by using the `oc run` command and the [`registry.ocp4.example.com:8443/redhattraining/do180-dbinit`](http://registry.ocp4.example.com:8443/redhattraining/do180-dbinit) container image. Use the pod to execute a query against the database service.
    
    1. Create the `query-db` pod. Configure the pod to use the MySQL client to execute a query against the `db-pod` service. Ignore the warning message.
        
        ```plaintext
        [student@workstation ~]$ oc run query-db -it --rm \
          --image registry.ocp4.example.com:8443/redhattraining/do180-dbinit \
          --restart Never --command \
          -- /bin/bash -c "mysql -uuser1 -pmypa55w0rd --protocol tcp \
          -h db-pod -P3306 items -e 'select * from Item;'"
        mysql: [Warning] Using a password on the command line interface can be insecure.
        +----+-------------------+------------+
        | id | description       | done       |
        +----+-------------------+------------+
        |  1 | Pick up newspaper | 0x00       |
        |  2 | Buy groceries     | 0x01       |
        +----+-------------------+------------+
        pod "query-db" deleted
        ```
        
9. Delete and then re-create the `db-pod` deployment.
    
    1. Delete the `db-pod` deployment.
        
        ```plaintext
        [student@workstation ~]$ oc delete deployment/db-pod
        deployment.apps "db-pod" deleted
        ```
        
    2. Verify that the PVC still exists without the deployment.
        
        ```plaintext
        [student@workstation ~]$ oc get pvc
        NAME         STATUS   VOLUME                                     CAPACITY   ...
        db-pod-pvc   Bound    pvc-ab5b38c7-359a-4e99-b81c-f7d11ef91cc9   1Gi        ...
        ```
        
    3. Re-create the `db-pod` deployment. Ignore the warning message.
        
        ```plaintext
        [student@workstation ~]$ oc create deployment db-pod --port 3306 \
          --image=registry.ocp4.example.com:8443/rhel8/mysql-80
        ...output omitted...
        deployment.apps/db-pod created
        ```
        
    4. Add the environment variables. Ignore the warning message.
        
        ```plaintext
        [student@workstation ~]$ oc set env deployment/db-pod \
          MYSQL_USER=user1 \
          MYSQL_PASSWORD=mypa55w0rd \
          MYSQL_DATABASE=items
        ...output omitted...
        deployment.apps/db-pod updated
        ```
        
10. Use the `oc set volume` command to attach the existing PVC to the deployment. Ignore the warning message.
    
    ```plaintext
    [student@workstation ~]$ oc set volumes deployment/db-pod \
      --add --type pvc \
      --mount-path /var/lib/mysql \
      --claim-name db-pod-pvc
    info: Generated volume name: volume-kfl28
    ...output omitted...
    deployment.apps/db-pod volume updated
    ```
    
11. Create a `query-db` pod by using the `oc run` command and the [`registry.ocp4.example.com:8443/redhattraining/do180-dbinit`](http://registry.ocp4.example.com:8443/redhattraining/do180-dbinit) container image. Use the pod to execute a query against the database service.
    
    1. Create the `query-db` pod. Configure the pod to use the MySQL client to execute a query against the `db-pod` service. Ignore the warning message.
        
        ```plaintext
        [student@workstation ~]$ oc run query-db -it --rm \
          --image registry.ocp4.example.com:8443/redhattraining/do180-dbinit \
          --restart Never --command \
          -- /bin/bash -c "mysql -uuser1 -pmypa55w0rd --protocol tcp \
          -h db-pod -P3306 items -e 'select * from Item;'"
        mysql: [Warning] Using a password on the command line interface can be insecure.
        +----+-------------------+------------+
        | id | description       | done       |
        +----+-------------------+------------+
        |  1 | Pick up newspaper | 0x00       |
        |  2 | Buy groceries     | 0x01       |
        +----+-------------------+------------+
        pod "query-db" deleted
        ```
        
12. Delete the `db-pod` deployment and the `db-pod-pvc` PVC.
    
    1. Delete the `db-pod` deployment.
        
        ```plaintext
        [student@workstation ~]$ oc delete deployment/db-pod
        deployment.apps "db-pod" deleted
        ```
        
    2. Delete the `db-pod-pvc` PVC.
        
        ```plaintext
        [student@workstation ~]$ oc delete pvc/db-pod-pvc
        persistentvolumeclaim "db-pod-pvc" deleted
        ```
        

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

```plaintext
[student@workstation ~]$ lab finish storage-volumes
```
