Knative — Kubernetes-native PaaS with Serverless

Knative — The Kubernetes PaaS for a Serverless Experience with Gloo API Gateway

Kubernetes has undoubtedly become the dominant platform for deploying containers. Kubernetes provides the ability to orchestrate nearly anything via its core APIs and custom controllers which extend its API via Kubernetes Custom Resources.

However, Kubernetes still leaves control to the user to make detailed decisions about how exactly to deploy, configure, manage, and scale applications. Decisions about how an application is scaled, secured, and exposed to traffic are left to the user to configure. For this reason, Kubernetes is distinct from a traditional Platform-as-a-Service such as Cloud Foundry and Heroku.

PaaSes target application developers, with a simplified user experience, concerned primarily with the configuration of individual applications. Routing, deployment, and telemetry are managed by the PaaS backend transparently to the user.

The PaaS handles source-to-deployment workflow, building the user’s container image, rolling out a new deployment, and configuring a new route and DNS subdomain to allow traffic to reach the deployed containers. All this triggered by a git push.

Kubernetes has (intentionally) provided only the building blocks for such platforms, leaving to its community the job of closing the gap. As Kelsey Hightower put it:

In response, we have seen an explosion in Kubernetes distros and hosted solutions which attempt to PaaS to Kubernetes such as OpenShift and Rancher. With the growing contention for Kube-PaaS market share, Google and Pivotal have stepped into the ring with Knative, announced in July 2018.

Built in collaboration by Google and Pivotal, with smaller contributions by companies including IBM, Red Hat, and Solo.io, Knative offers a PaaS-like experience for Kubernetes with first-class support for Serverless applications. Unlike Kubernetes distros, Knative can be installed to any compatible Kubernetes cluster as an add-on and configured via custom resources.

Knative is self-described as “Kubernetes-based platform to deploy and manage modern serverless workloads”. Billing itself as a platform for “serverless workloads”, Knative actively autoscales containers in proportion to concurrent HTTP requests. Services that are not in use are eventually scaled to zero, providing “serverless”-style scale-on-demand.

Knative is composed of a set of controllers which can be installed to any Kubernetes cluster that provide the features of:

  • Building containerized applications from source code (provided by the Build component of Knative)
  • Exposing applications to external traffic (provided by the Serving component)
  • Deploying & autoscaling applications based on demand (provided by the Serving component)
  • Defining event sources which can trigger application execution (provided by the Eventing component)

Serving is the core project, managing the deployment, autoscaling, and traffic routing for managed applications. The full Kubernetes API is still accessible after Knative is installed, allowing users to manage applications in the “traditional” manner, as well as to debug their Knative services by working with the same API primitives they’re used to (pods, services, etc.).

Serving also automates blue-green routing of traffic when users push updated versions of their applications, splitting traffic between the new and old versions of the application.

Knative itself depends on a compatible ingress controller being installed. At the time of writing, the Gloo API Gateway and the Istio Service Mesh are the only compatible ingress controllers available. Knative will configure the available ingress to route traffic to Knative-managed apps.

Because Knative only depends on a gateway, the Istio service mesh can be a larger dependency for users who wish to use Knative without having to also install and manage the Istio control plane.

For this reason, many users are choosing Gloo as their Knative gateway, providing feature parity with Istio (for the purposes of Knative) with a significantly reduced resource footprint and operational overhead.

Let’s see Knative in action with a quick demo. I’ll be using a fresh cluster running on GKE:

kubectl get namespace NAME          STATUS   AGE
default       Active   21h
kube-public   Active   21h
kube-system   Active   21h

Start by deploying Knative and Gloo. This can be done in any order:

# deploy Knative-Serving
 kubectl apply -f \
 https://github.com/knative/serving/releases/download/v0.8.0/serving-core.yaml
 namespace/knative-serving created
# deploy Gloo
  kubectl apply -f \
  https://github.com/solo-io/gloo/releases/download/v0.18.22/gloo-knative.yaml
  namespace/gloo-system created

Verify that all pods are Running:

