# Guided Exercise: Deploy Applications from Images and Templates

Deploy a database from a container image and from a template by using the OpenShift command-line interface and compare the resources and attributes generated by each method.

**Outcomes**

In this exercise, you deploy two MySQL database server pods to compare deployment methods and the resources that each creates.

* Deploy a database from a template.
    
* Deploy a database from a container image.
    

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

This command ensures that resources are available for the exercise.

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

**Procedure 4.1. Instructions**

1. As the `developer` user, create a project and verify that it is not empty after creation.
    
    1. Log in as the `developer` user with the `developer` password.
        
        ```plaintext
        [student@workstation ~]$ oc login -u developer -p developer \
          https://api.ocp4.example.com:6443
        ...output omitted...
        ```
        
    2. Create a project named `deploy-newapp`.
        
        ```plaintext
        [student@workstation ~]$ oc new-project deploy-newapp
        Now using project "deploy-newapp" on server ...output omitted...
        ```
        
        The new project is automatically selected.
        
    3. Observe that resources for the new project are not returned with the `oc get all` command.
        
        ```plaintext
        [student@workstation ~]$ oc get all
        No resources found in deploy-newapp namespace.
        ```
        
        ### **IMPORTANT**
        
        Commands that use `all` for the resource type do not include every available resource type. Instead, `all` is a shorthand form for a predefined subset of types. When you use this command argument, ensure that `all` includes any types that you intend to address.
        
    4. Observe that the new project contains other types of resources.
        
        ```plaintext
        [student@workstation ~]$ oc get serviceaccounts
        NAME       SECRETS   AGE
        builder    1         20s
        default    1         20s
        deployer   1         20s
        ```
        
        ```plaintext
        [student@workstation ~]$ oc get secrets
        NAME                       TYPE                                  DATA   AGE
        builder-dockercfg-sczxg    kubernetes.io/dockercfg               1      36m
        builder-token-gsnqj        kubernetes.io/service-account-token   4      36m
        default-dockercfg-6f8nm    kubernetes.io/dockercfg               1      36m
        ...output omitted...
        ```
        
2. Create two MySQL instances by using the `oc new-app` command with different options.
    
    1. View the `mysql-persistent` template definition to see the resources that it creates. Specify the project that houses the template by using the `-n openshift` option.
        
        ```plaintext
        [student@workstation ~]$ oc describe template mysql-persistent -n openshift
        Name:		mysql-persistent
        Namespace:	openshift
        ...output omitted...
        Objects:
            Secret	                              ${DATABASE_SERVICE_NAME}
            Service	                             ${DATABASE_SERVICE_NAME}
            PersistentVolumeClaim	               ${DATABASE_SERVICE_NAME}
            DeploymentConfig.apps.openshift.io	  ${DATABASE_SERVICE_NAME}
        ```
        
        The `objects` attribute specifies several resource definitions that are applied on using the template. These resources include one of each of the following types: secret, service (`svc`), persistent volume claim (`pvc`), and deployment configuration (`dc`).
        
    2. Create an instance by using the `mysql-persistent` template. Specify a `name` option and attach a custom `team=red` label to the created resources.
        
        ```plaintext
        [student@workstation ~]$ oc new-app -l team=red --template mysql-persistent \
          -p MYSQL_USER=developer \
          -p MYSQL_PASSWORD=developer
        ...output omitted...
        --> Creating resources with label team=red ...
            secret "mysql" created
            service "mysql" created
            persistentvolumeclaim "mysql" created
            deploymentconfig.apps.openshift.io "mysql" created
        --> Success
        ...output omitted...
        ```
        
        The template creates resources of the types from the preceding step.
        
    3. View and wait for the pod to start, which takes a few minutes to complete. You might need to run the command several times before the status changes to `Running`.
        
        ```plaintext
        [student@workstation ~]$ oc get pods
        NAME              READY   STATUS      RESTARTS  AGE
        mysql-1-deploy    0/1     Completed   0         93s
        mysql-1-qmxbf     1/1     Running     1         60s
        ```
        
        Your pod names might differ from the previous output.
        
    4. Create an instance by using a container image. Specify a `name` option and attach a custom `team=blue` label to the created resources.
        
        ```plaintext
        [student@workstation ~]$ oc new-app --name db-image -l team=blue \
          --image registry.ocp4.example.com:8443/rhel9/mysql-80:1 \
          -e MYSQL_USER=developer \
          -e MYSQL_PASSWORD=developer \
          -e MYSQL_ROOT_PASSWORD=redhat
        ...output omitted...
        --> Creating resources with label team=blue ...
            imagestream.image.openshift.io "db-image" created
        Warning: would violate PodSecurity "restricted:v1.24": ...output omitted...
            deployment.apps "db-image" created
            service "db-image" created
        --> Success
        ...output omitted...
        ```
        
        The command creates predefined resources that are needed to deploy an image. These resource types are image stream (`is`), deployment, and service (`svc`). Image streams and services are discussed in more detail elsewhere in the course.
        
        ### **NOTE**
        
        It is safe to ignore pod security warnings for exercises in this course. OpenShift uses the Security Context Constraints controller to provide safe defaults for pod security.
        
    5. Wait for the pod to start. After a few moments, list all pods that contain `team` as a label.
        
        ```plaintext
        [student@workstation ~]$ oc get pods -L team
        NAME                       READY   STATUS      RESTARTS   AGE    TEAM
        db-image-8d4b97594-6jb85   1/1     Running     1          55s    blue
        mysql-1-deploy             0/1     Completed   0          2m
        mysql-1-hn64v              1/1     Running     0          1m30s
        ```
        
        Your pod name might differ from the previous output. Without a `readinessProbe`, this pod shows as ready before the MySQL service is ready for requests. Readiness probes are discussed in more detail elsewhere in the course.
        
        Notice that only the `db-image` pod has a label that contains the word `team`. Pods that the `mysql-persistent` template creates do not have the `team=red` label, because the template does not define this label in its pod specification template.
        
