Serverless Without the Lock-in: Deploying OpenFaaS on High-Performance KVM in Norway
Letâs be honest: "Serverless" is a terrible name. There are always servers. The only difference is whether you control them, or if youâre renting execution time by the millisecond at a massive markup from a US giant. In 2018, the hype cycle around AWS Lambda and Google Cloud Functions is deafening, but for those of us managing serious infrastructure in the Nordics, the cracks are starting to show.
I recently audited a setup for a logistics client in Oslo. They were routing tracking events through a public cloud FaaS (Function as a Service) provider. It worked fine until their Black Friday volume hit. The bill didn't just scale linear; it went exponential. Worse, the "cold start" latencyâthe time it takes for the provider to spin up a containerâwas adding 400ms to every request. For a user in Bergen trying to check a package status on a mobile network, that lag feels like an eternity.
There is a better way. You can have the developer experience of Serverlessâdeploying code, not managing OS patchesâwithout the vendor lock-in or data sovereignty headaches. The answer lies in self-hosted FaaS on top of solid, raw KVM infrastructure.
The Architecture: OpenFaaS on Kubernetes
For this pattern, we aren't getting rid of servers; we are abstracting them. We will use OpenFaaS (Function as a Service), which has matured significantly this year. It runs on top of Docker and Kubernetes, allowing you to turn any binary or container into a serverless function.
Why do this yourself? Control. When you host this on a provider like CoolVDS, you know exactly where your data lives. With the GDPR enforcement that kicked in this past May, relying on US-managed control planes is becoming a compliance minefield for Norwegian data. Keeping the stack on local NVMe storage ensures your data stays within Norwegian jurisdiction, satisfying Datatilsynet requirements.
The Stack
- Infrastructure: CoolVDS KVM Instances (Ubuntu 18.04 LTS)
- Orchestration: Kubernetes 1.11 (via kubeadm)
- FaaS Framework: OpenFaaS
- Ingress: Nginx
Pro Tip: Avoid OpenVZ or LXC containers for this workload. Kubernetes requires low-level kernel access for networking overlays (CNI) and iptables manipulation. You need true hardware virtualization. We use CoolVDS KVM instances because they prevent the "noisy neighbor" CPU steal issues that plague cheaper container-based VPS providers.
Step 1: Preparing the Node
Serverless workloads are bursty. You need high I/O performance because functions are constantly pulling container images and writing logs. Standard SSDs often choke under the queue depth of a busy Kubernetes cluster. This is why we insist on NVMe.
First, let's provision the node and disable swap, as Kubernetes 1.11 still refuses to work properly with it enabled:
# On your CoolVDS instance
swapoff -a
sed -i '/ swap / s/^/#/' /etc/fstab
# Install Docker CE 18.06
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
apt-get update && apt-get install -y docker-ce=18.06.0~ce~3-0~ubuntu
Step 2: Deploying OpenFaaS
Once you have your Kubernetes cluster running (a single master node is fine for dev, 3 nodes for production), we deploy the OpenFaaS gateway. This gateway is the magic piece: it routes incoming HTTP requests to the correct container and auto-scales them based on traffic (Prometheus metrics).
We'll use kubectl to apply the yaml definitions. Note the use of RBAC (Role-Based Access Control), which is now standard in K8s 1.6+.
git clone https://github.com/openfaas/faas-netes
cd faas-netes
# Apply namespaces
kubectl apply -f namespaces.yml
# Deploy the stack (Gateway, Prometheus, AlertManager)
kubectl apply -f ./yaml
After a few seconds, check your services. You want to see the Gateway listening on port 31112 (NodePort).
$ kubectl get svc -n openfaas
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
alertmanager NodePort 10.106.98.11 9093:31119/TCP 1m
gateway NodePort 10.111.9.117 8080:31112/TCP 1m
prometheus NodePort 10.103.111.95 9090:31119/TCP 1m
Step 3: Creating a Python Function
Now for the developer experience. We use the faas-cli to scaffold a new function. Let's make a simple image resizerâa classic serverless use case.
# Install CLI
curl -sL https://cli.openfaas.com | sudo sh
# Create new python function
faas-cli new --lang python3 image-resizer --prefix=registry.coolvds-user.com
This generates a handler.py. We can use standard Python libraries. Because we are running on a KVM instance with decent specs, we don't need to worry about the memory limits as strictly as we do on AWS Lambda (where 128MB is the default).
import sys
from PIL import Image
import io
def handle(req):
try:
# Read image bytes from request
image_data = io.BytesIO(req.encode('utf-8'))
img = Image.open(image_data)
# Resize logic
img = img.resize((128, 128), Image.ANTIALIAS)
# Output
byte_io = io.BytesIO()
img.save(byte_io, 'PNG')
return byte_io.getvalue()
except Exception as e:
return str(e)
Step 4: The Performance Difference
Here is where the infrastructure choice matters. In a public cloud serverless environment, this function might be placed on a host that is already oversubscribed. When you trigger it, the network latency to fetch the Python docker image, spin it up, and execute can take 2-3 seconds (Cold Start).
On your CoolVDS instance, leveraging NVMe storage, image pull times are negligible. Furthermore, you can configure OpenFaaS to keep a "warm" replica always running. Since you are paying a flat monthly rate for the VPS, keeping one container alive costs you nothing extra. You get sub-10ms response times immediately.
Latency Comparison (Oslo Region)
| Metric | Public Cloud FaaS (London) | CoolVDS (Oslo) + OpenFaaS |
|---|---|---|
| Network Latency | 25-35 ms | < 2 ms (via NIX) |
| Cold Start | ~400 ms | ~50 ms (NVMe cached) |
| Data Location | UK/US (Uncertainty) | Norway (GDPR Compliant) |
| Cost Model | Per Request (Unpredictable) | Flat Rate (Predictable) |
Security & Nginx Configuration
Never expose the OpenFaaS gateway directly to the internet. We need a reverse proxy. Nginx is the industry standard here. On your CoolVDS server, install Nginx and set up a basic proxy pass with rate limiting to prevent DDoS attacks against your functions.
server {
listen 80;
server_name functions.your-domain.no;
location / {
proxy_pass http://127.0.0.1:31112;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
# Buffer settings for larger payloads (images)
client_max_body_size 50M;
proxy_buffers 16 16k;
proxy_buffer_size 32k;
}
}
This setup gives you a production-ready FaaS platform. You handle the scaling logic via Kubernetes, and the raw performance is delivered by the underlying hardware.
Conclusion
Serverless architecture is a powerful pattern, but it shouldn't mean surrendering your infrastructure to a black box. By combining Kubernetes and OpenFaaS on high-performance VPS Norway infrastructure, you gain the agility of functions with the stability and predictability of owned hardware.
Don't let latency or legal uncertainty dictate your architecture. Deploy a KVM instance today and build a platform that actually belongs to you.
Ready to build? Launch a High-Performance CoolVDS Instance in Oslo now and get root access in under 60 seconds.