kubectl get pod -n knative-serving
NAME                              READY   STATUS    RESTARTS   AGE
activator-5dd55958cc-fkp7r        1/1     Running   0          7m32s
autoscaler-fd66459b7-7d5s2        1/1     Running   0          7m31s
autoscaler-hpa-85b5667df4-mdjch   1/1     Running   0          7m32s
controller-85c8bb7ffd-nj9cs       1/1     Running   0          7m29s
webhook-5bd79b5c8b-7czrm          1/1     Running   0          7m29s
kubectl get pod -n gloo-system
NAME                                      READY   STATUS    RESTARTS   AGE
discovery-69548c8475-fvh7q                1/1     Running   0          44s
gloo-5b6954d7c7-7rfk9                     1/1     Running   0          45s
ingress-6c46cdf6f6-jwj7m                  1/1     Running   0          44s
knative-external-proxy-7dd7665869-x9xkg   1/1     Running   0          44s
knative-internal-proxy-7775476875-9xvdg   1/1     Running   0          44s

Gloo is now ready to start routing. Let’s create an autoscaling Knative Service (kservice) and route some traffic to it.

Knative Services provide an easier way to deploy apps to Kubernetes than the traditional Deployment+Service+Ingress model. We’ll work with the following example:

apiVersion: serving.knative.dev/v1alpha1
kind: Service
metadata:
 name: helloworld-go
 namespace: default
spec:
 template:
   spec:
     containers:
       - image: gcr.io/knative-samples/helloworld-go
         env:
           - name: TARGET
             Value: Knative user

I’ll paste this to a file and then deploy it to my Kubernetes cluster like so:

kubectl apply -f ksvc.yaml -n default

We can see what resources Knative created in our cluster after deploying our `helloworld-go` KService:

kubectl get pod -n default
NAME                                              READY   STATUS    RESTARTS   AGE
helloworld-go-fjp75-deployment-678b965ccb-sfpn8   2/2     Running   0          68s

A pod with our helloworld-go image gets cold-started on deployment of the kservice. Eventually the deployment backing this will be scaled down to zero if no traffic is reaching our pod. Conversely, pod instances will be scaled up if concurrent requests surpass a configurable threshold.

kubectl get ingresses.networking.internal.knative.dev -n default
NAME            READY   REASON
helloworld-go   True

Knative configures its ingress using a special `ingress` resource in the internal Knative API. Gloo consumes this API as its own configuration in order to provide PaaS-like features including blue-green deployments, automatic TLS termination, timeouts, and other advanced routing features.

After a period of time, we’ll see our pods go away (unless we hit them with traffic):

kubectl get pod -n default                                                           
No resources found.
kubectl get deployment -n default
NAME                             DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
helloworld-go-fjp75-deployment   0         0         0            0           9m46s

Finally, we can hit them with some traffic. Getting the URL of the Knative Proxy is particularly easy with `glooctl`:

glooctl proxy url --name knative-external-proxy
http://35.190.151.188:80

Without `glooctl` installed, we can look up the address/port from the kube service:

kubectl get svc -n gloo-system knative-external-proxy
NAME                     TYPE           CLUSTER-IP     EXTERNAL-IP      PORT(S)                      AGE
knative-external-proxy   LoadBalancer   10.16.11.157   35.190.151.188   80:32168/TCP,443:30729/TCP   77m

Send some traffic with cURL:

curl -H "Host: helloworld-go.default.example.com"
http://35.190.151.188
Hello Knative user!

Using Gloo as a high-performance, fully-featured API Gateway, Knative provides a PaaS-like experience for developers on top of out-of-the-box Kubernetes. This article only scratches the surface of what’s possible with Knative; much more is available with respect to customization and additional features. It also only scratches the surface of what’s possible with Gloo!

While Knative is still young, the Knative team has hit a six-week release cadence and more advanced features have begun to emerge from the pipeline such as automatic TLS provisioning and control plane autoscaling. As a collaboration between multiple heavy-hitter cloud companies and the backbone of Google’s new Cloud Run offering, Knative will almost certainly become one of the preeminent choices for bringing serverless and PaaS to Kubernetes. So stay tuned!

To learn more: