Let’s be brutally honest: you run a container in privileged mode for the same reason you give a toddler a power tool—because you’re either performing a very specific, dangerous task under close supervision, or you’re about to have a very, very bad day. A privileged container is essentially a process on your host node that has politely asked the kernel for its entire set of privileges, and the kernel, like a tired parent, has said “Fine, whatever, just don’t break anything.”

Running a container with privileged: true is the nuclear option. It strips away the isolation mechanisms that make containers safe and gives the process almost all the capabilities of the root user on the host machine. It can mount devices, reconfigure the network stack, and even, if you’re particularly unlucky, use the debugfs trick to escape to the host node entirely. I’ve seen it happen. It’s not pretty.

Why You Think You Need It (And Why You’re Probably Wrong)

You’re likely considering a privileged container for one of a few classic reasons. You need to use a hardware device (/dev something), you’re trying to use tcpdump or another networking tool that requires raw sockets, or you’re running some legacy systemd-based application that throws a fit without CAP_SYS_ADMIN. In 90% of these cases, you don’t need the sledgehammer of privileged; you need the scalpel of Linux Capabilities.

For example, you want to run tcpdump in a container to debug network issues. The lazy, dangerous way is this:

apiVersion: v1
kind: Pod
metadata:
  name: bad-idea-pod
spec:
  containers:
  - name: packet-sniffer
    image: corfr/tcpdump
    securityContext:
      privileged: true # NO. DON'T.

The correct, secure way is to add only the specific capabilities needed for the job. tcpdump needs CAP_NET_RAW and CAP_NET_ADMIN to do its magic. Nothing more.

apiVersion: v1
kind: Pod
metadata:
  name: better-idea-pod
spec:
  containers:
  - name: packet-sniffer
    image: corfr/tcpdump
    securityContext:
      capabilities:
        add: ["NET_RAW", "NET_ADMIN"] # Surgical precision.
      runAsUser: 1000 # And don't run as root while you're at it!

The Anatomy of a Privileged Container

So what does privileged: true actually do? It’s a macro that sets a bunch of dangerous settings all at once:

  • It grants the container every single Linux capability (CAP_SYS_ADMIN, CAP_SYS_MODULE, you name it).
  • It disables seccomp, AppArmor, and SELinux protections. All those security profiles you painstakingly configured? Gone. The container effectively tells the kernel, “I am the law now.”
  • It does not mask any system devices. The container can see and interact with every device on the host, like /dev/mem, which is a direct line into the host’s memory.

You can see this for yourself. Run a privileged container and look at the capabilities and devices.

# Run a privileged container
kubectl run -it --rm privileged-test --image=ubuntu --restart=Never --privileged

# Inside the container, check capabilities
cat /proc/self/status | grep CapEff
# You'll see a massive hex value like 0000003fffffffff, meaning almost all caps are set.

# Check devices
ls -la /dev/ | wc -l # A huge list of host devices

Now compare it to a non-privileged one:

# Run a non-privileged container
kubectl run -it --rm non-privileged-test --image=ubuntu --restart=Never

# Inside the container, check capabilities
cat /proc/self/status | grep CapEff
# You'll see a much smaller value like 0000000000000000 or 00000000a80425fb

# Check devices
ls -la /dev/ | wc -l # A very short, curated list

The One Semi-Valid Use Case

There is one arena where privileged containers are not just convenient but necessary: building container images or running container runtimes inside a pod. Tools like Docker-in-Docker (dind) or systemd-based operators that need to manage cgroups often require this level of access. Even then, you should treat these pods as an extension of the host’s trust boundary. They are a necessary evil, not a default pattern.

If you find yourself in this position, you must isolate them ruthlessly. Use nodeSelector to taint and tolerate them onto a dedicated, hardened node pool. Apply stringent Network Policies to ensure they can’t talk to anything else in your cluster. Their blast radius must be contained.

The Golden Rule

The rule is simple: never use privileged: true in a PodSpec. Treat it like a syntax error. Your default response to seeing it should be the same as if you saw apiVersion: please-hack-me/v1. If a piece of software demands it to run, that software is not designed for a multi-tenant Kubernetes environment. Find an alternative, pressure the vendor to fix their security model, or accept that you are introducing a catastrophic risk to your cluster. There are very few exceptions, and “it’s easier” is not one of them. Your future self, who isn’t cleaning up after a crypto-mining incident, will thank you.