Skip to main content
knative_vculer.webp

Building Serverless Functions on Kubernetes using Knative

Vishal Anarase

Vishal Anarase


Introduction

The evolution of cloud computing has taken us from bare metal to virtual machines, to containers, and now serverless. As organizations adopt Kubernetes for container orchestration, there's growing interest in combining it with Function-as-a-Service (FaaS) to maximize developer productivity and operational efficiency. But can Kubernetes truly be serverless? With Knative, the answer is yes.

Knative is a Kubernetes-based platform designed to build, deploy, and manage modern serverless workloads with ease. It brings serverless capabilities like scale-to-zero, on-demand scaling, and advanced traffic routing directly to Kubernetes, enabling teams to run event-driven, stateless applications seamlessly on their clusters.

In this blog post, we'll explore how Knative brings serverless capabilities to Kubernetes, how it compares to other FaaS platforms, and how to build and deploy your first serverless function on Kubernetes.

What is Function-as-a-Service (FaaS)

FaaS is a cloud computing model where developers write functions that are executed in response to events. Unlike traditional applications, FaaS abstracts infrastructure management, letting you focus purely on code. The serverless architecture became popular with one of the most popular services in AWS, i.e., Lambda. With the evolution of microservices and event-driven architectures, it made sense to reduce the size of execution code and package it in a small unit of compute. Moreover, with the advancements of cloud and Kubernetes, the autoscaling combined with serverless architectures makes the whole piece cost-effective.

Key Characteristics

  • Code runs in ephemeral containers
  • Event-driven execution
  • Automatic scaling (including to zero)
  • Pay-per-use model in public clouds

How FaaS differs from traditional microservices

FeatureFaaSTraditional Microservices
ScalingAuto-scales (including to 0)Manual or HPA-based scaling
RuntimeShort-lived, statelessLong-running, stateful possible
DeploymentEvent-triggeredAlways-on

FaaS is ideal for short-lived tasks like image processing, webhook handlers, or scheduled jobs, whereas microservices handle long-lived business processes.

Why Kubernetes needs a serverless layer

While Kubernetes is an incredibly powerful and flexible orchestration platform, it was not originally designed with Function-as-a-Service (FaaS) or serverless workloads in mind. By default, Kubernetes requires users to define deployments, manage YAML manifests, and configure scaling policies. All of which can slow down development and add operational overhead. Introducing a serverless layer on top of Kubernetes addresses these gaps and unlocks new capabilities that make it even more appealing for modern, cloud-native applications.

  • One major benefit is developer velocity. Serverless abstracts away much of the boilerplate YAML, deployment configurations, and infrastructure management that come with Kubernetes.
  • Another key advantage is cost efficiency. Traditional Kubernetes clusters often keep resources allocated even when they are idle, leading to unnecessary costs. A serverless layer enables scale-to-zero, where workloads can scale down completely when not in use, freeing up cluster resources and reducing cloud bills significantly.
  • Finally, Kubernetes with a serverless layer aligns well with event-driven architecture (EDA). Serverless encourages building loosely coupled, decoupled systems that react to events, such as HTTP requests, messages from queues, or cloud events. This design pattern makes applications more resilient, modular, and easier to evolve.
  • This combination of Kubernetes and serverless fits particularly well in architectures where microservices and event-driven patterns dominate. Use cases like APIs that experience sporadic traffic, background job processing, IoT event streams, and real-time data pipelines all benefit from the elastic, on-demand nature of serverless. It's especially suited for cloud-native organizations adopting distributed, decoupled architectures that demand both flexibility and efficiency.

Challenges of FaaS on Kubernetes

Cold Starts

One of the key challenges of running Function-as-a-Service (FaaS) on Kubernetes is dealing with cold starts. In a serverless environment, the platform often scales your application to zero when idle. When a new request arrives, Kubernetes has to spin up a pod from scratch, introducing noticeable latency before the function becomes ready to serve traffic. This delay, known as a cold start, can significantly impact user experience for latency-sensitive applications.

Autoscaling

Traditional Kubernetes autoscaling, such as the Horizontal Pod Autoscaler (HPA), isn't designed to handle the dynamic nature of FaaS workloads. HPA relies on metrics like CPU or memory utilization, and it struggles with scaling down to zero or reacting quickly to sudden burst traffic. To address this, Knative introduced its own Knative Pod Autoscaler (KPA), which scales based on request volume and supports scale-to-zero, making it better suited for serverless patterns.

Traffic Routing

Routing traffic effectively during updates or deployments is another challenge. FaaS often requires advanced traffic management to enable strategies like blue/green deployments, canary rollouts, or gradual traffic shifting between versions. Native Kubernetes services and ingresses are limited in this regard, so additional components and configurations are necessary to achieve the smooth traffic control expected in serverless environments.

Stateful vs Stateless Concerns

Serverless platforms like Knative are primarily designed for stateless functions, where each invocation is independent of previous ones. However, many real-world applications require maintaining state across requests. To support such scenarios, developers need to implement external state management or use patterns like event-driven workflows, for example, with Knative Eventing.

Operational Overhead

Finally, adopting FaaS on Kubernetes introduces operational complexity. Running and maintaining the necessary components, such as Istio or Kourier for networking, along with monitoring and scaling logic, increases the operational burden on platform teams. While serverless abstracts away much of the infrastructure from the developer's perspective, it still requires careful configuration and observability to ensure reliable and efficient operation at scale.

Enter Knative - Serverless Kubernetes

Core components of Knative

knative components
Knative components Image source: Knative.dev

Serving

Knative Serving is the part of Knative that turns your Kubernetes cluster into a serverless platform for stateless HTTP apps, using Kubernetes CRDs to control the lifecycle and behavior of your workloads.

serving

The primary Knative Serving resources are Services, Routes, Configurations, and Revisions.

  • Services

The Service resource (service.serving.knative.dev) manages the full lifecycle of your serverless app, coordinating Routes, Configurations, and Revisions behind the scenes. It ensures your app always has a route and creates a new revision with every update. You can direct traffic to the latest revision or pin it to a specific one for controlled rollouts.

  • Routes

The Route resource (route.serving.knative.dev) defines how traffic is directed to one or more revisions. It enables strategies like canary deployments, A/B testing, and traffic splitting between app versions, making gradual rollouts easy and flexible.

  • Configurations

The Configuration (configuration.serving.knative.dev) resource defines your deployment's desired state, separating code from configuration as per Twelve-Factor principles.

  • Revisions

A Revision resource (revision.serving.knative.dev) is an immutable snapshot of your app's code and config at a point in time. Revisions scale dynamically with traffic, even to zero when idle, and can be retained to roll back to previous versions when needed.

Eventing

Knative Eventing is an event-driven application platform for Kubernetes that enables building reactive, distributed systems using a set of APIs to connect event producers (sources) with event consumers (sinks).

eventing

Event-driven platform on Kubernetes, connecting event producers (sources) with event consumers (sinks) through a flexible routing layer.

  • Event Ingress

Knative Eventing brings events into the system from internal or external sources. Key components like ApiServerSource, PingSource, KafkaSource, or GoogleCloudPubSubSource generate CloudEvents from Kubernetes changes, schedules, or external messaging systems, enabling your cluster to react to diverse asynchronous signals.

  • Event Routing

It is the core of Knative Eventing, directing events to the right destinations using Brokers and Triggers. Brokers collect all events at an addressable endpoint, while Triggers filter and route them to consumers based on attributes, enabling flexible, decoupled subscriptions without altering producers.

  • Event Egress

Delivers routed events to sinks, which are HTTP endpoints like Knative Services, Kubernetes Services, Deployments, or external APIs. Sinks process the events and execute the business logic, keeping producers and consumers independent while ensuring reliable delivery and response.

Functions

Knative Functions offers a streamlined programming model for running serverless functions on Kubernetes using Knative, designed to remove the complexity of dealing directly with Kubernetes, Knative resources, container images, or Dockerfiles. With Knative Functions, developers can focus purely on writing stateless, event-driven business logic while the platform handles the underlying details.

Using the func CLI, you can easily create, build, and deploy your function as a Knative Service with minimal effort. When you build or execute a function, the system automatically generates an Open Container Initiative (OCI) compliant container image, stores it in a container registry, and keeps it up to date each time you make changes to your code. This allows for a seamless developer experience while adhering to container standards. Developers can work with Knative Functions either through the standalone func CLI or via the kn func plugin integrated into the Knative CLI, enabling flexible workflows and efficient management of function lifecycles.

Comparing Knative with Other Serverless Solutions

Knative brings serverless capabilities to its own Kubernetes clusters. Whether on-premises or in the cloud. It's worth noting that many organizations start their serverless journey with managed platforms like AWS Lambda, Azure Functions, or Google Cloud Run Functions. These solutions are fully managed and excellent for quickly building event-driven applications without managing infrastructure.

However, they come with trade-offs, particularly around vendor lock-in, less control over the underlying environment, and cost/concurrency challenges as workloads scale.

Knative, on the other hand, provides similar serverless patterns, scale-to-zero, event-driven workflows. While running on your own Kubernetes infrastructure.

For teams already invested in Kubernetes or those seeking greater flexibility and cloud neutrality, Knative can be an attractive alternative. It allows you to bring serverless applications closer to where your applications and data already live.

Setting Up Knative on Cluster

To set up Knative on your Kubernetes cluster, you'll need a few prerequisites.

  • A Kubernetes Cluster – You can use any Kubernetes cluster (Minikube, GKE, EKS, etc.) Here, we'll use Kind for local development.
  • kubectl – Installed and configured to interact with your cluster.
  • Knative CLI (kn) – For managing Knative resources.
  • A Networking Layer – Knative requires a networking layer (Istio, Contour, or Kourier). We'll use Kourier for simplicity.

Install Knative using quickstart

Follow the guide here, and you will get the required things up and running.

  • Create kind cluster using knative quickstart plugin
❯ kn quickstart kind
bash
  • Get cluster
❯ kind get clusters knative
bash
  • Kind cluster
❯ k cluster-info Kubernetes control plane is running at https://127.0.0.1:56608 CoreDNS is running at https://127.0.0.1:56608/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy
bash
  • kn CLI version
❯ kn version Version: v1.18.0 Build Date: 2025-04-23 19:42:52 Git Revision: 96721e59 Supported APIs: * Serving - serving.knative.dev/v1 (knative-serving v1.18.0) * Eventing - sources.knative.dev/v1 (knative-eventing v1.18.0) - eventing.knative.dev/v1 (knative-eventing v1.18.0)
bash
  • Verifying the knative-serving setup
❯ kubectl get pods -n knative-serving NAME READY STATUS RESTARTS AGE activator-76dfb9f767-nhv2h 1/1 Running 0 2d16h autoscaler-77f5c4668d-d96bb 1/1 Running 0 2d16h controller-79f47f6984-h5g7v 1/1 Running 0 2d16h net-kourier-controller-666c5cf64b-26q6r 1/1 Running 0 2d16h webhook-c8f58f6f7-ffxl4 1/1 Running 0 2d16h
bash

Deploying First Function

To deploy your first function on Knative, you can use the func CLI, which simplifies building and deploying serverless functions without worrying about containers or YAML. For example, you can quickly scaffold and write a sample function in Go, build it, and deploy it as a Knative Service.

Alternatively, you can define your function directly with a Knative Service YAML, giving you full control over configuration and deployment. Once deployed, you can observe Knative's autoscaling in action.

The function scales down to zero when idle and automatically scales back up when requests arrive, demonstrating true serverless behavior.

Create a New Function

❯ func create -l go -t http knative-hello Created go function in /Users/vishal/knative/knative-hello ❯ tree knative-hello knative-hello ├── func.yaml ├── go.mod ├── handle_test.go ├── handle.go └── README.md 0 directories, 5 files
bash

Deploy the Function using func CLI

❯ func deploy --registry docker.io/vishalanarase --builder=pack Building function image Still building Still building Yes, still building 🙌 Function built: index.docker.io/vishalanarase/knative-hello:latest Pushing function image to the registry "index.docker.io" using the "vishalanarase" user credentials 🎯 Creating Triggers on the cluster ✅ Function deployed in namespace "default" and exposed at URL: http://knative-hello.default.127.0.0.1.sslip.io
bash
  • Knative Service YAML (Option for func deploy)
apiVersion: serving.knative.dev/v1 kind: Service metadata: name: hello spec: template: spec: containers: - image: docker.io/yourrepo/hello
yaml

List Knative service/function

❯ kubectl get ksvc NAME URL LATESTCREATED LATESTREADY READY REASON knative-hello http://knative-hello.default.127.0.0.1.sslip.io knative-hello-00001 knative-hello-00001 True
bash

Invoke the function

curl http://knative-hello.default.127.0.0.1.sslip.io "GET / HTTP/1.1\r\nHost: knative-hello.default.127.0.0.1.sslip.io\r\nAccept: */*\r\nForwarded: for=10.244.0.10;proto=http\r\nK-Proxy-Request: activator\r\nUser-Agent: curl/8.7.1\r\nX-Forwarded-For: 10.244.0.10, 10.244.0.5\r\nX-Forwarded-Proto: http\r\nX-Request-Id: 23a9b1b7-5793-4dc2-92ea-954111643d07\r\n\r\n"
bash

Autoscaling behavior demo

  • Check Initial State (Scaled to Zero)
❯ k get po NAME READY STATUS RESTARTS AGE cert-manager-bd75fc784-f72tm 1/1 Running 3 (57m ago) 7h20m cert-manager-cainjector-6b666b746c-sb2pg 1/1 Running 0 7h20m cert-manager-startupapicheck-wktx4 0/1 Completed 1 7h20m cert-manager-webhook-8468858c77-bkqp4 1/1 Running 0 7h20m cluster-api-operator-554cc6f994-chkv2 1/1 Running 0 7h18m
bash
  • Triggering autoscaling by sending traffic using hey
❯ hey -z 30s -c 50 http://knative-hello.default.127.0.0.1.sslip.io Summary: Total: 30.0566 secs Slowest: 14.5674 secs Fastest: 0.0020 secs Average: 0.4136 secs Requests/sec: 120.7722 Total data: 1259610 bytes Size/request: 347 bytes Response time histogram: 0.002 [1] | 1.459 [3578] |■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ 2.915 [1] | 4.372 [0] | 5.828 [0] | 7.285 [0] | 8.741 [0] | 10.198 [0] | 11.654 [0] | 13.111 [0] | 14.567 [50] | Latency distribution: 10% in 0.0342 secs 25% in 0.0714 secs 50% in 0.1502 secs 75% in 0.3239 secs 90% in 0.5606 secs 95% in 0.7317 secs 99% in 13.9150 secs Details (average, fastest, slowest): DNS+dialup: 0.0123 secs, 0.0020 secs, 14.5674 secs DNS-lookup: 0.0123 secs, 0.0000 secs, 0.8900 secs req write: 0.0000 secs, 0.0000 secs, 0.0011 secs resp wait: 0.4012 secs, 0.0019 secs, 13.6756 secs resp read: 0.0001 secs, 0.0000 secs, 0.0027 secs Status code distribution: [200] 3630 responses
bash
  • Observe Pods Scaling Up
❯ k get po NAME READY STATUS RESTARTS AGE knative-hello-00003-deployment-7d754c97f4-4kj9k 2/2 Running 0 74s knative-hello-00003-deployment-7d754c97f4-4r5jc 2/2 Running 0 76s knative-hello-00003-deployment-7d754c97f4-54whm 2/2 Running 0 74s knative-hello-00003-deployment-7d754c97f4-5srql 2/2 Running 0 76s knative-hello-00003-deployment-7d754c97f4-67lcz 2/2 Running 0 76s knative-hello-00003-deployment-7d754c97f4-6b7g5 2/2 Running 0 74s knative-hello-00003-deployment-7d754c97f4-6rvqz 2/2 Running 0 76s knative-hello-00003-deployment-7d754c97f4-7bnv4 2/2 Running 0 75s knative-hello-00003-deployment-7d754c97f4-7d8wx 2/2 Running 0 70s knative-hello-00003-deployment-7d754c97f4-7md6k 2/2 Running 0 75s knative-hello-00003-deployment-7d754c97f4-7zxq8 2/2 Running 0 75s knative-hello-00003-deployment-7d754c97f4-85pff 2/2 Running 0 76s knative-hello-00003-deployment-7d754c97f4-954h6 2/2 Running 0 75s
bash
  • Check Knative Metrics
❯ kubectl get podautoscaler NAME DESIREDSCALE ACTUALSCALE READY REASON knative-hello-00003 70 55 True
bash
  • Stop traffic and wait Pods Scaled Back to Zero
❯ k get po NAME READY STATUS RESTARTS AGE cert-manager-bd75fc784-f72tm 1/1 Running 3 (62m ago) 7h25m cert-manager-cainjector-6b666b746c-sb2pg 1/1 Running 0 7h25m cert-manager-startupapicheck-wktx4 0/1 Completed 1 7h25m cert-manager-webhook-8468858c77-bkqp4 1/1 Running 0 7h25m cluster-api-operator-554cc6f994-chkv2 1/1 Running 0 7h23m
bash
  • Check Knative Metrics to verify it scale back to zero
❯ kubectl get podautoscaler NAME DESIREDSCALE ACTUALSCALE READY REASON knative-hello-00003 0 0 False NoTraffic
bash

Advanced Features

  • Updated the function and list Revisions
❯ kn revisions list NAME SERVICE TRAFFIC TAGS GENERATION AGE CONDITIONS READY REASON knative-hello-00003 knative-hello 100% 3 22h 3 OK / 4 True knative-hello-00002 knative-hello 2 22h 3 OK / 4 True knative-hello-00001 knative-hello 1 22h 3 OK / 4 True
bash
  • Traffic splitting and canary deployments
❯ kn service update knative-hello --traffic knative-hello-00001=40 --traffic knative-hello-00002=30 --traffic knative-hello-00003=30 Updating Service 'knative-hello' in namespace 'default': 0.067s The Route is still working to reflect the latest desired specification. 0.168s Ingress has not yet been reconciled. 0.222s Waiting for load balancer to be ready 0.386s Ready to serve. Service 'knative-hello' with latest revision 'knative-hello-00003' (unchanged) is available at URL: http://knative-hello.default.127.0.0.1.sslip.io
bash
❯ kn revisions list NAME SERVICE TRAFFIC TAGS GENERATION AGE CONDITIONS READY REASON knative-hello-00003 knative-hello 30% 3 22h 3 OK / 4 True knative-hello-00002 knative-hello 30% 2 22h 3 OK / 4 True knative-hello-00001 knative-hello 40% 1 22h 3 OK / 4 True
bash

Monitoring with Prometheus + Grafana

  • Install the Prometheus Stack by using Helm:
❯ helm install prometheus prometheus-community/kube-prometheus-stack \ --namespace monitoring \ --create-namespace NAME: prometheus LAST DEPLOYED: Tue Jul 8 18:16:14 2025 NAMESPACE: monitoring STATUS: deployed REVISION: 1
bash
  • Apply the ServiceMonitors and PodMonitors to collect metrics from Knative.
❯ kubectl apply -f https://raw.githubusercontent.com/knative-extensions/monitoring/main/servicemonitor.yaml servicemonitor.monitoring.coreos.com/controller created servicemonitor.monitoring.coreos.com/autoscaler created servicemonitor.monitoring.coreos.com/activator created servicemonitor.monitoring.coreos.com/webhook created servicemonitor.monitoring.coreos.com/broker-filter created servicemonitor.monitoring.coreos.com/broker-ingress created podmonitor.monitoring.coreos.com/eventing-controller created podmonitor.monitoring.coreos.com/imc-controller created podmonitor.monitoring.coreos.com/ping-source created podmonitor.monitoring.coreos.com/apiserver-source created
bash
  • Import Grafana dashboards
❯ kubectl apply -f https://raw.githubusercontent.com/knative-extensions/monitoring/main/grafana/dashboards.yaml configmap/knative-eventing-dashboards created configmap/knative-serving-dashboards created
bash
  • Access the Grafana instance locally

By default, the Grafana instance is only exposed on a private service named prometheus-grafana.

Enter the command:

kubectl port-forward -n monitoring svc/prometheus-grafana 3000:80
bash

Access the dashboards in your browser via [http://localhost:3000]

Use the default credentials to login:

username: admin password: prom-operator
bash
knative control plane

This diagram visualizes the Knative Serving control plane's efficiency.

knative scaling

Scaling up pods in response to incoming traffic, ensuring optimal performance and cost efficiency on Kubernetes.

knative request

This image illustrates how Knative Serving routes HTTP requests to specific revisions of a service.

When to choose Knative-based FaaS

  • You're Already Using Kubernetes
    • If your infrastructure runs on Kubernetes, Knative integrates seamlessly without needing external cloud services.
    • Avoid vendor lock-in while keeping the benefits of serverless (scale-to-zero, event-driven execution).
  • Need Fine-Grained Control Over Scaling
    • Knative's autoscaling (KPA) allows custom scaling based on Concurrency (requests-per-pod), RPS (Requests Per Second), CPU/Memory metrics
    • Unlike some managed FaaS (e.g., AWS Lambda), you can tweak scaling behavior precisely.
  • Hybrid or On-Prem Deployments
    • Works in air-gapped environments, private clouds, or edge setups where public cloud FaaS isn't an option.
  • Event-Driven Workloads with Custom Triggers
    • Knative Eventing lets you route events from Kafka, RabbitMQ, CloudEvents, Kubernetes-native sources (e.g., ConfigMap changes,) and Custom event producers
  • CI/CD Pipelines with GitOps
    • Deploy functions via kubectl or func CLI alongside other K8s resources.
    • Works with ArgoCD, Flux, or Tekton for GitOps workflows.

Conclusion

Knative has paved the way for serverless workloads on Kubernetes, combining scalability, event-driven patterns, and advanced deployment strategies into a seamless developer experience. As cloud-native technologies evolve, we can expect even more tailored platforms and patterns for emerging use cases like edge computing and AI.

There are alternatives, options like Kubeless (it's not actively maintained), OpenFaaS, and Fission also bring serverless capabilities to Kubernetes, each with unique strengths and trade-offs. Knative is just one of many tools shaping the future of serverless on Kubernetes.

If you are looking for more help, please contact us for a free consultation.


Ready to Migrate Your Lambda Workloads to Kubernetes?

Unlock the full potential of serverless on your own Kubernetes infrastructure. Download our free guide to planning your AWS Lambda to Kubernetes migration with Knative, or contact us for a personalized consultation today!

Enjoying this post?

Get our posts directly in your inbox.