Skip to content

Introduction to User Namespaces in Kubernetes

In Kubernetes, some features arrive quietly, but leave a massive impact. Kubernetes v1.33 is turning out to be one such release where there are some features with massive impact. In the previous blog, my colleague described how you can provision and operate Kubernetes v1.33 clusters on bare metal and VM based environments using Rafay.

In this blog, we will discuss a new feature in v1.33 called User Namespaces. This feature is not a headline grabber such as a service mesh etc, but is a game changer for container security.

Container in a Jail


Enter User Namespaces

For years, one of the most troubling issues with containerization was that root in the container often meant root on the host. So, if a containerized application was compromised and running as root, an attacker could potentially break out and gain control of the entire node. In a nutshell,

For all their benefits, containers were never supposed to be full-blown security boundaries.

User namespaces change the status quo. A user namespace is a Linux feature that isolates the user and group identifiers (UIDs and GIDs) of the containers from the ones on the host.

  1. Since the UIDs and GIDs for different containers are mapped to different UIDs and GIDs on the host, containers cannot attack each other even if they escape the container boundaries.

  2. Since the UIDs and GIDs are mapped to unprivileged users on the host, if a container escapes the container boundaries, even if it is running as root inside the container, it has no privileges on the host. This greatly protects what host files it can read/write, which process it can send signals to, etc.

  3. Capabilities granted are only valid inside the user namespace and not on the host.

In very simple terms, root inside the container ≠ root on the host.

Info

This separation means that even if an attacker gains root access within a container, they no longer gain escalated privileges on the host machine. It’s a foundational improvement for defense-in-depth strategies in Kubernetes environments.


🛠 How to Enable User Namespaces

Using user namespaces in your Pod spec is extremely straightforward. Just add the following field highlighted below. ✅ That’s it.

apiVersion: v1
kind: Pod
metadata:
  name: userns
spec:
  hostUsers: false
  containers:
  - name: shell
    command: ["sleep", "infinity"]
    image: debian

Note

App Developers will likely not remember to implement this manually. As a result, it is more practical for administrators to enforce it cluster-wide using a mutating admission webhook or an admission controller.


Requirements

There are several requirements that need to be satisfied before you can use this feature in Kubernetes v1.33.

  1. The node OS needs to be Linux
  2. Linux Kernel v6.3 or higher (e.g. Ubuntu 24.04 LTS) which supports idmappings
  3. A supported container runtime (e.g. containerd v2.0+)

Example/Demo

For our demo, we have provisioned a Rafay MKS Cluster based on Kubernetes v1.33.

MKS 1.33

As you can see from the node details, we are using "containerd v2.x" and "Linux Kernel v6.8". So, all our requirements listed above are satisfied.

MKS 1.33 Node

Step 1: Deploy Pod

Let's deploy this to our Kubernetes v1.33 cluster using kubectl (i.e. kubectl apply -f userns.yaml). This will deploy the pod into the "default" namespace.

apiVersion: v1
kind: Pod
metadata:
  name: userns
spec:
  hostUsers: false
  containers:
  - name: shell
    command: ["sleep", "infinity"]
    image: debian

Step 2: Check UID/GID

Now, let us check the UID and GID for our container

kubectl exec -it userns -n default -- cat /proc/1/status | grep -E 'Uid|Gid'

You should see something like the

uid=0(root) gid=0(root) groups=0(root)

This output means the following:

Field Value Description
uid=0(root) UID 0 (root) The process inside the container is running as user ID 0, the root user.
gid=0(root) GID 0 (root) The process belongs to group ID 0, also named root.
groups=0(root) Group 0 The user is a member of the root group, confirming full privileges inside the container.

Inside the Container

The process has full root privileges within the container’s namespace. As a result, it can perform administrative tasks such as modifying system files, installing packages, etc.

On the Host

Whether this is dangerous depends on your container runtime isolation.

Case A: Without User Namespaces (hostUsers: true or default)

  • Root in container = root on host.
  • If there’s a container breakout (via vulnerability), the attacker may gain root access to the node, a serious security risk.

Case B: With User Namespaces (hostUsers: false)

  • Root in container ≠ root on host.
  • UID 0 inside the container maps to an unprivileged UID on the host (e.g., 100000).
  • Breakouts still possible, but less damaging (containment enforced).

The image below shows an illustrative example for a k8s pod with user namespace enabled.

UID GID Mapping k8s 1.33


Conclusion

Security professionals at enterprises wrestle with the illusion of containment in modern infrastructure. Namespaces—particularly user namespaces—are an elegant way to achieve true segregation, not just isolation. Click here for more information about this user namespaces. Enabling user namespaces brings immediate and measurable security benefits.

🚫 1. Prevent Lateral Movement

Isolate compromised containers to prevent them from accessing other workloads.

🛡 2. Reduce Blast Radius

Minimize the impact of container escapes.

🔄 3. Support Legacy Apps

Run applications that require root access—safely—without exposing the host to unnecessary risk.

In the next blog on interesting features in Kubernetes 1.33, we will discuss how you can change the CPU and memory resource requests and limits assigned to a container without recreating the Pod.