Kubernetes Privileged Container Control: Disable Privileged Mode & Enforce Least Privilege in Production
This guide explains why privileged containers are a critical security risk in Kubernetes, details core securityContext fields and Pod Security Standards, demonstrates how to disable privileged containers using built-in PodSecurity Admission and Kyverno policies, provides a hardened securityContext template for workloads, and outlines a phased approach to eliminate existing privileged workloads while handling operational exceptions.
Background: Privileged Containers as a "Nuclear Button" in Kubernetes
In the Docker era, --privileged was treated as a temporary debugging tool. In Kubernetes, running a Pod in privileged mode hands over most host capabilities to the container:
Access to all host devices ( /dev)
Ability to load kernel modules, manipulate iptables, mount filesystems
Easy container escape to gain node-level root access
This means any compromised privileged container can escalate to full node or cluster compromise, blocks compliance (zero-trust, MLPS, cloud-native security baselines), and creates configuration debt from "just enable privileged for convenience." Modern consensus: privileged containers must be an extreme exception in production.
Core Concepts & Key Configuration Fields
2.1 Privileged & Permission-Related Fields
In Pod spec, the main fields are: securityContext.privileged: run container in privileged mode securityContext.allowPrivilegeEscalation: allow privilege escalation (e.g., setuid) securityContext.capabilities: Linux capabilities (e.g., CAP_SYS_ADMIN), add/drop securityContext.runAsUser / runAsNonRoot: run as non-root user securityContext.readOnlyRootFilesystem: root filesystem read-only securityContext.seccompProfile: enable seccomp syscall filtering
These fields combine to define the container's "action boundary" on the host.
2.2 Pod Security Standards (Baseline / Restricted)
PodSecurity provides three preset levels: privileged: almost unrestricted, only for highly trusted environments baseline: blocks most obviously dangerous capabilities, retains some compatibility restricted: enforces least privilege, requires container image cooperation
For most production business namespaces, use restricted as the enforce level to ban privileged containers and most high-risk configs from the ground up. restricted core goal: forbid running as root — either set runAsNonRoot: true, explicit runAsUser > 0, or image USER non-zero.
Policy Layer: Blanket Ban on Privileged Containers
3.1 Built-in PodSecurity Admission (K8s 1.25+)
PSP removed; replaced by built-in PodSecurity Admission. First step: label namespaces:
apiVersion: v1
kind: Namespace
metadata:
name: prod-app
labels:
pod-security.kubernetes.io/enforce: "restricted"
pod-security.kubernetes.io/enforce-version: "latest"
pod-security.kubernetes.io/audit: "restricted"
pod-security.kubernetes.io/warn: "restricted"Under restricted:
Forbids securityContext.privileged: true Strictly limits hostPID, hostNetwork, hostPath Rejects root containers (via runAsNonRoot, runAsUser, image USER)
Advantage: out-of-the-box, policy evolves automatically with K8s upgrades.
3.2 Kyverno for Fine-Grained Control
For finer control (e.g., only business namespaces, relax for ops tools), use Kyverno. Example: disallow explicit privileged: true in specific namespaces:
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: disallow-privileged-containers
spec:
validationFailureAction: Enforce
background: true
rules:
- name: disallow-privileged
match:
resources:
kinds:
- Pod
validate:
message: "不允许创建 privileged 容器"
pattern:
spec:
containers:
- securityContext:
privileged: falseNote: above rule only constrains containers that explicitly set privileged ; unset fields fall back to PodSecurity restricted baseline. Production pattern: PodSecurity for baseline safety, Kyverno for business-side fine-grained constraints and audit .
Policy engine enables:
Different security baselines per environment (dev/test/prod)
Exception for few must-have-privileged ops namespaces (via namespaceSelector)
Audit trail for every policy change
Workload Layer: Least Privilege Implementation Examples
4.1 Recommended Container securityContext Template
Hardened Pod template for general business apps:
apiVersion: apps/v1
kind: Deployment
metadata:
name: demo-web
namespace: prod-app
spec:
replicas: 3
selector:
matchLabels:
app: demo-web
template:
metadata:
labels:
app: demo-web
spec:
securityContext:
runAsNonRoot: true
fsGroup: 2000
containers:
- name: web
image: your-registry/demo-web:1.0.0
imagePullPolicy: IfNotPresent
ports:
- containerPort: 8080
resources:
requests:
cpu: "100m"
memory: "128Mi"
limits:
cpu: "500m"
memory: "512Mi"
securityContext:
privileged: false
allowPrivilegeEscalation: false
runAsUser: 1000
readOnlyRootFilesystem: true
capabilities:
drop:
- ALL
add:
- NET_BIND_SERVICE
seccompProfile:
type: RuntimeDefaultImplementation tips:
At image build, ensure app runs under non-root, read-only rootfs
Abstract template into Helm Chart or Kustomize Patch as org-wide baseline
Add template validation in CI (kube-score, polaris, kubescape) to prevent drift
4.2 Scenarios That Should Never Use Privileged Containers
Most business workloads don't need privileged:
Pure web/API services
Queue consumers, cron jobs, data processing workers
Most Job/CronJob
If teams habitually enable privileged: true or CAP_SYS_ADMIN for these, it usually means:
Image build laziness (e.g., writing temp files to root dir)
Debug convenience left open, never closed
Fix by adjusting image and app behavior , not by running with excessive rights.
Handling Policy-Business Conflicts & Gradual Tightening
Real-world issues:
Existing privileged Pods in legacy apps — blanket ban breaks production
Ops components (CNI, CSI, monitoring DaemonSets) need hostNetwork, hostPID, or privileged
Practical approach:
Discover first, then tighten : use kubectl or policy scanners to list all privileged containers; align with business owners; tier and plan remediation.
Namespace layering : business namespaces → enforce: restricted; platform/ops namespaces → enforce: baseline or custom policy.
Canary policy : start with warn / audit, observe alerts; tighten low-risk namespaces first.
Example: jq queries to find privileged containers and CAP_SYS_ADMIN:
# Find pods with privileged=true
kubectl get pods -A -o json |
jq -r '
.items[]
| select(
any(.spec.containers[]?; .securityContext.privileged == true)
or any(.spec.initContainers[]?; .securityContext.privileged == true)
)
| "\(.metadata.namespace)\t\(.metadata.name)"'
# Find pods with CAP_SYS_ADMIN
kubectl get pods -A -o json |
jq -r '
.items[]
| select(
any(.spec.containers[]?;
any(.securityContext.capabilities.add[]?; . == "SYS_ADMIN")
)
or any(.spec.initContainers[]?;
any(.securityContext.capabilities.add[]?; . == "SYS_ADMIN")
)
)
| "\(.metadata.namespace)\t\(.metadata.name)"'Best Practices Checklist
6.1 Policy Layer
Enforce restricted PodSecurity on business namespaces
Separate policy for ops namespaces, evaluate each privileged need
Use Kyverno/OPA to manage "deny privileged", "deny dangerous capabilities" rules
All policy changes go through change process, dry-run in non-prod first
6.2 Application & Image Layer
Build images with non-root user from the start
Apps use config/data dirs ( /app, /data), avoid writing root
Prefer read-only rootfs + mounted data volumes
Avoid running cluster ops (e.g., kubectl, iptables) inside app containers
6.3 Observability & Audit
Feed policy denial logs (Admission Webhook, Kyverno, API Server Audit) to central logging
Regularly scan for leftover privileged Pods, produce governance reports
Alert on privileged Pod creation in critical namespaces
Summary: Make "Enable Privileged" a High-Barrier Action
Container privileged mode is essentially amplified trust in the host. In multi-tenant cloud-native environments, it must shift from "casual debugging tool" to "rare, fully justified and approved capability."
One-sentence execution:
Use cluster policy to ban default privileged, use security baselines to tighten container permissions, use tooling and audit to raise the cost of "enabling privileged" high enough.
If your cluster still has many privileged: true business Pods, start today:
Full scan to see current state
Pilot restricted + policy engine in non-prod
Phased remediation plan to drive privileged containers to zero
When "no privileged" becomes the default, your Kubernetes cluster truly enters the secure cloud-native era.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Cilantro Loves Linux
Focused on Linux system operations and maintenance technology exchange, regularly publishing in-depth technical articles covering core areas such as system architecture, performance optimization, and security hardening. Whether you are a beginner or a seasoned expert, you can find valuable resources to enhance your skills and solve problems here. Follow us to explore the mysteries of Linux operations!
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
