# Lab: Deploy Web Applications

Use image streams with Kubernetes workload resources to ensure reproducibility of application deployments.

Configure applications by using Kubernetes secrets to initialize environment variables.

Provide applications with persistent storage volumes.

Expose applications to clients outside the cluster.

**Outcomes**

You should be able to create and configure OpenShift and Kubernetes resources, such as projects, secrets, deployments, persistent volumes, services, and routes.

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. The command also creates the `/home/student/DO180/labs/compreview-deploy/resources.txt` file. The `resources.txt` file contains the URLs of your OpenShift cluster and the image names that you use in the exercise. You can use the file to copy and paste these URLs and image names.

```plaintext
[student@workstation ~]$ lab start compreview-deploy
```

**Specifications**

The API URL of your OpenShift cluster is [https://api.ocp4.example.com:6443](https://api.ocp4.example.com:6443), and the `oc` command is already installed on your `workstation` machine.

The URL of the OpenShift web console is [https://console-openshift-console.apps.ocp4.example.com](https://console-openshift-console.apps.ocp4.example.com). When you access the web console, select **Red Hat Identity Management** as the authentication mechanism.

Log in to the OpenShift cluster as the `developer` user with the `developer` password. The password for the `admin` user is `redhatocp`, although you do not need administrator privileges to complete the exercise.

In this exercise, you deploy a web application and its database for testing purposes. The resulting configuration is not ready for production, because you do not configure probes and resource limits, which are required for production. Another comprehensive review exercise covers these subjects.

Perform the following tasks to complete the exercise:

* Create a project named `review` to store all of your work.
    
* Configure your project so that its workloads refer to the database image by the `mysql8:1` short name.
    
    * The short name must point to the [`registry.ocp4.example.com:8443/rhel9/mysql-80:1-228`](http://registry.ocp4.example.com:8443/rhel9/mysql-80:1-228) container image. The database image name and its source registry are expected to change in the near future, and you want to isolate your workloads from that change.
        
        The classroom setup copied the image from the Red Hat Ecosystem Catalog. The original image is [`registry.redhat.io/rhel9/mysql-80:1-228`](http://registry.redhat.io/rhel9/mysql-80:1-228).
        
    * Ensure that the workload resources in the `review` project can use the `mysql8:1` resource. You create these workload resources in a later step.
        
* Create the `dbparams` secret to store the MySQL database parameters. Both the database and the front-end deployment need these parameters. The `dbparams` secret must include the following variables:
    
    | Name | Value |
    | --- | --- |
    | `user` | `operator1` |
    | `password` | `redhat123` |
    | `database` | `quotesdb` |
    
* Create the `quotesdb` deployment and configure it as follows:
    
    * Use the `mysql8:1` image for the deployment.
        
    * The database must automatically roll out whenever the source container in the `mysql8:1` resource changes.
        
        To test your configuration, you can change the `mysql8:1` image to point to the [`registry.ocp4.example.com:8443/rhel9/mysql-80:1-237`](http://registry.ocp4.example.com:8443/rhel9/mysql-80:1-237) container image that the classroom provides, and then verify that the `quotesdb` deployment rolls out. Remember to reset the `mysql8:1` image to the [`registry.ocp4.example.com:8443/rhel9/mysql-80:1-228`](http://registry.ocp4.example.com:8443/rhel9/mysql-80:1-228) container image before grading your work.
        
    * Define the following environment variables in the deployment from the keys in the `dbparams` secret:
        
        | Environment variable | `dbparams` secret key |
        | --- | --- |
        | `MYSQL_USER` | `user` |
        | `MYSQL_PASSWORD` | `password` |
        | `MYSQL_DATABASE` | `database` |
        
    * Ensure that OpenShift preserves the database data between pod restarts. This data does not consume more than 2 GiB of disk space. The MySQL database stores its data under the `/﻿var/lib/mysql` directory. Use the `lvms-vg1` storage class for the volume.
        
* Create a `quotesdb` service to make the database available to the front-end web application. The database service is listening on port 3306.
    
* Create the `frontend` deployment and configure it as follows:
    
    * Use the [`registry.ocp4.example.com:8443/redhattraining/famous-quotes:2-42`](http://registry.ocp4.example.com:8443/redhattraining/famous-quotes:2-42) image. For this deployment, you refer to the image by its full name, because your organization develops the image and controls its release process.
        
    * Define the following environment variables in the deployment:
        
        | Environment variable name | Value |
        | --- | --- |
        | `QUOTES_USER` | The `user` key from the `dbparams` secret |
        | `QUOTES_PASSWORD` | The `password` key from the `dbparams` secret |
        | `QUOTES_DATABASE` | The `database` key from the `dbparams` secret |
        | `QUOTES_HOSTNAME` | `quotesdb` |
        
* You cannot yet test the application from outside the cluster. Expose the `frontend` deployment so that the application can be reached at [http://frontend-review.apps.ocp4.example.com](http://frontend-review.apps.ocp4.example.com).
    
    The `frontend` deployment is listening to port 8000.
    
    When you access the [http://frontend-review.apps.ocp4.example.com](http://frontend-review.apps.ocp4.example.com) URL, the application returns a list of quotations from famous authors.
    

1. Log in to the OpenShift cluster from the command line, and then create the `review` project.
    
    1. Log in as the `developer` user.
        
        ```plaintext
        [student@workstation ~]$ oc login -u developer -p developer \
          https://api.ocp4.example.com:6443
        Login successful.
        ...output omitted...
        ```
        
    2. Create the `review` project.
        
        ```plaintext
        [student@workstation ~]$ oc new-project review
        Now using project "review" on server "https://api.ocp4.example.com:6443".
        ...output omitted...
        ```
        
2. Create the `mysql8:1` image stream tag from the [`registry.ocp4.example.com:8443/rhel9/mysql-80:1-228`](http://registry.ocp4.example.com:8443/rhel9/mysql-80:1-228) image. Enable image stream resolution for the `mysql8` image stream so that Kubernetes resources in the current project can use it.
    
    1. Use the `oc create istag` command to create the image stream and the image stream tag.
        
        ```plaintext
        [student@workstation ~]$ oc create istag mysql8:1 \
          --from-image registry.ocp4.example.com:8443/rhel9/mysql-80:1-228
        imagestreamtag.image.openshift.io/mysql8:1 created
        ```
        
    2. Use the `oc set image-lookup` command to enable image lookup resolution.
        
        ```plaintext
        [student@workstation ~]$ oc set image-lookup mysql8
        imagestream.image.openshift.io/mysql8 image lookup updated
        ```
        
    3. Run the `oc set image-lookup` command without any arguments to verify your work.
        
        ```plaintext
        [student@workstation ~]$ oc set image-lookup
        NAME    LOCAL
        mysql8  true
        ```
        
3. Create the `dbparams` secret.
    
    ```plaintext
    [student@workstation ~]$ oc create secret generic dbparams \
      --from-literal user=operator1 --from-literal password=redhat123 \
      --from-literal database=quotesdb
    secret/dbparams created
    ```
    
4. Create the `quotesdb` deployment from the `mysql8:1` image stream tag. Set the number of replicas to zero, to prevent OpenShift from deploying the database before you finish its configuration. Ignore the warning message.
    
    ```plaintext
    [student@workstation ~]$ oc create deployment quotesdb --image mysql8:1 \
      --replicas 0
    Warning: would violate PodSecurity "restricted:v1.24":
    ...output omitted...
    deployment.apps/quotesdb created
    ```
    
5. Add an image trigger to the `quotesdb` deployment.
    
    1. Retrieve the name of the container from the `quotesdb` deployment.
        
        ```plaintext
        [student@workstation ~]$ oc get deployment quotesdb -o wide
        NAME       READY   UP-TO-DATE   AVAILABLE   AGE   CONTAINERS ...
        quotesdb   0/0     0            0           11s   mysql8     ...
        ```
        
    2. Use the `oc set triggers` command to add the trigger for the `mysql8:1` image stream tag to the `mysql8` container. Ignore the warning message.
        
        ```plaintext
        [student@workstation ~]$ oc set triggers deployment/quotesdb \
          --from-image mysql8:1 --containers mysql8
        Warning: would violate PodSecurity "restricted:v1.24":
        ...output omitted...
        deployment.apps/quotesdb triggers updated
        ```
        
6. Add environment variables to the `quotesdb` deployment from the `dbparams` secret. Add the `MYSQL_` prefix to each variable name. Ignore the warning message.
    
    ```plaintext
    [student@workstation ~]$ oc set env deployment/quotesdb \
      --from secret/dbparams --prefix MYSQL_
    Warning: would violate PodSecurity "restricted:v1.24":
    ...output omitted...
    deployment.apps/quotesdb updated
    ```
    
7. Add a 2 GiB persistent volume to the `quotesdb` deployment. Use the `lvms-vg1` storage class. Inside the pods, mount the volume under the `/var/lib/mysql` directory. Ignore the warning message.
    
    ```plaintext
    [student@workstation ~]$ oc set volumes deployment/quotesdb --add \
      --claim-class lvms-vg1 --claim-size 2Gi --mount-path /var/lib/mysql
    info: Generated volume name: volume-n7xpd
    Warning: would violate PodSecurity "restricted:v1.24":
    ...output omitted...
    deployment.apps/quotesdb volume updated
    ```
    
8. Start the database by scaling up the `quotesdb` deployment to one replica.
    
    1. Scale up the deployment.
        
        ```plaintext
        [student@workstation ~]$ oc scale deployment/quotesdb --replicas 1
        deployment.apps/quotesdb scaled
        ```
        
    2. Wait for the pod to start. You might have to rerun the command several times for the pod to report a `Running` status. The name of the pod on your system probably differs.
        
        ```plaintext
        [student@workstation ~]$ oc get pods
        NAME                       READY   STATUS    RESTARTS   AGE
        quotesdb-99f9b4ff8-ggs7z   1/1     Running   0          4s
        ```
        
9. Create the `quotesdb` service for the `quotesdb` deployment. The database server is listening on port 3306.
    
    1. Use the `oc expose deployment` command to create the service.
        
        ```plaintext
        [student@workstation ~]$ oc expose deployment quotesdb --port 3306
        service/quotesdb exposed
        ```
        
    2. Verify that OpenShift associates the IP address of the MySQL server with the endpoint. The endpoint IP address on your system probably differs.
        
        ```plaintext
        [student@workstation ~]$ oc describe service quotesdb
        Name:              quotesdb
        Namespace:         review
        ...output omitted...
        TargetPort:        3306/TCP
        Endpoints:         10.8.0.123:3306
        Session Affinity:  None
        Events:            <none>
        ```
        
10. Create the `frontend` deployment from the [`registry.ocp4.example.com:8443/redhattraining/famous-quotes:2-42`](http://registry.ocp4.example.com:8443/redhattraining/famous-quotes:2-42) image. Set the number of replicas to zero, to prevent OpenShift from deploying the application before you finish its configuration. Ignore the warning message.
    
    ```plaintext
    [student@workstation ~]$ oc create deployment frontend \
      --image registry.ocp4.example.com:8443/redhattraining/famous-quotes:2-42 \
      --replicas 0
    Warning: would violate PodSecurity "restricted:v1.24":
    ...output omitted...
    deployment.apps/frontend created
    ```
    
11. Add environment variables to the `frontend` deployment from the `dbparams` secret, and add the `QUOTES_HOSTNAME` variable with the `quotesdb` value.
    
    1. Add the variables from the `dbparams` secret. Add the `QUOTES_` prefix to each variable name. Ignore the warning message.
        
        ```plaintext
        [student@workstation ~]$ oc set env deployment/frontend \
          --from secret/dbparams --prefix QUOTES_
        Warning: would violate PodSecurity "restricted:v1.24":
        ...output omitted...
        deployment.apps/frontend updated
        ```
        
    2. Declare the `QUOTES_HOSTNAME` variable. Ignore the warning message.
        
        ```plaintext
        [student@workstation ~]$ oc set env deployment/frontend QUOTES_HOSTNAME=quotesdb
        Warning: would violate PodSecurity "restricted:v1.24":
        ...output omitted...
        deployment.apps/frontend updated
        ```
        
12. Start the application by scaling up the `frontend` deployment to one replica.
    
    1. Scale up the deployment.
        
        ```plaintext
        [student@workstation ~]$ oc scale deployment/frontend --replicas 1
        deployment.apps/frontend scaled
        ```
        
    2. Wait for the pod to start. You might have to rerun the command several times for the pod to report a `Running` status. The name of the pod on your system probably differs.
        
        ```plaintext
        [student@workstation ~]$ oc get pods
        NAME                       READY   STATUS    RESTARTS   AGE
        frontend-86cdd7c7bf-hpnwz  1/1     Running   0          44s
        quotesdb-99f9b4ff8-ggs7z   1/1     Running   0          2m11s
        ```
        
13. Expose the `frontend` deployment so that the application is accessible from outside the cluster. The web application is listening on port 8000.
    
    1. Create the `frontend` service for the `frontend` deployment.
        
        ```plaintext
        [student@workstation ~]$ oc expose deployment frontend --port 8000
        service/frontend exposed
        ```
        
    2. Create the route.
        
        ```plaintext
        [student@workstation ~]$ oc expose service frontend
        route.route.openshift.io/frontend exposed
        ```
        
    3. Retrieve the application URL from the route.
        
        ```plaintext
        [student@workstation ~]$ oc get route
        NAME       HOST/PORT                               PATH   SERVICES ...
        frontend   frontend-review.apps.ocp4.example.com          frontend ...
        ```
        
    4. Use the `curl` command to test the application.
        
        ```plaintext
        [student@workstation ~]$ curl http://frontend-review.apps.ocp4.example.com
        <html>
        	<head>
                <title>Quotes</title>
            </head>
            <body>
        
                <h1>Quote List</h1>
        
                    <ul>
        
                            <li>1: When words fail, music speaks.
        - William Shakespeare
        </li>
        ...output omitted...
        ```
        

[Hide Solution](https://rol.redhat.com/rol/app/#)

**Evaluation**

As the `student` user on the `workstation` machine, use the `lab` command to grade your work. Correct any reported failures and rerun the command until successful.

```plaintext
[student@workstation ~]$ lab grade compreview-deploy
```

**Finish**

As the `student` user 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 compreview-deploy
```
