How to use Knative to deploy a Serverless Application on Kubernetes

By Robert Neumann

Photo by Pixabay from Pexels

Container or Serverless? A question that will soon be superfluous with Knative. The open source project Knative was developed by Google together with Pivotal, IBM, Red Hat and SAP and offers middleware components for serverless container applications based on Kubernetes and Istio. This allows developers to focus more on writing code. Based on the story “Deploy a Kubernetes Cluster on OpenStack using Kubespray” we install Knative and show how to use it.

Knative is an open source framework that provides a collection of components that extend Kubernetes. Currently, Knative offers three components: Serving, Build, and Eventing.

The best descriptions of the components are given by Pivotal on their website.

Serving is a scale-to-zero, request-driven compute runtime which leverages Istio to route traffic amongst revisions. The goal of Serving is to provide Kubernetes extensions for deploying and running serverless workloads.¹
Build provides a pluggable model for building containers from source code. It’s based on Google’s container builder service. Buildpacks are one style of builds that could be plugged into this model.¹
Eventing provides building blocks for consuming and producing events that adhere to the CloudEvents specification. It includes abstractions for feeds from event sources, and decoupled delivery through messaging channels backed by pluggable pub/sub broker services.¹

Knative is developed for different target groups the following diagram gives an overview:

Diagram by Knative
Knative components offer developers Kubernetes-native APIs for deploying serverless-style functions, applications, and containers to an auto-scaling runtime.²
Knative components are intended to be integrated into more polished products that cloud service providers or in-house teams in large enterprises can then operate. Any enterprise or cloud provider can adopt Knative components into their own systems and pass the benefits along to their customers.²
With a clear project scope, lightweight governance model, and clean lines of separation between pluggable components, the Knative project establishes an efficient contributor workflow.²

The use of cloud platforms is diverse and offers companies far-reaching opportunities. But it can lead to a situation in which the operation of the cloud burdens the developers as well as the operation. This leads to complex microservice architectures to ensure portability, with the operation having to administer extensive hybrid and multi-cloud implementation. In this situation Istio helps to control, secure, connect and monitor services. For more information about Istio, I recommend the Istio-documentation

After a short introduction we can start to install Knative on our Kubernetes Cluster, that we deployed in my last Kubernetes story. The installation is based on the Knative documentation.

First, we need to install Istio. This will be done by the following commands. It will take some seconds to get all services in the running state.

Next, we need to label the default namespace with istio-injection=enabled. This activates Istio on the “default” Kubernetes namespace and injects automatically an Istio proxy sidecar container to all pods deployed to the this namespace.

To check whether all Istio components are in Running status, execute the following command.

It will take a few minutes until all components are started.

At this stage our Istio service mesh is running and we are ready to install Knative. The following command must be executed without any error.

We can monitor the component installation with the following commands. All these must indicate the status running before continuing.

If everything looks good we are ready to deploy our first app with Knative.

After the installation of Istio and Knative we can start to deploy a serverless application. In this case we will deploy a go hello-world example by use of the serving component.

For our example we will use the “default” namespace in the Kubernetes cluster. If you like to use another namespace you can create one by the following command and edit the metadata in the example file below.

We need to create yaml-file for our application with the following content.

Content source Knative

With the created namespace and the yaml-file we are ready to deploy our app by the use of kubectl apply.

Our service is ready to interact we need to find the public IP-address of the gateway. We use the kubectl get service command in our case we don’t have an external load balancer we will use NodePorts.

It is recommended to set an environment variable “IP-ADDRESS”.

And we need the host URL of our service:

With all the collected information we are ready to interact with our service by the us of the curl. Output should like the line below.

Our service is available and we can interact with it. The next step is to change the version of our application. We have to edit the yaml-file like the following.

Content source Knative

After the applying the service again. The configuration of it will change. We will see another revision of our service.

The curl command will also show the new revision v.2 as response.

To demonstrate the scale-to-zero feature we do not send requests to our service. We will see that the pods will disappear.

When we send requests again it will take a few seconds until we get a response because the pods have to be started again.

The Serving component provides four resources Service, Route, Configuration and Revision. These are defines as a set of objects as Kubernetes Custom Resource Definitions (CRDs) and used to define and control the behaviour you serverless workflow on the cluster.

  • Service: The service.serving.knative.dev resource automatically manages the whole lifecycle of your workload. It controls the creation of other objects to ensure that your app has a route, a configuration, and a new revision for each update of the service. Service can be defined to always route traffic to the latest revision or to a pinned revision.⁵
  • Route: The route.serving.knative.dev resource maps a network endpoint to a one or more revisions. You can manage the traffic in several ways, including fractional traffic and named routes.⁵
  • Configuration: The configuration.serving.knative.dev resource maintains the desired state for your deployment. It provides a clean separation between code and configuration and follows the Twelve-Factor App methodology. Modifying a configuration creates a new revision.⁵
  • Revision: The revision.serving.knative.dev resource is a point-in-time snapshot of the code and configuration for each modification made to the workload. Revisions are immutable objects and can be retained for as long as useful.⁵

The following diagram shows how these interact with each other.

Diagram by Knative

This tutorial can be adapted for any other application to deploy it with Knative on a Kubernet cluster. The Knative documentation offers also different samples for many other programming languages. Further topics will be Knative Eventing- and Build-component and will be covered in future stories.

[1]: Pivotal. Knative: https://pivotal.io/de/knative

[2]: Knative. Knative: https://www.knative.dev/docs/

[3]: Istio. What is Istio: https://istio.io/docs/concepts/what-is-istio/

[4]: Google. Using Knative to deploy serverless applications to Kubernetes: https://codelabs.developers.google.com/codelabs/knative-intro/index.html#0

[5]: Knative. Knative Serving: https://www.knative.dev/docs/serving/