Getting started
vNode is a tenant isolation container runtime that provides strong isolation between workloads using Linux user namespaces and seccomp filters. It runs in Kubernetes environments and supports privileged workloads such as Docker-in-Docker and Kubernetes-in-Kubernetes. For more details, see the vNode architecture.
vNode places each pod inside an isolated sandbox on the Kubernetes node.
Before you begin
- An existing vCluster Platform installation.
- A license plan that includes vNode. To verify your plan, navigate to Platform Config → License and Billing in the platform. If vNode is not listed, contact support@vcluster.com.
- A valid platform access key. Not required when deploying vNode inside a Tenant Cluster.
- A Kubernetes cluster meeting the system requirements — Linux kernel 6.1+, containerd 1.7 or 2.0, Kubernetes 1.24+.
Set your environment variables
# Platform host
PLATFORM_HOST=https://platform-your-domain.com
# Platform access key
PLATFORM_ACCESS_KEY=your-access-key
If the vCluster Platform is deployed in the same cluster as vNode, set PLATFORM_HOST to the platform Service's ClusterIP, not its cluster-internal DNS name (for example, https://loft.vcluster-platform).
The vnode-manager enters the node's network namespace to configure containerd. From that namespace it uses the node's DNS resolver, which cannot resolve cluster-internal service names. kube-proxy does route ClusterIP traffic for node-originated connections, so the ClusterIP address works correctly.
Find the ClusterIP of the platform Service:
kubectl get svc loft -n vcluster-platform -o jsonpath='{.spec.clusterIP}'
Then set PLATFORM_HOST=https://<clusterIP>:443.
If a cluster-internal DNS name is used instead, the manager logs dial tcp: lookup ... no such host, containerd is never reconfigured, and tenant pods fail with FailedCreatePodSandbox: no runtime for "vnode" is configured.
If you manage vNode with Argo CD, Flux, or another GitOps tool, store the access key in a Kubernetes secret instead of your values file. See Provide the platform access key via a secret.
Install vNode
helm upgrade --install vnode-runtime vnode-runtime -n vnode-runtime \
--repo https://charts.loft.sh --create-namespace \
--set "config.platform.host=https://platform-your-domain.com" \
--set "config.platform.accessKey=your-access-key"
# Add the following only if your platform uses a self-signed certificate:
# --set "config.platform.insecure=true"
For cluster creation steps and platform-specific configuration, see Installation.
Verify your installation
Create a privileged test pod using the vNode runtime:
echo "apiVersion: v1
kind: Pod
metadata:
name: vnode-test
spec:
runtimeClassName: vnode
hostPID: true
terminationGracePeriodSeconds: 1
containers:
- image: ubuntu:jammy
name: vnode-test
command: ['tail', '-f', '/dev/null']
securityContext:
privileged: true" | kubectl apply -f -
kubectl wait --for=condition=ready pod vnode-test
Verify UID remapping
User namespace remapping is the observable proof that vNode's tenant isolation is active. Read /proc/self/uid_map inside the pod:
kubectl exec vnode-test -- cat /proc/self/uid_map
A pod using the vNode runtime shows root remapped to a high unprivileged host UID:
0 589824 65536
Container UID 0 maps to host UID 589824. Even if a process escapes the container boundary, it has no host privileges.
A pod not using the vNode runtime shows an identity map:
0 0 4294967295
UID 0 inside the container is UID 0 on the host. If you see this output on a pod that should be using vNode, check that containerd was reconfigured successfully (see the ClusterIP note in Set your environment variables).
Verify process isolation
Within the test pod, ps -ef shows only the pod's own processes — not those of other containers or the host:
kubectl exec -it vnode-test -- ps -ef --forest
UID PID PPID C STIME TTY TIME CMD
root 1 0 0 10:20 ? 00:00:00 /var/lib/vnode/bin/vnode-init
root 53 1 0 10:20 ? 00:00:00 /var/lib/vnode/bin/vnode-containerd-shim-runc-v
65535 75 53 0 10:20 ? 00:00:00 \_ /pause
root 185 53 0 10:20 ? 00:00:00 \_ tail -f /dev/null
Without vNode, a privileged pod with hostPID: true would see all processes on the host.