3. Compare the resources that each image and template method creates.
    
    1. View the `template-created` pod and observe that it contains a readiness probe.
        
        ```plaintext
        [student@workstation ~]$ oc get pods -l deploymentconfig=mysql \
          -o jsonpath='{.items[0].spec.containers[0].readinessProbe}' | jq
        {
          "exec": {
            "command": [
              "/bin/sh",
              "-i",
              "-c",
              "MYSQL_PWD=\"$MYSQL_PASSWORD\" mysqladmin -u $MYSQL_USER ping"
            ]
          },
          "failureThreshold": 3,
          "initialDelaySeconds": 5,
          "periodSeconds": 10,
          "successThreshold": 1,
          "timeoutSeconds": 1
        }
        ```
        
        ### **NOTE**
        
        The results of the preceding `oc` command are passed to the `jq` command, which formats the JSON output.
        
    2. Observe that the image-based pod does not contain a readiness probe.
        
        ```plaintext
        [student@workstation ~]$ oc get pods -l deployment=db-image \
          -o jsonpath='{.items[0].spec.containers[0].readinessProbe}' | jq
        no output expected
        ```
        
    3. Observe that the template-based pod has a memory resource limit, which restricts allocated memory to the resulting pods. Resource limits are discussed in more detail elsewhere in the course.
        
        ```plaintext
        [student@workstation ~]$ oc get pods -l deploymentconfig=mysql \
          -o jsonpath='{.items[0].spec.containers[0].resources.limits}' | jq
        {
          "memory": "512Mi"
        }
        ```
        
    4. Observe that the image-based pod has no resource limits.
        
        ```plaintext
        [student@workstation ~]$ oc get pods -l deployment=db-image \
          -o jsonpath='{.items[0].spec.containers[0].resources}' | jq
        {}
        ```
        
    5. Retrieve secrets in the project. Notice that the template produced a secret, whereas the pod that was created with only an image did not.
        
        ```plaintext
        [student@workstation ~]$ oc get secrets
        NAME                       TYPE                                  DATA   AGE
        ...output omitted...
        mysql                      Opaque                                4      3m
        ```
        
4. Explore filtering resources via labels.
    
    1. Observe that not supplying a label shows all services.
        
        ```plaintext
        [student@workstation ~]$ oc get services
        NAME       TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
        db-image   ClusterIP   172.30.38.113   <none>        3306/TCP   1m30s
        mysql      ClusterIP   172.30.95.52    <none>        3306/TCP   2m30s
        ```
        
    2. Observe that supplying a label shows only the services with the label.
        
        ```plaintext
        [student@workstation ~]$ oc get services -l team=red
        NAME    TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)    AGE
        mysql   ClusterIP   172.30.95.52   <none>        3306/TCP   2m43s
        ```
        
    3. Observe that not all resources include the label, such as the pods that are created with the template.
        
        ```plaintext
        [student@workstation ~]$ oc get pods -l team=red
        No resources found in deploy-newapp namespace.
        ```
        
5. Use labels to delete only the resources that are associated with the image-based deployment.
    
    1. Delete only the resources that use the `team=red` label by using it with the `oc delete` command. List the resource types from the template to ensure that all relevant resources are deleted.
        
        ```plaintext
        [student@workstation ~]$ oc delete all -l team=red
        replicationcontroller "mysql-1" deleted
        service "mysql" deleted
        deploymentconfig.apps.openshift.io "mysql" deleted
        ```
        
        ```plaintext
        [studen@workstation ~]$ oc delete secret,pvc -l team=red
        secret "mysql" deleted
        persistentvolumeclaim "mysql" deleted
        ```
        
        ### **NOTE**
        
        By using the `oc delete all -l team=red` command, some resources are deleted, but the persistent volume claim and secret remain.
        
    2. Observe that the resources that the template created are deleted.
        
        ```plaintext
        [student@workstation ~]$ oc get secret,svc,pvc,dc -l team=red
        No resources found in deploy-newapp namespace.
        ```
        
    3. Observe that the image-based resources remain unchanged.
        
        ```plaintext
        [student@workstation ~]$ oc get is,deployment,svc
        NAME                                      IMAGE REPOSITORY ...output omitted...
        imagestream.image.openshift.io/db-image   image-registry.openshift...output omitted...
        NAME                       READY   UP-TO-DATE   AVAILABLE   AGE
        deployment.apps/db-image   1/1     1            1           46m
        
        NAME               TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)    AGE
        service/db-image   ClusterIP   172.30.71.0   <none>        3306/TCP   46m
        ```
        

**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 deploy-newapp
```
