← Back to Blog
Header image for blog post: Your containers aren’t isolated. Here’s why that’s a problem. microVMs, VMMs and container isolation.
Will Stewart
Published 26th May 2025

Your containers aren’t isolated. Here’s why that’s a problem. microVMs, VMMs and container isolation.

Everyone wants to build faster now. AI agents write code, generate tasks, even deploy apps. Package managers like npm let you install 12,000 transitive dependencies with a single command.

This means you can ship fast. It also means you might be inviting an attacker to run code in your infrastructure… and you'd barely notice.

This isn't theoretical. Malicious packages get published. Supply chain attacks spread laterally. Developers run random scripts from GitHub just to get something working. And now we're asking AI agents to decide what packages to install, what commands to run, and what services to spin up.

If you're deploying this stuff into the same environment that runs your customer workloads, you're playing with fire.

The illusion of isolation

Containers are often treated like security boundaries. They're not. Namespacing, seccomp, AppArmor, disabling kernel capabilities, running as non-root, all of these help, but none of them prevent container escapes. runc, the default container runtime for Docker and Kubernetes, shares the host kernel. If an attacker breaks out of a container, they get access to the host. And if that host is shared between tenants? Game over.

A successful container escape lets someone:

  • Steal environment variables (your Stripe key, your DB password)

  • Access the node's IAM permissions (hello, S3 bucket exfiltration)

  • Laterally move into other workloads (multi-tenant compromise)

Now imagine one of those variables is your OpenAI key, your Cloudflare API token, or access to your Kubernetes cluster, because an AI agent "needed it" to run.

That's not a rare edge case. It's the whole point of multi-tenancy. If you're not isolating untrusted code at the kernel level or below, you're leaving yourself and your customers exposed.

You need container sandboxing

This is where secure runtimes come in. You need a way to execute code that cannot affect anything outside its box, no matter how malicious it gets.

Two leading approaches stand out:

gVisor

gVisor is a user-space kernel developed by Google. It intercepts syscalls and simulates a Linux kernel, acting as a kind of syscall proxy. This gives you a strong sandbox: code thinks it's talking to Linux, but it's actually talking to gVisor. The result? A drastically reduced attack surface.

gVisor supports multiple execution modes:

  1. PTrace uses ptrace to intercept syscalls. Very secure, very slow, no longer maintained

  2. KVM: uses virtualization for syscall isolation. Fastest option for bare-metal.

  3. Systrap: uses seccomp to intercept syscalls. Better performance than ptrace.

Storage modes include:

  • Directfs: Securely exposes file descriptors to the sandbox. Replaces gofer RPCs for more performant filesystem operations

  • Overlayfs: provides a union filesystem with isolation.

It’s not a silver bullet. gVisor doesn’t support every syscall, which means not every workload can run inside it. But for AI agents, scripts, and anything you wouldn’t run on prod bare metal, it’s a strong contender.

3.png

KVM + microVMs

Kernel-based Virtual Machines (KVM) take a different approach. Instead of simulating a kernel, you boot an actual VM, fast and minimal. Technologies like Firecracker (used by AWS Lambda), Cloud Hypervisor, and Kata Containers let you run these VMs with overhead that’s just a few percent above containers.

Kata Containers integrates with Kubernetes and CRI. Under the hood, it spins up lightweight VMs with full kernel isolation, giving you the best of both worlds: container workflows with VM-level security.

Northflank uses Kata Containers and Cloud Hypervisor in production. We run over 2 million microVMs per month inside Kubernetes. It works. It scales. And it keeps your workloads isolated even in high-density, noisy, multi-tenant environments.

When should you care about container isolation?

If you're:

  • Running code you didn’t write (AI-generated, open source, customer-submitted, AI agents you didn’t write)
  • Providing an execution sandbox for others (ML workloads, agents, plugins)
  • Offering multi-tenant services on shared infrastructure
  • Just paranoid enough to want true production isolation
  • Or using code gen tools that generate and deploy code in real-time without human review

Then yes, you should care. And you should probably be running secure runtimes.

It’s not just about compute isolation

Isolation isn't just about sandboxing code. You need to defend across layers:

Networking security in Kubernetes

  • Use service mesh + mTLS to enforce trusted service-to-service communication.
  • Use Cilium and Kubernetes NetworkPolicies to block cross-namespace or cross-project traffic.

Workload permissions

  • Enforce strict PodSecurityPolicies or PodSecurityAdmission.
  • Remove default capabilities, deny host access, and disable privileged mode.
  • Use RBAC to deny Kubernetes API access from within pods.

Resource abuse (noisy neighbors)

  • Rate-limit DNS, disk, and CPU usage.
  • Apply cgroups and ephemeral storage limits to sandbox abuse.

Running secure isolation is an ongoing operational grind

gVisor and Kata Containers are evolving constantly. New kernel versions break things. Security patches deprecate syscalls. Performance regressions creep in.

One week, a runtime works flawlessly; the next, it silently fails under load. You’re juggling compatibility between container runtimes, kernel modules, CRI implementations, and virtualization backends.

Nested virtualization might stop working on a new GCP instance type. A gVisor update might block a syscall your workload suddenly needs. You can’t set it and forget it. Maintaining secure isolation means continuous testing, fast iteration, and deep understanding of the stack at every level, from Kubernetes to KVM.

Most teams don’t have the time or muscle to do that well. We do.

How to get started DIY

You don’t need to rebuild your entire stack to get secure runtimes.

How to install and setup gVisor

Install via runsc:

sudo apt-get update && \
sudo apt-get install -y \
    apt-transport-https \
    ca-certificates \
    curl \
    gnupg

sudo apt-get update && sudo apt-get install -y runsc

In Kubernetes, configure your container runtime class and use runsc.

How to install and setup Kata Containers (on Kubernetes)

Follow the official guide:

# Deploy the needed RBAC for running the kata-deploy daemonset
kubectl apply -f https://raw.githubusercontent.com/kata-containers/kata-containers/main/tools/packaging/kata-deploy/kata-rbac/base/kata-rbac.yaml

# Deploy the kata-deploy daemonset
kubectl apply -f https://raw.githubusercontent.com/kata-containers/kata-containers/main/tools/packaging/kata-deploy/kata-deploy/base/kata-deploy.yaml

# Ensure kata-deploy is ready
kubectl -n kube-system wait --timeout=10m --for=condition=Ready -l name=kata-deploy pod

# Deploy the runtimeClasses
kubectl apply -f https://raw.githubusercontent.com/kata-containers/kata-containers/main/tools/packaging/kata-deploy/runtimeclasses/kata-runtimeClasses.yaml

# And run an example workload using Kata Containers and Cloud Hypervisor
kubectl apply -f https://raw.githubusercontent.com/kata-containers/kata-containers/main/tools/packaging/kata-deploy/examples/test-deploy-kata-clh.yaml

Or, skip the setup.

What we do at Northflank

2.png

Northflank offers a secure runtime environment by default. Whether you're running production workloads or sandboxed AI agents, every container is isolated in the way that makes sense for your workload:

  • On environments where nested virtualisation is unavailable? We use gVisor.
  • On infra that supports nested virtualisation? We run Kata + Cloud Hypervisor.

You get VM-grade security, container-grade workflows, and Kubernetes-native orchestration, on any cloud, in 30 minutes with Bring your own Cloud or in seconds on Northflank PaaS.

That matters when you're working with AI tools like MCPs or self/hosted agents, especially when those services demand your API tokens or environment variables to work. They might need your Cloudflare auth token, your Stripe secret key, your Postgres access. You're giving them access to run against your infra. Without proper isolation, you're giving them the ability to become your infra.

If you're using code gen tools, you better know where the source code is being generated (and where it's being used) because your most precious asset (your source code) could be under attack.

Secure runtime is the thing that prevents someone else's AI from running your infrastructure into the ground. You should wrap it, because otherwise it'll ruin the rest of your stack.

If you're building infrastructure for the next generation of apps (AI-driven, plugin-based, user-customizable) you need more than just a container. You need a sandbox that doesn’t break when someone does something stupid, malicious, or both.

That’s what we’ve built. If you want help running it, come talk to us.

To deploy a secure microVM on Northflank via the API is two requests, all you need to do is the following:

  1. Create a project to provide tenant, network and namespace isolation

    await apiClient.create.project({
      data: {
        "name": "New Project",
        "description": "This is a new project.",
        "region": "europe-west",
      }    
    });
  2. Create a Northflank service that deploys an existing container image from a registry. This will spawn a container on a Kubernetes cluster and isolate it in a microVM, also known as a VMM.

    await apiClient.create.service.deployment({
      data: {
        "name": "alpine-linux",
        "infrastructure": {
          "architecture": "x86"
        },
        "billing": {
          "deploymentPlan": "nf-compute-50"
        },
        "deployment": {
          "type": "deployment",
          "instances": 1,
          "docker": {
            "configType": "customCommand",
            "customCommand": "sleep 5000"
          },
          "external": {
            "imagePath": "alpine:latest"
          },
        },
      }
    });
  3. If you need advanced networking, custom DNS, secrets injection, white-labelled Git based CI/CD, certificate management, autoscaling this all comes built in

Share this article with your network
X