Deploy a Watson Discovery application with New Relic observability on IBM Cloud Kubernetes Service

This tutorial is part of the 2021 Call for Code Global Challenge.

In this tutorial, learn how to deploy a simple app that serves a Single Page Application (SPA) and communicates with IBM Watson Discovery on Kubernetes. The SPA is served by a Node.js back end running Fastify. The back end then makes queries to Watson Discovery and returns the results. Finally, you’ll set up your cluster for Full-Stack Observability with New Relic to easily ensure that everything is running correctly in your cluster. You’ll also analyze some metrics and logging.


To complete this tutorial, you need:

  1. An IBM Cloud account. (You must upgrade to create a free Kubernetes cluster.)
  2. Docker.
  3. IBM Cloud CLI.
  4. Kubectl.
  5. Access to the application.

Set up

Before beginning the tutorial, you must:

  1. Install the following IBM Cloud CLI plug-ins:

     ibmcloud plugin install kubernetes-service
     ibmcloud plugin install container-registry
  2. Create a free 1 worker IBM Kubernetes Service cluster.

  3. Create a free Watson Discovery instance.

Estimated time

It should take you approximately 30 minutes to complete this tutorial.


This step-by-step guide assumes Linux/UNIX-like shell usage. Slight adaptations might be necessary for different CLI shells.

Logging in and connecting to the Kubernetes cluster

  1. Log in to IBM Cloud.

     ibmcloud login
  2. Log in to IBM Container Registry.

     ibmcloud cr login
  3. Add a namespace for your project at the IBM Container Registry.

     export ICR_NAMESPACE=<your_namespace>
     ibmcloud cr namespace-add $ICR_NAMESPACE
  4. Build a Docker image for the app, tag it, and push it to IBM Container Registry under your namespace.

     docker build -t $APP_IMAGENAME .
     docker push $APP_IMAGENAME

    Building the image should take a few minutes.

  5. Connect to your IBM Kubernetes Service cluster.

     ibmcloud ks cluster config --cluster <your_cluster_name>

    The cluster name is the one you chose when creating it. If you forgot, you can check for it under Clusters in the IBM Cloud resource list.

Sending requests to Watson Discovery

For the back end to send requests to Watson Discovery, it needs the Discovery instance credentials, which are defined by two environment variables. Here, you’ll create the credentials as a Kubernetes secret, then inject them in the app by configuring environment variables in the deployment yaml file. You can find your APIKEY and URL for Watson Discovery by going to your IBM Cloud resource list, and clicking your Watson Discovery instance under Services. Store them in the environment variables as follows, and create the secret.

export DISCOVERY_APIKEY=<discovery_apikey>
export DISCOVERY_URL=<discovery_url>

kubectl create secret generic discovery-credentials --from-literal=api-key=$DISCOVERY_APIKEY --from-literal=url=$DISCOVERY_URL

Deploying the build to Kubernetes

Next, you’ll deploy your built image to Kubernetes.

  1. Update the deployment.yaml file to match your image name. You should update line 24’s image value. Note that updating just the namespace is fine.

    Important note: Your pod will not find any images if you do not change the image name.

  2. Deploy the build.

     kubectl apply -f server/deployment.yaml

    The deployment.yaml file can be generated with the following command.

     kubectl create deployment <deployment_name> --image=<image_name> --port <port> --dry-run=client -o yaml > deployment.yaml

    The yaml file used here is additionally configured to use the secret as environment variables.

Running the app

The app should now be running. You can confirm this by using kubectl get pods. If there are any errors, you can check the logs with kubectl logs <pod_id>. The next step is to expose the app publicly so that you can access it.

kubectl expose deploy discovery-demo-app --type=NodePort

A Node Port is created, and it forwards the pod’s exposed port to the node’s public interface. Now the app is ready to be publicly accessed. To do that, get the cluster worker node’s public IP address and access the port forwarded by the Node Port.

  1. Run the following command.

     kubectl get svc

    You should see the discovery-demo-app NodePort as well as some columns of information. With a free cluster, you won’t have an external IP address for your service, but you can access the service through the worker node’s public IP address. You can find the TCP port forwarded by the Node Port in the previous command’s output. It should look similar to 8080:<port>/TCP, with a port in the range 30000 - 32767.

    Record the port because you’ll use it to access the app.

  2. Get your worker node’s public IP address by running the following command.

     ibmcloud ks worker ls -c <your_cluster_name> # Cluster name is the same as in step 5.

    This command outputs the ID of the worker in your cluster together with its public and private IP addresses. Copy the public IP address because you’ll use it next.

  3. Access the app directly from your browser using http://<worker_ip>:<node_port>. Try out a few queries for Watson Discovery news.


Setting up Observability

Let’s set up Observability with New Relic. To do that:

  1. Register for a free New Relic account.

  2. Log in to your New Relic account and follow the guided installation for Kubernetes. During the guided installation, you must:

    1. Give your cluster a meaningful name.
    2. Accept all set-up options.
    3. Choose Manifest.
    4. Download the manifest file.
    5. Apply the manifest file with kubectl apply -f <PATH_TO_DOWNLOADED_FILE> -n default.

      Before going into the Kubernetes Cluster Explorer, you’ll want to set up detailed application monitoring. To do that, you must update the server/deployment.yaml file and uncomment the NEW_RELIC_LICENSE_KEY and NEW_RELIC_APP_NAME environment variable definitions.

  3. Redeploy the app.

     kubectl apply -f server/deployment.yaml

    The Node.js app is already instrumented with New Relic:

    • The New Relic library was imported with a require('newrelic'); in the main module (src/index.ts).
    • The package.json file includes newrelic as a dependency.
  4. Navigate to the New Relic Kubernetes Cluster Explorer and look at what’s happening in your cluster.

    If you filter by the discovery-demo-app deployment, you can see the status of the running pod. Click the pod to see its status.

    New Relic Dashboard

    You can also see the response times for your service. Do that by navigating to Explorer > APM and searching for discovery-demo.

    Service response time

Much more can be done within New Relic One. If you want to learn more about the Kubernetes Cluster Explorer, watch this video.


In this tutorial, you learned how to deploy a publicly accessible application that’s built with Watson Discovery functions on Kubernetes. You can use this application to ask complex queries. For information about language support, see Discovery language support.