IBM Cloud Satellite: Run and manage services anywhere Learn more

Deploy Appsody applications to OpenShift

In this tutorial, we show you how to use Appsody to deploy a sample insurance quote application to Red Hat® OpenShift®. We show you how to host your container images on OpenShift’s internal registry and how to use a ConfigMap resource to store an API key. In our example, we use the Dacadoo API key.

Specifically, we make use of the following commands throughout this tutorial:

  • appsody build will create a container image
  • apposdy deploy will deploy the image to a cluster

This tutorial is an extension of the “Create an insurance quote application using Appsody” code pattern. The original code pattern shows you how deploy to an IBM Kubernetes Service and to store container images on the IBM Container Registry. This tutorial deploys to OpenShift and uses OpenShift’s internal registry to store container iamges.

Learning objectives

After completing this exercise, you will understand how to:

  • Deploy an application to OpenShift using the Appsody CLI
  • Access OpenShift’s internal registry
  • Configure and consume a ConfigMap

Prerequisites

  • Understand the “Create an insurance quote application using Appsody” code pattern. Specifically, performing Steps 1-3 (clone, run frontend locally, run backend locally) is essential before starting this tutorial.

  • Install the Appsody CLI.

  • Get access to a Red Hat OpenShift on IBM Cloud cluster.
  • (Optional) Obtain a Dacadoo API key.
    • Record the URL for the API (usually https://models.dacadoo.com/score/2) and the key (something similar to UFDzMHAfsEg0oKzGp4rCSmXPClKKq3hDPLbPdvc2h).
    • There is a mock implementation of the API in the code that you can use if you do not want to register.

Estimated time

Completing the steps in this tutorial should take about 45 minutes.

Steps

  1. Set up a project namespace
  2. Access the internal Docker Registry
  3. Deploy the back-end application to OpenShift
  4. Deploy the front-end application to OpenShift

1. Set up a project namespace

OpenShift applications are deployed within a project. So, the first step of this tutorial is to create a new project. Run the following command from a terminal:

oc new-project insurance-quote

You should see output similar to the following:

$ oc new-project insurance-quote
Now using project "insurance-quote" on server "https://c100-e.us-east.containers.cloud.ibm.com:31718".

You can add applications to this project with the 'new-app' command. For example, try:

    oc new-app centos/ruby-25-centos7~https://github.com/sclorg/ruby-ex.git

to build a new example application in Ruby.

Check that the current context is your team’s project space.

oc project -q

2. Access the internal Docker registry

Now you need a spot to push the newly built Docker images that Appsody created. Luckily, OpenShift comes with an internal Docker registry you can use. However, by default, this registry is not enabled for public access.

If you run the oc get route --all-namespaces command below, you’ll see that only a dashboard for the registry is available, which is not quite what we need.

oc get route --all-namespaces | grep registry

You should see output similar to the following:

$ oc get route --all-namespaces | grep registry
default    registry-console    registry-console-default.cp4apps-workshop-prop-5290c8c8e5797924dc1ad5d1b85b37c0-0001.us-east.containers.appdomain.cloud

Docker Registry GUI

To access the internal registry, you need to create a route and expose it. See the IBM Cloud documentation for the complete steps, but here is the short version.

  1. Run the following command to create a new route.

     oc create route reencrypt docker-registry --service=docker-registry -n default
    
  2. You can now get the Docker registry URL, like so:

     oc get route --all-namespaces | grep registry
    

    You should see output similar to the following:

     $ oc get route --all-namespaces | grep registry
     default    docker-registry    docker-registry-default.cp4apps-workshop-prop-5290c8c8e5797924dc1ad5d1b85b37c0-0001.us-    east.containers.appdomain.cloud
     default    registry-console    registry-console-default.cp4apps-workshop-prop-5290c8c8e5797924dc1ad5d1b85b37c0-0001.us-    east.containers.appdomain.cloud
    

    The URL you want to use is the docker-registry one. It’ll look like docker-registry-default.*.containers.appdomain.cloud.

  3. Once you have the URL, set it as a variable:

     export IMAGE_REGISTRY=<docker_url>
    
  4. And set your local docker command to use that registry. Use docker login:

     docker login -u $(oc whoami) -p $(oc whoami -t) $IMAGE_REGISTRY
    

3. Deploy the back-end application to OpenShift

The appsody deploy command is used for deployments. This command:

  • builds a deployment image for production usage (for example, it does not include development-mode tools)
  • pushes the image to your designated image registry
  • builds a deployment YAML file (if you have not generated one already), as a CR for the Appsody Operator
  • applies the YAML file to your Kubernetes cluster

Appsody has the ability to deploy directly to a Kubernetes cluster using a default deployment manifest. This works if the cluster does not require any specific credentials.

In this example, you need to provide the credentials, so Appsody allows you to generate the deployment manifest it would have used, but without doing the actual deployment. You can then modify the manifest, and ask Appsody to use it for the deployment of your applications.

3.1 Create a ConfigMap for the Dacadoo API key

To have the back-end application send requests to the Dacadoo Health Score API, you need to create a secret that contains the configuration for making requests to the Dacadoo server. You obtained the Health Score API in the prerequisites of this tutorial. (Note: If you do not want to use the Dacadoo Health Score API, you can skip this setup and continue to use the mock endpoint.)

oc create configmap dacadoo-config --from-literal=url=<url> --from-literal=apikey=<apikey>

where:

  • <url> is the URL of the Dacadoo server (usually https://models.dacadoo.com/score/2)
  • <apikey> is the API key that you obtained when you registered to use the API.

for example:

oc create configmap dacadoo-config --from-literal=DACADOO_URL=https://models.dacadoo.com/score/2 --from-literal=DACADOO_APIKEY=Y3VB...RMGG
configmap/dacadoo-config created

3.2 Deploy the back-end application

IMPORTANT: This part of the exercise extends the initial code pattern which shows you how to create the initial code for the back end.

  1. Navigate to your quote-backend directory. You need to modify the deployment YAML to pass the secret’s values to the application. You can generate the initial deployment YAML as follows:

     cd ~/appsody-apps/quote-backend
     appsody deploy --generate-only
    

    This creates a file named app-deploy.yaml in your project.

     apiVersion: appsody.dev/v1beta1
     kind: AppsodyApplication
     metadata:
       name: quote-backend
     spec:
       # Add fields here
       version: 1.0.0
       applicationImage: dev.local/quote-backend
       stack: java-spring-boot2
       service:
         type: NodePort
         port: 8080
         annotations:
           prometheus.io/scrape: 'true'
           prometheus.io/path: '/actuator/prometheus'
       readinessProbe:
         failureThreshold: 12
         httpGet:
           path: /actuator/health
           port: 8080
         initialDelaySeconds: 5
         periodSeconds: 2
       livenessProbe:
         failureThreshold: 12
         httpGet:
           path: /actuator/liveness
           port: 8080
         initialDelaySeconds: 5
         periodSeconds: 2
       expose: true
       createKnativeService: false
    
  2. You need to add a section to the generated file. Under the spec key, create a new envFrom key that has the value of your OpenShift ConfigMap. dacadoo-config is used as the name in this workshop.

    TIP: Ensure there are two spaces before name, see this GitHub issue

     apiVersion: appsody.dev/v1beta1
     kind: AppsodyApplication
     metadata:
       name: quote-backend
     spec:
       # Add fields here
       version: 1.0.0
       .
       .
       envFrom:
         - configMapRef:
             name: dacadoo-config
       expose: true
       createKnativeService: false
    
  3. Now use appsody deploy to push the image and deploy it. When using the OpenShift Docker registry, the URLs used to push and pull a given image are different. appsody deploy allows you to specify these URLs on the command line:

     appsody deploy --tag insurance-quote/quote-backend:v1 --push-url $IMAGE_REGISTRY --push --pull-url docker-registry.default.svc:5000 --namespace insurance-quote
    

    You should see output similar to the following:

     $ appsody deploy --tag insurance-quote/quote-backend:v1 --push-url $IMAGE_REGISTRY --push --pull-url docker-registry.default.svc:5000 --namespace insurance-quote
     .
     .
     [Docker] Successfully built 4294712e0f9e
     [Docker] Successfully tagged docker-registry-default.cp4apps-workshop-prop-5290c8c8e5797924dc1ad5d1b85b37c0-0001.us-  east.containers.appdomain.cloud/insurance-quote/quote-backend:v1
     Built docker image docker-registry-default.cp4apps-workshop-prop-5290c8c8e5797924dc1ad5d1b85b37c0-0001.us-east.containers.appdomain.cloud/insurance-quote/quote-backend:v1
     Using applicationImage of: docker-registry-default.cp4apps-workshop-prop-5290c8c8e5797924dc1ad5d1b85b37c0-0001.us-east.containers.appdomain.cloud/insurance-quote/quote-backend:v1
     Pushing docker image docker-registry-default.cp4apps-workshop-prop-5290c8c8e5797924dc1ad5d1b85b37c0-0001.us-east.containers.appdomain.cloud/insurance-quote/quote-backend:v1
     Attempting to apply resource in Kubernetes ...
     Running command: kubectl apply -f app-deploy.yaml --namespace insurance-quote
     Deployment succeeded.
     Appsody Deployment name is: quote-backend
     Running command: kubectl get rt quote-backend -o jsonpath="{.status.url}" --namespace insurance-quote
     Attempting to get resource from Kubernetes ...
     Running command: kubectl get route quote-backend -o jsonpath={.status.ingress[0].host} --namespace insurance-quote
     Deployed project running at quote-backend-insurance-quote.cp4apps-workshop-prop-5290c8c8e5797924dc1ad5d1b85b37c0-0001.us-  east.containers.appdomain.cloud
    

    NOTE: If the deployment times out, see the section Pushing to the OpenShift registry times out in the Admin Guide. NOTE: Running appsody deploy installs the Appsody Operator on the Default namespace of the cluster.

  4. After the deployment completes, you can test the service using curl. The last line output (above) in the deploy gives you the URL to the back-end application. For simplicity, let’s put that in an environment variable.

    So, for the example above, here’s the back-end URL:

     export  BACKEND_URL=quote-backend-insurance-quote.cp4apps-workshop-prop-5290c8c8e5797924dc1ad5d1b85b37c0-0001.us-    east.containers.appdomain.cloud
    

    Test the service using curl, like so:

     curl -X POST -d @backend-input.json  -H "Content-Type: application/json"  http://$BACKEND_URL/quote
    

    You should see output similar to the following:

     $ curl -X POST -d @backend-input.json -H "Content-Type: application/json" http://$BACKEND_URL/quote
     {"quotedAmount":70,"basis":"Dacadoo Health Score API"}
    

    NOTE: If you are not using the Dacadoo Health Score API, you may see different text for the value of “basis” — (“mocked backend computation” instead of “Dacadoo Health Score API”).

  5. Navigating back to the registry dashboard should show the new image.

    The apps backend in the registry

4. Deploy the front-end application to OpenShift

IMPORTANT!: This part of the exercise extends the initial code pattern which shows you how to create the initial code for the front end.

We are now going to deploy the frontend application to OpenShift. The steps are similar to what we did for the back-end application. The difference here is that we need to tell the front-end application how to talk to the back-end application. The front end will look at an environment variable BACKEND_URL to find the address of the back end, so we will set this in the application CR.

  1. You could specify this as the actual exposed back-end URL you used earlier. However since both the front and back end are running within the same cluster, it is better to use the service that is defined for the back end.

You can see this by entering:

```bash
oc get services
```

which should produce something like:

```bash
$ oc get services
NAME             TYPE       CLUSTER-IP       EXTERNAL-IP   PORT(S)          AGE
quote-backend    NodePort   172.21.175.254   <none>        8080:32379/TCP   15m
```
  1. In order to reference this in the application resource, you first need to generate the deployment YAML so that you can edit it. Change the current directory back to the front-end application and generate the deployment YAML.

     cd ../quote-frontend
     appsody deploy --generate-only
    
  2. Edit the file that was created, app-deploy.yaml, and add the env section as shown below (which defines an environment variable with the URL of the back-end application within the cluster). Be careful to match the indentation (env: is indented the same number of spaces as applicationImage:).

     apiVersion: appsody.dev/v1beta1
     kind: AppsodyApplication
     metadata:
       name: quote-frontend
     spec:
       # Add fields here
       version: 1.0.0
       applicationImage: quote-frontend
       env:
       - name: BACKEND_URL
         value: http://quote-backend:8080/quote
       .
       .
       .
    
  3. Save the YAML file and do the deployment.

     appsody deploy --tag insurance-quote/quote-frontend:v1 --push-url $IMAGE_REGISTRY --push --pull-url docker-registry.default.svc:5000 --namespace insurance-quote
    

    You should see output like the following:

     $ appsody deploy --tag insurance-quote/quote-frontend:v1 --push-url $IMAGE_REGISTRY --push --pull-url docker-registry.default.svc:5000 --namespace insurance-quote
     ...
     [Docker] Successfully built ba7451568a04
     [Docker] Successfully tagged docker-registry-default.cp4apps-workshop-prop-5290c8c8e5797924dc1ad5d1b85b37c0-0001.us-    east.containers.appdomain.cloud/insurance-quote/quote-frontend:v1
     Built docker image docker-registry-default.cp4apps-workshop-prop-5290c8c8e5797924dc1ad5d1b85b37c0-0001.us- east.containers.appdomain.cloud/insurance-quote/quote-frontend:v1
     Using applicationImage of: docker-registry-default.cp4apps-workshop-prop-5290c8c8e5797924dc1ad5d1b85b37c0-0001.us-east.containers.appdomain.cloud/insurance-quote/quote-frontend:v1
     Pushing docker image docker-registry-default.cp4apps-workshop-prop-5290c8c8e5797924dc1ad5d1b85b37c0-0001.us-east.containers.appdomain.cloud/insurance-quote/quote-frontend:v1
     Attempting to apply resource in Kubernetes ...
     Running command: kubectl apply -f app-deploy.yaml --namespace insurance-quote
     Deployment succeeded.
     Appsody Deployment name is: quote-frontend
     Running command: kubectl get rt quote-frontend -o jsonpath="{.status.url}" --namespace insurance-quote
     Attempting to get resource from Kubernetes ...
     Running command: kubectl get route quote-frontend -o jsonpath={.status.ingress[0].host} --namespace insurance-quote
     Deployed project running at quote-frontend-insurance-quote.cp4apps-workshop-prop-5290c8c8e5797924dc1ad5d1b85b37c0-0001.us-    east.containers.appdomain.cloud
    
  4. You can then use a browser to open the front-end application at the URL given above (in the example above the URL is quote-frontend-insurance-quote.cp4apps-workshop-prop-5290c8c8e5797924dc1ad5d1b85b37c0-0001.us-east.containers.appdomain.cloud).

  5. Fill in the form and click the button to submit it. You should get a quote from the backend application.

Sample web form

NOTE: If you are not using the Dacadoo Health Score API, you may see different text after the quote You would see “determined using mocked backend computation” instead of “determined using Dacadoo Health Score API”.

Summary

Congratulations! You have now deployed both front and back-end applications to OpenShift, hooked them together, and enabled outreach to an external service.

In general, using Appsody to deploy your application in this fashion is recommended only to enable additional testing within a Docker or Kubernetes environment. As you are probably aware, using such a manual approach inside formal test, staging, and production environments doesn’t solve the problems of maintaining consistency, repeatability, and control.

In later exercises, we show you how to use Appsody and Kabanero to achieve these — using a Tekton pipeline, hooked to a Git repository of the code of the application, ensuring triggering of automated builds and deployments. This is the recommended methodology supported by Kabanero and Cloud Pak for Applications.