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
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.
What is Knative?
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 namespaceNAME 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 \
# ...# deploy Gloo
kubectl apply -f \
Verify that all pods are Running:
kubectl get pod -n knative-servingNAME 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 7m29skubectl get pod -n gloo-systemNAME 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:
- image: gcr.io/knative-samples/helloworld-go
- 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 defaultNAME 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 defaultNAME READY REASON
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 defaultNAME 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-proxyhttp://18.104.22.168:80
Without `glooctl` installed, we can look up the address/port from the kube service:
kubectl get svc -n gloo-system knative-external-proxyNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
knative-external-proxy LoadBalancer 10.16.11.157 22.214.171.124 80:32168/TCP,443:30729/TCP 77m
Send some traffic with cURL:
curl -H "Host: helloworld-go.default.example.com" http://126.96.36.199Hello 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: