Console Login

Escaping Vendor Lock-in: Building a Private Serverless Platform with Knative and Kubernetes

The "Serverless" Lie: Why We Built Our Own FaaS on Raw Compute

Let's get one thing straight immediately: "Serverless" is a marketing term for a billing model. There are always servers. The difference is whether you control the kernel, the network stack, and the billβ€”or if Amazon and Google do.

In 2019, the allure of AWS Lambda or Google Cloud Functions is strong. You push code, it runs, you pay per millisecond. But for those of us managing serious workloads in the Nordics, the cracks appear quickly. Cold starts taking 2 seconds? Unpredictable latency spikes because your function landed on a noisy hypervisor? Data residency concerns with Datatilsynet because you aren't sure exactly where that ephemeral container executed?

I recently consulted for a fintech startup in Oslo. They were bleeding money on public cloud functions because their idle-heavy workloads were keeping resources "warm" artificially to avoid latency penalties. The solution wasn't more cloud optimizations; it was moving to a self-hosted Kubernetes cluster running Knative.

The Architecture: Knative on Bare-Metal KVM

Knative provides the building blocks for serverless workloads on Kubernetes: Serving (scale-to-zero, request-driven model) and Eventing. But Knative is heavy. It relies on Istio (currently v1.2) as a service mesh. If you try to run this on a budget VPS with shared CPU resources, the control plane alone will starve your application.

This is why the underlying infrastructure matters. We need dedicated KVM slices. We need NVMe storage because when a function scales from zero to one, the container image pull time is the biggest bottleneck. Spinning drives effectively kill the serverless experience.

Pro Tip: Don't skimp on the Control Plane node. Istio Pilot and Mixer are memory hungry. For a production Knative cluster, I recommend at least 8GB RAM for the master node if you are running a single-master topology. On CoolVDS, the "Performance" tier is usually the sweet spot here.

Step 1: Prerequisite Checks

We are assuming you have a Kubernetes v1.14 or v1.15 cluster running. If you are setting this up on CoolVDS, standard Ubuntu 18.04 LTS images with `kubeadm` are the way to go. Do not use Docker versions newer than 18.09 yet; K8s compatibility can be flaky.

# Check your node resources before we start adding the heavy lifting
kubectl get nodes -o wide

# Ensure you have enough allocatable memory
kubectl describe node <node-name> | grep Allocatable -A 5

Step 2: The Service Mesh (Istio)

Knative (v0.7) requires Istio. It uses the mesh for traffic splitting and ingress routing. We'll use the lean installation to avoid installing the kitchen sink (Prometheus, Grafana, Jaeger) unless you specifically need them right now.

# Download Istio 1.2.2
curl -L https://git.io/getLatestIstio | ISTIO_VERSION=1.2.2 sh -
cd istio-1.2.2

# Install the CRDs
for i in install/kubernetes/helm/istio-init/files/crd*yaml; do kubectl apply -f $i; done

# Create the namespace
kubectl create namespace istio-system

# Apply the configuration (using the lean profile for lower resource usage)
kubectl apply -f install/kubernetes/istio-demo-lean.yaml

Step 3: Deploying Knative Serving

Once Istio is healthy (check your pods in `istio-system`), we apply the Knative CRDs and core components. This puts the "Serving" controller in charge of watching your deployments.

kubectl apply --selector knative.dev/crd-install=true \
--filename https://github.com/knative/serving/releases/download/v0.7.0/serving.yaml \
--filename https://github.com/knative/build/releases/download/v0.7.0/build.yaml \
--filename https://github.com/knative/eventing/releases/download/v0.7.0/eventing.yaml

# Wait for the CRDs to establish, then apply the rest
kubectl apply --filename https://github.com/knative/serving/releases/download/v0.7.0/serving.yaml --selector networking.knative.dev/certificate-provider!=cert-manager

The Real-World Test: Latency and I/O

Here is where the hardware hits the road. When a request hits the Istio Ingress Gateway, Knative checks if a pod is running. If not, it triggers the Activator, which scales the deployment up.

I ran a benchmark comparing a standard VPS provider (spinning disk, OpenVZ) against a CoolVDS NVMe KVM instance. The metric: Cold Start Time for a simple Go binary.

Metric Standard HDD VPS CoolVDS NVMe KVM
Image Pull (150MB) 4.2s 0.8s
Container Creation 1.5s 0.4s
Total Cold Start ~6s ~1.5s

That 1.5-second cold start is acceptable for many webhooks and background processors. Six seconds is a timeout waiting to happen. This speed difference is almost entirely due to NVMe storage I/O and the lack of "CPU Steal" that plagues oversold hosting providers.

Deployment Configuration

To deploy your function, you stop writing standard K8s `Deployment` YAMLs and switch to a Knative `Service`. Here is a robust configuration for a Python microservice:

apiVersion: serving.knative.dev/v1alpha1
kind: Service
metadata:
  name: payment-processor
  namespace: default
spec:
  template:
    metadata:
      annotations:
        # Limit scaling to prevent resource exhaustion on your cluster
        autoscaling.knative.dev/maxScale: "10"
    spec:
      containers:
        - image: docker.io/myrepo/payment-processor:v1
          env:
            - name: TARGET
              value: "Norwegian Krone"
          resources:
            limits:
              memory: "256Mi"
              cpu: "500m"

Why Location Matters: The Norwegian Context

If your users are in Oslo, Bergen, or Trondheim, routing traffic through Frankfurt or London adds 30-50ms of latency unnecessarily. By hosting your Knative cluster on VPS Norway infrastructure, you keep the round-trip time (RTT) incredibly low.

Furthermore, GDPR compliance is strict. While Privacy Shield is currently in effect, legal experts are already wary of US-cloud data transfers. Keeping your processing logic and database state on servers physically located in Norway simplifies your compliance posture with Datatilsynet. You know exactly where the drive is.

Troubleshooting: When Autoscaling Fails

A common issue in 2019 builds of Knative is the "Activator" getting stuck if the underlying network is flaky. If your pods aren't scaling up, check the activator logs:

kubectl logs -n knative-serving -l app=activator -c activator

Usually, this traces back to DNS timeouts. Ensure your CoreDNS config map is tuned correctly. On CoolVDS, we configure our upstream resolvers to be extremely fast, but you should verify your `/etc/resolv.conf` isn't using a slow public resolver.

Conclusion

Running serverless on your own infrastructure isn't just a fun experiment; it's a valid strategy for cost reduction and performance stability. You trade the convenience of AWS Lambda for the raw power and predictability of KVM.

However, this stack requires hardware that can keep up. Knative and Istio are not forgiving on slow I/O. If you want to replicate the results above, you need high-frequency CPUs and genuine NVMe storage.

Ready to build your private cloud? spin up a high-performance KVM instance on CoolVDS today and start deploying in under 60 seconds.