Run OpenWhisk actions on managed Knative on a Kubernetes cluster

The OpenWhisk community began prototyping OpenWhisk runtime environments, specifically Node.js, so OpenWhisk actions can be deployed and run on Knative. You can read more about running OpenWhisk actions with Docker for Desktop and Minikube on my blog post.

In addition, Doug Davis announced managed Knative on the IBM Cloud Kubernetes service in early 2019. He explains how to enable the managed Knative add-on in your Kubernetes cluster.

This tutorial shows how to experiment with the IBM Cloud Kubernetes Service to see how it differs from other environments.

Learning objectives

Understand how to run OpenWhisk actions on managed Knative on a Kubernetes cluster. Experiment with examples using the IBM Cloud Kubernetes Service.

Estimated time

This tutorial takes about 10-15 minutes after installing and configuring the prerequisites.


  • Create a standard Kubernetes cluster with version 1.12.7 of IBM Cloud Kubernetes Service in Single Zone/Multi Zone with a flavor of 4 cores, 16 GB RAM, and 3 worker nodes. (Feel free to grab some lunch while the standard cluster is created!)

  • Configure IBM Cloud CLI. To download the kubeconfig files for your cluster using the following command:

     ibmcloud ks cluster-config <cluster-name>
  • Configure kubectl to access the cluster on IBM Cloud Kubernetes Service.

    You can verify with the following command:

     kubectl cluster-info
  • Enable the Knative add-on:

     ibmcloud ks cluster-addon-enable knative <cluster-name>

    (Now is a good time to grab some coffee!)

  • Verify that all pods are Running under istio-system, knative-build, knative-serving, knative-eventing, and knative-monitoring.

      kubectl get pods --all-namespaces
      NAMESPACE            NAME                                            READY   STATUS              RESTARTS   AGE
      istio-system         cluster-local-gateway-6d8585d55d-jmmwn          1/1     Running             0          79s
      knative-build        build-controller-865d99747c-lj9sh               1/1     Running             0          109s
      knative-eventing     eventing-controller-64bf9bbf79-ccq5p            2/2     Running             0          79s
      knative-monitoring   elasticsearch-logging-0                         1/1     Running             0          108s
      knative-serving      activator-58fb6bdff4-5tsjh                      0/2     PodInitializing     0          78s
      knative-sources      controller-manager-0                            1/1     Running             0          106s


Complete the following six steps to build and serve OpenWhisk actions on Knative:

Architecture flow diagram for building and serving an OpenWhisk runtime environment on Knative

Step 1. Register secrets for your container registry on Knative

Knative needs access to your container registry in order to push locally built container image. The examples here use Docker Hub, but you can use any registry of your choice by changing the registry name under annotation.

Save this file as docker-secret.yaml after replacing DOCKERHUB_USERNAME_BASE64_ENCODED and DOCKERHUB_PASSWORD_BASE64_ENCODED with your Docker Hub user name and password:

apiVersion: v1
kind: Secret
    name: dockerhub-user-pass
    # use `echo -n "username" | base64 -b 0` to generate this value
    # use `echo -n "password" | base64 -b 0` to generate this value

Apply the secret resource manifest for Docker Hub:

 $ kubectl apply -f docker-secret.yaml
secret/dockerhub-user-pass created

Verify that the secret exists:

$ kubectl get secret dockerhub-user-pass
NAME                    TYPE                                  DATA      AGE
dockerhub-user-pass              2       21s

Step 2: Create Service Account for our Knative Builds

Create a service account to link the build process with the registry secret that you created in step 1 so that the Knative build system can push container images to the registry using these credentials.

apiVersion: v1
kind: ServiceAccount
    name: openwhisk-runtime-builder
    - name: dockerhub-user-pass
$ kubectl apply -f service-account.yaml
serviceaccount/openwhisk-runtime-builder created

Verify the service account exists:

$ kubectl get serviceaccount/openwhisk-runtime-builder
NAME                        SECRETS   AGE
openwhisk-runtime-builder   2         3m46s

Step 3: Install the build template for the Node.js runtime environment

Deploy the OpenWhisk build template:

$ kubectl apply -f created

Verify that the build template exists:

$ kubectl get buildtemplate openwhisk-nodejs-runtime
NAME                       AGE
openwhisk-nodejs-runtime   2m

Step 4: Deploy the Node.js runtime environment with the Hello World action code

Configure the build file to point to your Docker Hub repo by replacing DOCKER_USERNAME with your user name:

kind: Build
  name: nodejs-10-helloworld-with-params
  serviceAccountName: openwhisk-runtime-builder
      url: ""
      revision: "master"
    name: openwhisk-nodejs-runtime
      - name: TARGET_IMAGE_NAME
        value: "${DOCKER_USERNAME}/nodejs-10-helloworld-with-params"
      - name: DOCKERFILE
        value: "./core/nodejs10Action/knative/Dockerfile"
      - name: OW_ACTION_NAME
        value: "nodejs-helloworld-with-params"
      - name: OW_ACTION_CODE
        value: "function main(params) { return { payload: 'Hello ' + + ' from ' + +  '!' }; }"

Deploy the Node.js runtime environment with the following action code:

$ kubectl apply -f build.yaml created

Verify that the build pod exists:

$ kubectl get
nodejs-10-helloworld-with-params   True                 8m

Step 5: Serve the Node.js runtime environment as a Knative service

Now that you built the OpenWhisk Node.js runtime image with the helloworld function included in it, you can deploy that image as a Knative service.

Configure the service template to point to the Docker Hub repo where the OpenWhisk runtime environment (that you built in step 4) is pulled from. Replace ${DOCKER_USERNAME} and create service.yaml:

kind: Service
  name: nodejs-helloworld-with-params
  namespace: default

Deploy the runtime environment:

 $ kubectl apply -f service.yaml created

Step 6: Run the Hello World action

This step differs in the way you run the Knative service on IBM Kubernetes or Docker for Desktop or Minikube using the JSON payload:

  "activation": {
    "namespace": "default",
    "action_name": "nodejs-helloworld-with-params",
    "api_host": "",
    "api_key": "",
    "activation_id": "",
    "deadline": "4102498800000"
  "value": {
    "name" : "Jill",
    "place" : "OK"
kubectl get ksvc nodejs-helloworld-with-params
NAME                            DOMAIN                                                                                  LATESTCREATED                         LATESTREADY                           READY   REASON
nodejs-helloworld-with-params   nodejs-helloworld-with-params.default.<cluster-name>.<region>   nodejs-helloworld-with-params-f2w4p   nodejs-helloworld-with-params-f2w4p   True
curl nodejs-helloworld-with-params.default.<cluster-name>.<region> -H "Content-Type: application/json" -d '@params.json'
{"payload":"Hello Jill from OK!"}

Hooray! You have your hello world action running on Knative on IBM Cloud Kubernetes Service.


This example can help you understand how to run OpenWhisk actions on managed Knative on a Kubernetes cluster. I hit a memory limitation when I installed Knative on a free IBM Cloud Kubernetes cluster. In a production environment, you might need to plan for more memory.

Try it out for yourself at IBM Cloud Kubernetes Service.