Get Started with Serverless Computing on Kubernetes with Minikube and Kubeless

Introduction

Typically, you write code in your development environment and then create a deployment environment to run it. Even for running a very small amount of code in the cloud, you need to go through the hassle of creating a virtual machine or container, deploying it to the cloud, and maintaining it there.

The idea behind serverless computing is that it lets you, as a developer, focus only on writing your code. With serverless computing, you just upload the code somewhere, and it runs whenever you invoke it. Simply put, serverless computing frees you from the complexities of creating Docker containers or configuring and maintaining Kubernetes clusters.

This guide will show you how to get started with serverless computing using Bitnami’s Kubeless platform, running on top of a Kubernetes cluster in Minikube or Google Container Engine.

Overview

To get started with serverless computing, you only need three ingredients:

This tutorial assumes that you already have a Kubernetes cluster on either Minikube or GKE with kubectl installed. For detailed instructions to accomplish these tasks, refer to our Kubernetes starter tutorial.

Once you have verified that your Kubernetes cluster is running, you will need to perform the following steps:

Start the Kubernetes Dashboard on port 8080

Install Kubeless

Write a function

Register the function with Kubeless

Call the function

Step 1: Start the Kubernetes Dashboard on port 8080

Once your Kubernetes cluster is running, make the Kubernetes Dashboard available on port 8080 with the command below.

$ kubectl proxy --port=8080

NOTE: Execute the above command in a separate window or shell, so that the Kubernetes Dashboard remains running while you work through the remaining steps of this guide.

Point your browser to http://localhost:8080/ui and you should see something like this:

Once you can access the Kubernetes Dashboard on port 8080, proceed to install Kubeless.

Step 2: Install the Kubeless CLI tool

Kubeless is an application designed to be deployed on top of a Kubernetes cluster. It accepts commands to register, delete, and list functions that you would like to run. Once Kubeless is running, all of the hassles of setting up containers and pods, disappear.

Step 3: Deploy Kubeless in your Kubernetes cluster

You should deploy Kubeless in your cluster using one of YAML manifests found in the release package. It will create a kubeless Namespace and a function ThirdPartyResource. You will see a kubeless Controller, and kafka, zookeeper StatefulSet running.

There are several kubeless manifests being shipped for multiple k8s environments (non-rbac and rbac), please consider to pick up the correct one:

kubeless-$RELEASE.yaml is used for non-RBAC Kubernetes cluster.

kubeless-rbac-$RELEASE.yaml is used for RBAC-enabled Kubernetes cluster.

For example, this below is a show case of deploying kubeless to a non-RBAC Kubernetes cluster.

NOTE: This function is deliberately written without any error handling or input validation for ease of understanding. You should not use this function as is in a production environment.

This is a simple and potentially useful function. Its purpose is simply to search through the list of Capital City Bikeshare stations and return a list of matches. To add this function to an existing application, you would typically integrate it with an existing code base, create new VMs or containers, and do a canary deploy of the result. However, with serverless computing, you can also just register the function and then reach it over the Web whenever needed.

Notice that this find() function has a required parameter named request. When Kubeless calls the function, it will pass in a LocalRequest object from the Bottle Web Framework. The LocalRequest object has a handy property called json which returns all of the POST request parameters as a JSON object. By parsing the JSON, it’s easy to extract the search term from the posted data.

For this example, save the code in a file at /tmp/city-bikes.py and head to the next step.

Step 5: Register the function with Kubeless

The next step is to register the function with Kubeless. Registering the function with Kubeless involves telling Kubeless these bits of information:

The name you will use to access the function over the Web

The protocol you will access the function (here, HTTP)

The runtime to be executed to run the code (here, Python)

The name of the file containing the function code

The name of the function inside the file

All of this seems like quite a mouthful, but it’s all easily done using a reasonably simple command called kubeless function deploy. Here it is:

kubeless function deploy bikesearch tells Kubeless to register a new function named bikesearch. The function will be accessible over the Web using this name. Note that this doesn’t need to be the same as the function name used inside the code (we’ll specify that a little further along using the --handler option).

--trigger-http tells Kubeless that the function will be invoked over HTTP. It’s also possible to trigger the function in other ways, but that is not covered here.

--runtime python2.7 tells Kubeless to use Python 2.7 to execute the code. Node is also supported as a runtime, with more to come in future.

--handler city-bikes.find tells Kubeless the name of the function to call inside the code module. You can see in the Python code above that the function is called find().

--from-file /tmp/city-bikes.py tells Kubeless to upload and use the /tmp/city-bikes.py file as the source for the function. It is possible to pass a function in other ways as well.

Once the command has completed executing, check that it’s registered with Kubeless using the kubeless function ls command, as shown below:

$ kubeless function ls

You should see the function registered with Kubeless, as shown in the image below:

To delete a function, simply use the kubeless function delete command:

$ kubeless function delete bikesearch

Step 6: Call the function

Take a quick look back at the function code. You’ll see that the function expects to be called by a form POST, and that it will use the value of the input parameter term as the search key. So, to search for a location on Albemarle Avenue, the easiest way is to use curl and send in a POST request like the one below:

And the function returns a JSON payload of matches. Here’s what it looks like:

You can obviously refine this (or create a new function) to do something else instead - for example, return HTML with a map showing the locations.

Debugging Kubeless functions

What happens when something goes wrong? The function currently has no error handling, so that’s easy enough to test. Try sending the request again, but this time with a typo (use trm as the name of the input parameter instead of term):

Kubeless returned an error message with a 500 server code, which is what you would expect from a web framework. However, it would be useful to see Python stack trace to better debug the source of the error. To achieve this, first find the container where the function is running using kubectl:

It should be clear from the second-to-last line that the error originates in an incorrect key name.

This is a very basic example of debugging a Kubeless function, but it should hopefully highlight the basic principles. Obviously, in production environments, you would want to have more formal and sophisticated error handling built into your code.